AgentEvent variants were duplicated in PipelineEvent with `stage: String`
added, requiring a 130-line mechanical bridge to translate between them.
Collapse into a single `PipelineEvent::Agent { stage, event }` variant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 9e9f00828e4b
- LlmRetry: wrap agent session stream() with llm::retry, emit
AgentEvent::LlmRetry and forward to PipelineEvent::LlmRetry
- failure_class on StageFailed/StageCompleted: "transient" for
retry-eligible failures, "terminal" for final failures, None for success
- ParallelEarlyTermination: emit on fail_fast break with reason,
completed_count, and pending_count
- SubgraphStarted/SubgraphCompleted: boundary events with timing and
step count for sub-pipeline execution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 82c1bbcbe2f2
Embed the full Usage struct (with cache_read_tokens, cache_write_tokens,
reasoning_tokens) in AssistantMessage events instead of bare input/output
token fields. Add skip_serializing_if annotations to keep NDJSON clean.
Extend StageUsage with cache/reasoning aggregation. Track files touched
via write_file/edit_file tool call correlation in the backend bridge.
Update format functions, cost accumulator, and TypeScript types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2c15cd247556
Adds observability for skill expansion so CLI users and pipeline event
consumers know when a skill reference was matched and expanded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: d94221388541
Skills are markdown files with YAML frontmatter that define reusable
prompt templates (e.g., /commit, /review-pr). When a user references
/skill-name in their input, the skill template expands in place with
{{user_input}} receiving the remaining text.
- Add skills.rs with parse, expand, discover, and formatting functions
- Discover skills from ~/.attractor/skills/, <git-root>/.attractor/skills/,
and <git-root>/skills/ (overridable with --skills-dir CLI flag)
- Inject available skills into system prompt between project docs and
user instructions
- Expand skill references in session input before recording user turn
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2a8ed77f26c5
Use structured handoff-style prompt with explicit sections (Task & Goal,
Completed Work, Current State, Failed Approaches, Open Issues, Next Steps)
instead of generic summarizer prompt, improving context preservation across
compaction boundaries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2a12087def60
Decorator that tracks which files the agent has read (via read_file or
grep) and returns an error when writing to an existing file that hasn't
been read first. Prevents the model from hallucinating file contents and
blindly overwriting working code. New files are always allowed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: a565c5a5e2f9
When context usage exceeds the configurable threshold (default 80%), older
turns are summarized via a non-streaming LLM call and replaced with a single
System turn. Compaction is non-fatal — errors are emitted as AgentEvent::Error
and the session continues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 18435f31db91
Restructures agent events from misaligned EventKind+EventData pair into flat
AgentEvent enum, enriches AssistantMessage with model/token/tool_call data,
adds 8 new PipelineEvent variants (Prompt, AssistantMessage, ToolCallStarted,
ToolCallCompleted, SessionError, ContextWindowWarning, LoopDetected,
TurnLimitReached), and forwards agent session events to the pipeline emitter
in AgentBackend so they appear in progress.ndjson.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: d59f9e69008a
Removed the workspace-level clippy lint config that enabled all, pedantic, nursery,
and cargo lint groups. Removed all #[allow(clippy::...)] annotations that were only
needed to suppress those extra lints, and fixed the few default clippy warnings that
were uncovered.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thread CancellationToken into tool executors and exec_command so that
running processes are killed (SIGTERM -> 2s -> SIGKILL) when abort fires,
rather than only checking the flag between LLM calls. Key changes:
- ToolExecutor type gains CancellationToken parameter
- ExecutionEnvironment::exec_command gains cancel_token param
- LocalExecutionEnvironment uses tokio::select! (completion vs timeout
vs cancellation) with extracted sigterm_then_kill helper
- DockerExecutionEnvironment uses same select! pattern
- Session replaces Arc<AtomicBool> with CancellationToken, passes
child_token() per tool call
- Shell tool forwards cancel token to exec_command
- CLI SIGINT handler calls cancel_token.cancel()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Stylesheet: add bare-word Shape selector (specificity between Universal and Class)
- LLM: apply per_step timeout to connection and total timeout to stream (Section 4.7)
- Interviewer: add MultiSelect question type alongside MultipleChoice
- Session: move SessionStart/SessionEnd to initialize()/close(), deduplicate close logic
- Engine: return Ok(fail outcome) instead of error when goal gate unsatisfied with no retry_target
- Docker: mark Docker-dependent tests with #[ignore]
- Validation: add extensive unit test coverage for all rule types
- Integration: update tests to match engine/fidelity changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Break out of streaming loop on abort and drop the stream before emitting
SessionEnd to properly cancel the HTTP connection
- Emit ToolCallOutputDelta events for tool call results in both sequential
and parallel execution paths
- Retry on StageStatus::Fail in addition to Retry in pipeline engine
- Set preferred_label on WaitHumanHandler choice outcomes
- Enforce exactly one terminal node in pipeline validation
- Downgrade unreachable node diagnostic from Error to Warning
- Update context window test to match 1M token limit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Strip the CWD prefix from string arguments in format_tool_args so tool
call output shows relative paths instead of absolute ones.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Anthropic API requires a `signature` field on thinking blocks when
they are sent back in conversation history. Previously, thinking blocks
were stored as plain text in Turn::Assistant.reasoning, losing the
signature. Now Thinking/RedactedThinking content parts are preserved
in provider_parts (which retains signatures), and the lossy
reconstruction path is skipped when provider_parts already contains
thinking blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch default model from claude-sonnet-4-5 to claude-opus-4-6 across
run and serve commands. Enable the 1M token context window via the
context-1m-2025-08-07 beta header for opus-4-6 requests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updates the default Gemini model from gemini-3-pro-preview to
gemini-3.1-pro-preview across agent, attractor, and ullm CLIs.
Adds "Using model:" output to stderr in both agent and ullm CLIs
so users can see which model is being used.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updates the default Anthropic model from claude-sonnet-4-5 to
claude-opus-4-6 and replaces beta headers with adaptive thinking
provider options for 4.6 models.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements ExecutionEnvironment trait backed by Docker containers via
bollard. Host working directory is bind-mounted; all file ops, commands,
grep, and glob execute inside the container via docker exec. Extracts
shared format_lines_numbered() helper from LocalExecutionEnvironment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Long Opus responses hit the 120s request timeout with complete(). With
stream(), the request timeout only covers initial connection + first
chunk, then the 30s stream_read timeout guards against stalls between
chunks. Also emits AssistantTextDelta events during streaming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Requests were always sent with max_tokens: None, which defaulted to
4096 in the Anthropic provider, causing large outputs to be truncated.
Now build_request() looks up the model's max_output from the catalog
and passes it through, giving each model its full output capacity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move ANSI Styles struct from agent/cli.rs into a shared terminal crate
so both binaries can use it. Add green and yellow color codes. Prettify
all attractor CLI output: bold headers, colored diagnostics by severity,
green/red status, yellow warnings, dimmed event details, and styled
interviewer prompts. Move pipeline status output from stdout to stderr.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Styles struct that pre-resolves ANSI escape codes based on whether
stderr is a TTY. Tool calls show as "● tool_name(args)" with bold+cyan
names, errors use red "✗", summaries are dimmed, and debug/verbose
middleware output is styled. No ANSI codes emitted when piped.
Also passes tool call arguments through to EventData::ToolCall so the
event handler can format them inline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agent-cli binary was a thin wrapper over the agent library with
nothing else depending on it. Moving it into the agent crate as a
`pub mod cli` with a `[[bin]]` entry reduces workspace complexity
and follows the attractor crate pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agent's Turn::Assistant decomposed responses into text, tool_calls,
and reasoning fields, discarding ContentPart::Other items. This lost
OpenAI reasoning items needed for Responses API round-tripping.
Add provider_parts field to Turn::Assistant to carry opaque content
parts through the history, and emit them first in convert_to_messages
so they precede function_call items as the API requires.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce `ToolApprovalFn` callback in `SessionConfig` to gate tool
execution by permission level. Create `agent-cli` crate as a thin CLI
binary wrapping `Session` with provider/model resolution, permission
model (read-only/read-write/full), interactive approval prompts,
real-time event rendering, debug middleware, and SIGINT handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `extended-thinking-2025-04-14` and `max-tokens-3-5-sonnet-2025-04-14`
beta headers are no longer accepted by the Anthropic API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>