Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

Commit 4de6e7a

Browse files
committed
feat: Release v1.8.0 - Context Management and Dependency Refactor
- Context: Added per-provider 'context_limit' and automatic history pruning/distillation to prevent failover loops. - Config: Added '/config budget' command and '/config set ... context_limit' support. - Fix: Resolved critical code duplication in OpenAICompatibleProvider causing double responses. - Fix: Fixed UI buffer duplication during retry/failover events. - Refactor: Consolidated dependencies into pyproject.toml, simplifying requirements.txt and CI/CD. - Tests: Converted verification scripts to pytest and achieved 100% pass rate. - Docs: Updated documentation for context management and new commands.
1 parent ca09180 commit 4de6e7a

16 files changed

Lines changed: 318 additions & 210 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ jobs:
2020
- name: Install dependencies
2121
run: |
2222
python -m pip install --upgrade pip
23-
pip install -e .
24-
pip install pytest pytest-asyncio beautifulsoup4 requests pydantic-settings
23+
pip install -e ".[dev]"
2524
26-
- name: Run unit tests
25+
- name: Run all tests
2726
run: |
28-
pytest tests/test_components.py tests/test_v1_2_features.py tests/test_web_v1_3.py
27+
pytest tests/
2928
3029
- name: Set up Docker
3130
uses: docker-practice/actions-setup-docker@master

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
# Plexir 🌌
1+
# Plexir
22

33
**Plexir** is a modular, secure, and beautiful AI-powered terminal workspace. Designed for developers who live in the CLI, it combines multi-provider LLM orchestration, advanced agentic tools, and a secure, persistent Docker sandbox into a single keyboard-centric interface.
44

55
![Plexir UI](assets/image.png)
66

7-
[![Version](https://img.shields.io/badge/version-1.7.0-blue.svg)](https://github.com/pomilon/plexir)
7+
[![Version](https://img.shields.io/badge/version-1.8.0-blue.svg)](https://github.com/pomilon/plexir)
88
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
99

1010
---
1111

12-
## 🚀 Features
12+
## Features
1313

1414
- **Multi-Provider Failover**: Seamlessly switch between Gemini, Groq, Cerebras, and OpenAI-compatible APIs. If one model hits a quota, Plexir automatically fails over to the next in your priority list.
1515
- **Economics & Metrics**: Real-time **Token Tracking** and **Cost Estimation** in the sidebar. Set a session budget via `/config budget` to prevent runaway costs.
@@ -18,6 +18,7 @@
1818
- **Persistent Memory Bank**: Semantic storage (`chromadb`) for long-term facts using `/memory save`.
1919
- **Rolling Summarization**: Automatically condenses long histories.
2020
- **Message Pinning**: `/session pin` ensures critical context is never lost.
21+
- **Context Window Management**: Intelligent token counting and history pruning ensures conversations never exceed model limits, preventing failover loops.
2122
- **Persistent Docker Sandbox**: Launch with `--sandbox` to give the AI its own persistent Linux "computer." All tools (file system, git, shell) are automatically redirected inside the container.
2223
- **Deep MCP Integration**: Fully supports **Model Context Protocol (MCP)**, including dynamic discovery of tools, **Resources**, **Resource Templates**, and **Prompts** from MCP servers.
2324
- **Smart Agent Capabilities**:
@@ -42,7 +43,7 @@
4243

4344
---
4445

45-
## 📦 Installation
46+
## Installation
4647

4748
### Prerequisites
4849
- Python 3.10 or higher.
@@ -61,7 +62,7 @@
6162

6263
---
6364

64-
## 🛠 Usage
65+
## Usage
6566

6667
Start Plexir from any terminal:
6768
```bash
@@ -90,7 +91,7 @@ plexir --sandbox
9091

9192
---
9293

93-
## ⚙️ Configuration
94+
## Configuration
9495

9596
Plexir stores its configuration in `~/.plexir/config.json`. You can manage this file manually or using the in-app `/config` commands.
9697

@@ -101,7 +102,7 @@ Example failover hierarchy:
101102

102103
---
103104

104-
## 📄 Documentation
105+
## Documentation
105106

106107
Detailed guides are available in the `docs/` directory:
107108
- [Getting Started](docs/getting_started.md)
@@ -113,14 +114,14 @@ Detailed guides are available in the `docs/` directory:
113114

114115
---
115116

116-
## 🤝 Contributing
117+
## Contributing
117118

118119
Contributions are welcome! Please see our [Contributing Guidelines](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md) for more details.
119120

120-
## 🛡️ Security
121+
## Security
121122

122123
If you discover a security vulnerability, please see our [Security Policy](SECURITY.md).
123124

124-
## ⚖️ License
125+
## License
125126

126-
Plexir is released under the [MIT License](LICENSE).
127+
Plexir is released under the [MIT License](LICENSE).

docs/COMMANDS.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This document provides a comprehensive guide to all available slash commands in
44

55
---
66

7-
## 🚀 General Commands
7+
## General Commands
88

99
### `/help`
1010
Displays a summary of all primary slash commands.
@@ -23,7 +23,7 @@ Exits the Plexir application cleanly, stopping the sandbox if it's running.
2323

2424
---
2525

26-
## ⚙️ Configuration (`/config`)
26+
## Configuration (`/config`)
2727

2828
Manages providers, tool settings, and application preferences.
2929

@@ -33,11 +33,16 @@ Shows the current provider failover order, tool configurations, and other app se
3333
#### `/config set <provider_name> <key> <value>`
3434
Updates a specific property for a provider.
3535
- **`<provider_name>`**: The name of the provider (e.g., `"Gemini Primary"`). Use quotes if it contains spaces.
36-
- **`<key>`**: The property to change (`api_key`, `model_name`, `type`, `base_url`).
36+
- **`<key>`**: The property to change (`api_key`, `model_name`, `type`, `base_url`, `context_limit`).
3737
- **`<value>`**: The new value.
38-
- **Example**: `/config set "Gemini Primary" api_key ghp_...`
38+
- **Example**: `/config set "Gemini Primary" context_limit 50000`
3939
- **Example**: `/config set "Groq Backup" model_name llama3-70b-8192`
4040

41+
#### `/config budget <amount>`
42+
Sets a maximum dollar amount for the current session to prevent runaway costs.
43+
- **Example**: `/config budget 0.50`
44+
- **Example**: `/config budget 0` (disables limit)
45+
4146
#### `/config tool <domain> <key> <value>`
4247
Sets a configuration value for a specific tool suite. This is how you provide tokens for external services.
4348
- **`<domain>`**: The tool domain (e.g., `git`, `github`).
@@ -67,7 +72,7 @@ Changes the failover priority of a provider.
6772

6873
---
6974

70-
## 💾 Session Management (`/session`)
75+
## Session Management (`/session`)
7176

7277
Saves and loads chat histories.
7378

@@ -88,7 +93,7 @@ Deletes a saved session file.
8893

8994
---
9095

91-
## 📹 Macro Management (`/macro`)
96+
## Macro Management (`/macro`)
9297

9398
Records and plays back sequences of commands and prompts.
9499

@@ -108,4 +113,4 @@ Lists all saved macros.
108113

109114
#### `/macro delete <name>`
110115
Deletes a saved macro.
111-
- **Example**: `/macro delete old-macro`
116+
- **Example**: `/macro delete old-macro`

docs/configuration.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ Instead of plain text, you can use:
2626
- `env:VARIABLE_NAME`: Read from environment variables.
2727
- `keyring:username`: Read from the system keyring (service: `plexir`).
2828

29+
## Context Management
30+
31+
Plexir automatically manages the context window to prevent model errors when conversations get too long.
32+
33+
### Automatic Limits
34+
Plexir comes with pre-configured token limits for popular models (e.g., 2M tokens for Gemini 1.5 Pro, 128k for GPT-4o). When the conversation history exceeds this limit, Plexir will:
35+
1. **Preserve** the most recent messages.
36+
2. **Preserve** system instructions.
37+
3. **Summarize/Distill** the older parts of the conversation to save space while retaining context.
38+
39+
### Manual Configuration (`context_limit`)
40+
You can override the default limit for any provider. This is useful for:
41+
- Testing how models behave with shorter context.
42+
- Forcing stricter limits on "Preview" models to save costs.
43+
44+
To set a strict 50,000 token limit on a provider:
45+
```bash
46+
/config set "Gemini Primary" context_limit 50000
47+
```
48+
*Set to `0` or `null` to use the model's default.*
49+
2950
## Failover & Retries
3051

3152
Plexir manages providers using a priority order defined in your config.
@@ -87,4 +108,4 @@ To prevent unexpected costs during long sessions, you can set a maximum dollar a
87108
*Set to `0` to disable the limit.*
88109

89110
### View current usage
90-
Usage metrics (Tokens and Estimated Cost) are always visible in the **System Status** sidebar.
111+
Usage metrics (Tokens and Estimated Cost) are always visible in the **System Status** sidebar.

docs/memory.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Plexir uses advanced techniques to manage long-running conversations, ensuring the model remains coherent even as the history grows.
44

5-
## 🧠 Persistent Memory Bank (New in v1.7)
5+
## Persistent Memory Bank (New in v1.7)
66

77
Plexir now includes a **Long-Term Memory** system powered by `chromadb`. This allows the agent to store and recall specific facts across different sessions.
88

@@ -20,15 +20,15 @@ You can prompt the agent to remember things directly:
2020
Or ask it to recall:
2121
> "Where did I say my keys were?"
2222
23-
## 🔄 Rolling Summarization
23+
## Rolling Summarization
2424

2525
When a conversation history becomes too large (exceeding 40 messages), Plexir automatically triggers **Rolling Summarization**.
2626

2727
1. **How it works**: Plexir identifies older, unpinned messages and uses the primary LLM to condense them into a concise "BACKGROUND SUMMARY."
2828
2. **Context Preservation**: This summary is injected at the start of the conversation, allowing the model to remember high-level decisions and context while clearing out detailed token-heavy noise.
2929
3. **Automatic**: This happens in the background without user intervention.
3030

31-
## 📌 Message Pinning
31+
## Message Pinning
3232

3333
You can manually protect critical messages from being summarized or pruned using **Context Pinning**.
3434

@@ -44,6 +44,6 @@ Use the `/session pin` command followed by the message number (visible in the hi
4444
/session unpin 5
4545
```
4646

47-
## 🧠 Distillation (Failover)
47+
## Distillation (Failover)
4848

49-
During a **Provider Failover** (e.g., Gemini Primary hitting a quota), Plexir uses a "Distillation" process to transfer only the most essential recent context to the backup provider. This ensures a smooth transition with minimal latency and token waste.
49+
During a **Provider Failover** (e.g., Gemini Primary hitting a quota), Plexir uses a "Distillation" process to transfer only the most essential recent context to the backup provider. This ensures a smooth transition with minimal latency and token waste.

docs/sandbox.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ If you encounter issues with the sandbox:
3131
```bash
3232
docker stop plexir-persistent-sandbox
3333
docker rm plexir-persistent-sandbox
34-
```
34+
```

docs/tools.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ Executes Python code in an isolated Docker container. This is useful for perform
6565
## Critical Actions & HITL
6666
Tools marked as **Critical** in the table above will trigger a **Human-in-the-Loop (HITL)** confirmation dialog in the TUI.
6767
* **Visual Diffs:** For `write_file` and `edit_file`, the confirmation dialog displays a color-coded diff of the proposed changes.
68-
* You must manually click **Confirm** before the action is executed.
68+
* You must manually click **Confirm** before the action is executed.

plexir/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.7.0"
1+
__version__ = "1.8.0"

plexir/core/config_manager.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class ProviderConfig(BaseModel):
6060
"auto",
6161
description="Authentication mode: 'auto', 'api_key', or 'oauth' (Gemini only)."
6262
)
63+
context_limit: Optional[int] = Field(None, description="Max input tokens. If None, uses model default.")
6364

6465
def get_api_key(self) -> Optional[str]:
6566
"""Resolves the API key securely."""
@@ -121,6 +122,34 @@ class AppConfig(BaseModel):
121122
},
122123
description="Pricing map: model -> (prompt_price, completion_price) per 1M tokens."
123124
)
125+
model_context_windows: Dict[str, int] = Field(
126+
default_factory=lambda: {
127+
# --- Google Gemini Series ---
128+
"gemini-3-pro-preview": 2000000,
129+
"gemini-3-flash-preview": 1000000,
130+
"gemini-2.5-pro": 2000000,
131+
"gemini-2.5-flash": 1000000,
132+
"gemini-2.5-flash-lite": 1000000,
133+
134+
# --- Anthropic Claude Series ---
135+
"claude-4.5-sonnet": 200000,
136+
"claude-4.5-haiku": 200000,
137+
"claude-4-opus": 200000,
138+
139+
# --- OpenAI Series ---
140+
"gpt-4o": 128000,
141+
"gpt-4o-mini": 128000,
142+
"gpt-oss-120b": 8192,
143+
144+
# --- Specialized ---
145+
"deepseek-v3": 64000,
146+
"deepseek-reasoner": 64000,
147+
"llama-3.3-70b-versatile": 128000,
148+
"llama3.1-8b": 8192,
149+
"llama3.1-70b": 8192,
150+
},
151+
description="Default context window sizes (in tokens) for known models."
152+
)
124153
macros: Dict[str, List[str]] = Field(default_factory=dict)
125154
tool_configs: Dict[str, Dict[str, str]] = Field(default_factory=dict)
126155

0 commit comments

Comments
 (0)