Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/anthropic-role-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"trae-agent": patch
---

### Bug Fixes

- **Anthropic Role Alternation**: Add `_normalize_alternation()` to merge consecutive same-role messages before sending — prevents Anthropic API 400 errors when tool call/result sequences fragment the `user`/`assistant` alternation pattern.
69 changes: 69 additions & 0 deletions .changeset/compression-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
"trae-agent": minor
---

### New Features

- **Micro-Compression for OrchestratorAgent**: PLANNING / CODING / REVIEWING
phases now integrate micro-compression with dual-trigger model:
- SEMANTIC: natural-boundary keywords ("step completed", "moving on",
"summarize", "next step", "here is a summary")
- FORCED: every 10 steps or 3 consecutive tool errors
- **Safe atomic cut** (`find_safe_cut`): backtracking Algorithm B guarantees
`tool_call` / `tool_result` atomic pairs are never split during compression,
preventing 400 errors from providers that validate call chains.
- **Lazy-load refs**: tool outputs exceeding 1024 characters are replaced
with `[lazy-ref:hash]` placeholders in compressed summaries.

### Security

- **`FileBackend` path traversal prevention**: resolved path is validated
to ensure it stays within the workspace directory; `read()` uses
`try/except FileNotFoundError` instead of TOCTOU-prone `exists()` check.
- **Markdown injection prevention**: `_escape_md_lines()` escapes `## `-prefixed
lines in LLM-generated content to prevent section-boundary injection.
- **Sensitive data TODO**: explicit hook marker for future content scrubber
integration in the summarization path.
- **`CompressionContext.last_message`**: new field enables semantic trigger
evaluation from the last assistant response text.

### Refactoring

- **`BaseAgent._compress_messages`** delegates to `MicroCompressionStrategy`
with proper `last_compression_step` state tracking (方案 B), eliminating
the per-call instantiation overhead and redundant step-interval checks.
Includes `_reset_llm_client_history()` call for client-side state consistency.
(Addresses findings F-1, F-4, F-5.)
- **`MicroCompressionStrategy`** moved to `BaseAgent.__init__` as a shared
singleton instance (matching `OrchestratorAgent.__init__` pattern).

### Bug Fixes

- **`MicroCompressionStrategy.compress()` report trigger**: now dynamically
detects SEMANTIC vs FORCED trigger via `_detect_trigger()`, replacing the
previously hardcoded `CompressionTrigger.FORCED`.
- **`MicroCompressionStrategy.should_compress()`**: dual-trigger evaluation
(semantic OR forced) instead of forced-only.

### Testing

- `tests/agent/test_orchestrator_compression.py` — 4 tests (TC-1–TC-4)
covering step-interval trigger, consecutive error trigger, client history
reset, and no-trigger boundary condition.
- `tests/test_phase2_compression.py` — 55→87 tests (32 new) covering
`find_safe_cut` edge cases, `from_markdown` error recovery,
`MicroCompressionStrategy` semantic/forced triggers, `_escape_md_lines`.
- `tests/agent/test_context_compression.py` — updated 2 tests for unified
`MicroCompressionStrategy` format.

### Design Decisions

- **`BaseAgent._compress_messages` intentional limitations**: The single-phase
ReAct loop deliberately passes `consecutive_errors=0` and `last_message=None`
to `CompressionContext`. Error tracking is the `OrchestratorAgent`'s
responsibility (it has per-step visibility into tool results). Semantic
triggering requires `last_assistant_message` capture which the
`OrchestratorAgent`'s `_run_phase()` maintains explicitly between iterations.
The base agent compresses only on step-interval forced triggers — any
richer triggering belongs in the orchestrator, which has the necessary
execution context.
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
10 changes: 10 additions & 0 deletions .changeset/deepseek-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"trae-agent": minor
---

### New Features

- **DeepSeek Provider**: Add `DeepSeekClient` via OpenAI-compatible base with default endpoint `https://api.deepseek.com`.
- Supports V3 (`deepseek-chat`) and R1/V4 (`deepseek-reasoner`) models.
- `SupportsToolCalling` auto-detection: enabled for non-reasoning models, disabled for R1.
- Registered in `LLMProvider` enum and `LLMClient` dispatch.
41 changes: 41 additions & 0 deletions .changeset/fuzzy-search-replace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
"trae-agent": minor
---

## Tool Schema — Minor expansion

### New commands

- **`search_replace`** — A SEARCH/REPLACE edit command using a fuzzy matching engine. Uses `difflib.SequenceMatcher` sliding-window search with context-based disambiguation. Supports three match modes:
- `auto` (default): exact match first, falls back to fuzzy
- `exact`: strict exact match only, no fallback
- `fuzzy`: skip exact, directly use fuzzy matching

- **`write`** — Full-file overwrite command (replaces entire file contents atomically).

### Schema changes

Added parameters:
| Command | Parameter | Type | Description |
|---------|-----------|------|-------------|
| `search_replace` | `search_block` | `string` | The text to search for |
| `search_replace` | `replace_block` | `string` | Replacement text |
| `search_replace` | `match_mode` | `"auto" \| "exact" \| "fuzzy"` | Matching strategy |

### Deprecations

- **`str_replace`** — Kept for backward compatibility but deprecated; callers should migrate to `search_replace`.

### Internal improvements

- **Fuzzy matching engine** (`edit_utils.py`):
- `normalize_whitespace()` — Normalizes tabs→4 spaces, CRLF→LF, strips trailing whitespace, collapses 3+ blank lines→2
- `find_similar_regions()` — Sliding-window `SequenceMatcher` search; uses step=3 for files >1 MB, skips entirely for files >10 MB
- `disambiguate_by_context()` — Resolves multiple fuzzy candidates by comparing surrounding context lines with search-block boundaries
- `fuzzy_match_and_replace()` — Orchestrates exact→fuzzy→replace pipeline; returns line-count deltas

- **Line offset tracker** — `TextEditorTool._line_offset_tracker` maps old line numbers to new positions after edits, so `view_range` stays correct across multiple modifications.

- **Bug fix**: `view_range` with `final_line=-1` (view-to-end sentinel) no longer incorrectly adjusted by line offset tracker.

- **Atomic file writes**: All file modifications use `tempfile.mkstemp(dir=parent)` + `os.replace` for crash-safe writes.
66 changes: 66 additions & 0 deletions .changeset/orchestrator-agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
"trae-agent": minor
---

## Phase 4 — OrchestratorAgent: Multi-Phase Execution Architecture

### Breaking Changes

- **`AgentType` enum**: New member `OrchestratorAgent = "orchestrator_agent"`. Consumers that match exhaustively on `AgentType` must add a case.
- **`AgentStepState` enum**: 5 new values — `PLANNING`, `CODING`, `REVIEWING`, `WAITING`, `RETRYING` (10 total). Consumers that match exhaustively must add cases.
- **`BaseAgent`**:
- New `allow_mcp_servers: list[str] | None` attribute (default `None`).
- New `initialise_mcp()` async method (no-op base, overridden by `TraeAgent`).
- New abstract method pattern: `cleanup_mcp_clients()` already existed; `initialise_mcp()` added alongside it for symmetry.

### New Features

- **`OrchestratorAgent`** (`trae_agent/agent/orchestrator_agent.py`):
- 3-phase execution flow: `PLANNING → CODING → REVIEWING`
- Each phase runs an isolated ReAct loop with:
- Fresh message context (no cross-phase message bleed)
- Per-phase system prompt (`PLANNER_SYSTEM_PROMPT`, `CODER_SYSTEM_PROMPT`, `REVIEWER_SYSTEM_PROMPT`)
- Per-phase tool permission isolation via `PHASE_TOOL_NAMES` dict
- Structured text handoff between phases (no raw message sharing)
- Phase completion signals:
- PLANNING: "plan completed" in LLM response content
- CODING: `task_done` tool call detected
- REVIEWING: `**Pass**`, `**Fail**`, or `## Review Verdict` in content
- `MAX_STEPS_PER_PHASE = 30` inner-loop bound
- Error handling: LLM exceptions caught per-phase, returned as error string (execution continues to remaining phases)

- **`Agent` facade** (`trae_agent/agent/agent.py`):
- Routes `AgentType.OrchestratorAgent` to `OrchestratorAgent` via match/case
- `self.agent` type widened from `TraeAgent` to `BaseAgent`

- **Context compression** (`BaseAgent._compress_messages`):
- Deterministic summarization triggered at `step_number % 10 == 0` AND `len(messages) > 30`
- Preserves: system prompt + last 15 messages verbatim
- Compresses middle section: extracts tool result outcomes (success/failure) and assistant "plan"/"approach" content
- Injects `Context Summary` message at position 1

- **LLM client history reset** (`BaseAgent._reset_llm_client_history`):
- Resets `self._llm_client.client.message_history = []` after compression
- Wrapped in `contextlib.suppress(AttributeError)` for client variants without `message_history`

### Bug Fixes

- **`TraeAgent.reflect_on_result`**: Replaced bare `return None` with error-specific reflection guidance strings (timeout, not found, permission denied, default)
- **`BaseAgent._tool_call_handler`**: Fixed handling of `None` and empty `tool_calls`:
- `None` (no tool_call field): if substantive content (>20 chars), treat as thinking; else nudge LLM
- Empty list: if content exists, pass through; else push "not completed" message
- **`BaseAgent._run_llm_step`**: Fixed `tool_calls = getattr(llm_response, 'tool_calls', [])` — was returning `None` from Anthropic responses, now correctly defaults to empty list

### Tool Isolation

- **`PHASE_TOOL_NAMES`** per phase:
- PLANNING: `str_replace_based_edit_tool`, `sequentialthinking` (read-only, no bash)
- CODING: All `TraeAgentToolNames` (full tool access including `bash`, `task_done`)
- REVIEWING: `str_replace_based_edit_tool`, `bash`, `sequentialthinking` (no `task_done`)

### Testing

- `tests/agent/test_agent_basics.py` — 8 tests for `AgentStepState` new values
- `tests/agent/test_context_compression.py` — 11 tests covering threshold, preservation, failure summaries, client history reset
- `tests/agent/test_orchestrator_agent.py` — 23 tests covering phase constants, completion detection, tool isolation, context handoff, full 3-phase execution, error handling, AgentType registration
- `tests/agent/test_trae_agent.py` — 7 existing tests (no regressions)
9 changes: 9 additions & 0 deletions .changeset/reasoning-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"trae-agent": minor
---

### New Features

- **Reasoning Content Tracking**: `LLMMessage` carries an optional `reasoning_content: str | None` field for chain-of-thought tracing in reasoning models (DeepSeek R1/V4, OpenAI o1/o3).
- `OpenAICompatibleClient` extracts `reasoning_content` from both streaming and non-streaming responses.
- `_is_reasoning_model()` auto-detects o1/o3/R1 models for correct token parameter selection (`max_completion_tokens` vs `max_tokens`).
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,4 @@ trae_config.yaml

# Patch selection python binary
py312/
/review/
10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions .idea/trae-agent.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading