Commit graph

65 commits

Author SHA1 Message Date
Bryan Helmkamp
b11c92bf66 Redesign compact and summary:high preamble rendering
Compact mode now renders nested-bullet summaries with handler-specific
sub-items (script: command/stdout/stderr; codergen: model/tokens/files)
under a ## Completed stages heading. Summary:high renders per-stage
## Stage sections with full detail and a ## Current context table.

Also captures script.stderr in context_updates for both success and
failure branches, and improves context filtering across all modes to
exclude engine keys (graph.*, thread.*, response.*, last_stage, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:26:07 -05:00
Bryan Helmkamp
92a4c5e506 Inject fidelity preamble into LLM prompts and reuse sessions for full fidelity
CodergenHandler now reads `current.preamble` from context and prepends it
to the prompt before dispatching to backends. For `full` fidelity the engine
sets preamble to empty, so the prepend is a no-op. This ensures downstream
LLM nodes see prior node outputs (e.g. script stdout) without any trait
changes.

AgentBackend gains a `sessions` cache keyed by thread ID. When fidelity is
`full` and a thread_id is present, sessions are reused across nodes so the
LLM sees the full conversation history. Usage aggregation only counts turns
added after the reuse point to prevent double-counting. Failed sessions are
dropped rather than cached.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:27:36 -05:00
Bryan Helmkamp
38caf9166f Fix pre-existing lint warnings
Remove unused set_event_callback on MockExecutionEnvironment and
replace always-true u64 >= 0 comparisons with is_u64() checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:09:48 -05:00
Bryan Helmkamp
f81113d71c Add backwards compatibility for tool → script rename
Register "tool" as an alias for ScriptHandler, fall back to
tool_command attribute, dual-write tool.output context key, and
add "tool" to known handler types for validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:07:20 -05:00
Bryan Helmkamp
7ad750c5b6 Rename tool handler to script handler and add language attribute
Rename the entire "tool" concept to "script": ToolHandler → ScriptHandler,
tool_command attribute → script, tool.output → script.output, and all
related artifact filenames. Add a language attribute (shell | python,
default shell) so script nodes can run Python via python3 -c natively.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:50:39 -05:00
Bryan Helmkamp
b51e387885 Fix Daytona sandbox: rewrite SSH URLs to HTTPS and generate unique names
SSH git URLs (git@github.com:...) cause "invalid auth method" errors
since Daytona uses HTTPS token auth. Added ssh_url_to_https() to
convert them before cloning. Also removed the static sandbox name
config field and auto-generate unique names with timestamps to prevent
"already exists" errors on repeated runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 00:23:54 -05:00
Bryan Helmkamp
5504660379 Add more tests for daytona 2026-02-26 22:10:43 -05:00
Bryan Helmkamp
05903892f6 Add execution environment and setup command observability events
Introduces ExecutionEnvEvent enum (15 variants covering lifecycle, Docker
image pull, Daytona snapshot, and git clone operations) with callback
injection on all execution environment implementations. Adds
PipelineEvent::ExecutionEnv wrapper and Setup* variants for setup command
tracking. Wires callbacks in run.rs so exec env and setup events flow
through the pipeline event emitter to stderr and progress.ndjson.

Also changes PipelineEngine::new to accept Arc<EventEmitter> so the
emitter can be shared with exec env callbacks before engine construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 22:09:41 -05:00
Bryan Helmkamp
35bccb5d36 Share one execution environment per pipeline run
Instead of creating a separate Docker/Daytona sandbox per stage inside
AgentBackend::run(), create the execution environment once in
run_command(), initialize it, run setup commands, and pass it through
EngineServices to all handlers. This lets multi-stage pipelines share
file changes across nodes and avoids redundant container/sandbox creation.

Key changes:
- Add execution_env field to EngineServices
- Add execution_env param to CodergenBackend::run() trait method
- Remove env creation, setup_commands, daytona_config from AgentBackend
- Lift env lifecycle (create, initialize, setup, cleanup) to run_command()
- Use scopeguard for cleanup on error/panic paths
- Update PipelineEngine constructors to accept execution_env

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 92cbe0d3c133
2026-02-26 21:27:42 -05:00
Bryan Helmkamp
2253259ec5 Add [execution] section to TOML task config for execution environment
Allow specifying execution environment (local/docker/daytona) in TOML
task configs so pipelines are self-contained. CLI flag takes precedence
over TOML, which takes precedence over the default (local).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 600b7720bbda
2026-02-26 18:53:51 -05:00
Bryan Helmkamp
8d593ff68e Add Daytona execution environment and replace --docker with --execution-env
Replace the `--docker` boolean flag with `--execution-env <local|docker|daytona>`
to support three execution environments. The new `DaytonaExecutionEnvironment`
uses the Daytona cloud sandbox SDK to run agent tools remotely, auto-cloning the
current git repo into the sandbox via `gh auth token` credentials.

Setup commands from TOML task configs now run inside the execution environment
(via `exec_command` after `initialize()`) rather than locally, so they work
correctly for both Docker and Daytona sandboxes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 306da8ff6de1
2026-02-26 18:35:33 -05:00
Bryan Helmkamp
93ab7b8dbd Add [vars] expansion in TOML task configs for DOT source parameterization
Allows users to define variables in their TOML task config that get
expanded as $name placeholders in the DOT file before parsing. This
enables parameterized pipelines without duplicating DOT files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 293af13a0e54
2026-02-26 13:58:27 -05:00
Bryan Helmkamp
0f9e31204f Add TOML-based task config for attractor run
Support `attractor run task.toml` as an alternative to `.dot` files.
Auto-detects format by file extension. TOML bundles pipeline config
(graph path, model, setup commands, working directory) into a single
file with precedence: CLI flag > TOML > DOT graph attrs > defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 8744d57d6053
2026-02-26 13:37:08 -05:00
Bryan Helmkamp
5198a29a62 Close logging gaps vs Kilroy: panic.txt, graph.dot, run.pid, final.json, parallel_results.json, provider_used.json, api_request.json, api_response.json
Adds 8 log file outputs to reach parity with Kilroy's per-node and
run-level logging:

- panic.txt: written on handler panic with the panic message
- graph.dot: DOT source saved to logs dir at run start
- run.pid: process ID saved to logs dir at run start
- final.json: run outcome (status, duration, failure_reason) written
  after engine completes, before error propagation
- parallel_results.json: branch results written per parallel node
- provider_used.json: mode/provider/model written by AgentBackend
- api_request.json: serialized LLM request in one_shot mode
- api_response.json: serialized LLM response in one_shot mode

Adds stage_dir parameter to CodergenBackend trait methods so backends
can write artifacts to the correct per-node log directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: a3934db0f826
2026-02-25 19:44:18 -05:00
Bryan Helmkamp
db85f7b0bd Add per-node log files to ToolHandler for Kilroy parity
ToolHandler now writes 4 files to {logs_root}/{node_id}/:
- tool_invocation.json (command, timeout_ms) before execution
- stdout.log and stderr.log after command completes
- tool_timing.json (duration_ms, exit_code, timed_out) after execution

The timeout branch also writes tool_timing.json with timed_out: true
and exit_code: null. Inlined process_output since stdout/stderr are
now needed in the surrounding scope for file writes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 6c9fde8bdc72
2026-02-25 19:19:39 -05:00
Bryan Helmkamp
650567a1cf Add codergen_mode (one_shot | agent_loop) to support single-call LLM nodes
Enables simple generation nodes (summarization, classification, routing)
without the overhead of a full agent session. Nodes default to agent_loop
when the attribute is absent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 1574218eca96
2026-02-25 19:12:57 -05:00
Bryan Helmkamp
1e3726b7f3 Add missing data to agent events and cost tracking in pipeline logs
Enrich three AgentEvent variants with payload data (UserInput.text,
TurnLimitReached.max_turns, SteeringInjected.text) and forward
UserInput/SteeringInjected to the pipeline event stream. Add cost
field to StageUsage (computed from model pricing catalog) and
total_cost to PipelineCompleted (summed from stage outcomes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: adb2363c9ec4
2026-02-25 17:17:13 -05:00
Bryan Helmkamp
d47c8e9048 Redact secrets from pipeline event output (NDJSON, live.json, SSE)
Apply redact::redact_jsonl_line at all three serialization sites so
secrets (AWS keys, GitHub PATs, private keys, etc.) are scrubbed
before reaching disk or the network.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: e23c92750cd9
2026-02-25 16:02:06 -05:00
Bryan Helmkamp
5067a59f7b Add per-node visit counter to prevent infinite loops in dry-run mode
Cyclic graphs (e.g. consensus_task.dot, semport.dot) loop infinitely
under --dry-run because the mock backend always returns outcome=success,
which never matches conditional edges. Add a configurable max_node_visits
limit (graph attr, default 0=disabled) that defaults to 10 in dry-run
mode, terminating execution when any node is visited more than the limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 633b59435252
2026-02-25 15:58:01 -05:00
Bryan Helmkamp
1388f6539a Replace 10 duplicate PipelineEvent variants with Agent wrapper
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
2026-02-25 15:23:01 -05:00
Bryan Helmkamp
20c972ef96 Resolve model catalog aliases in pipeline runner
The run and serve commands now resolve model aliases (e.g. "claude-haiku"
→ "claude-haiku-4-5-20251001") through the catalog before passing to the
backend, matching the behavior of the ullm CLI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 2b1f7b77b1ab
2026-02-25 15:22:17 -05:00
Bryan Helmkamp
655e207b8e Add 4 missing pipeline events for observability parity
- 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
2026-02-25 15:06:25 -05:00
Bryan Helmkamp
4239e3892d Support empty attribute blocks [] in DOT parser
The parser used separated_list1 for attr_block which required at least
one attribute inside brackets. DOT files from kilroy use empty brackets
(e.g., `consolidate_dod []`) which caused parse failures. Changed to
separated_list0 to accept empty attribute blocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: bccbc8222bde
2026-02-25 14:23:59 -05:00
Bryan Helmkamp
e415e18801 Add attempt tracking, EdgeSelected, and LoopRestart to pipeline events
Emit missing progress NDJSON data identified in gap analysis:
- Add attempt/max_attempts fields to StageStarted, StageCompleted, StageRetrying
- Add EdgeSelected event emitted after edge selection with label/condition
- Add LoopRestart event emitted before recursive loop-restart execution
- Simplify backend.rs usage aggregation to use Usage::Add impl

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f47850c1422d
2026-02-25 13:12:14 -05:00
Bryan Helmkamp
778bf45a0b Add cache tokens, reasoning tokens, and file change tracking to pipeline logs
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
2026-02-25 13:01:45 -05:00
Bryan Helmkamp
a00f7fd60e Add missing data fields to PipelineEvent variants
Thread existing data through to pipeline events to match kilroy's
progress.ndjson schema: handler_type on StageStarted, failure_reason on
StageFailed/StageCompleted, notes on StageCompleted, join_policy and
error_policy on ParallelStarted, status (replacing success bool) on
ParallelBranchCompleted, and question_type on InterviewStarted. Adds
Display impls for QuestionType, JoinPolicy, and ErrorPolicy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2d4a98c3b5f0
2026-02-25 11:40:19 -05:00
Bryan Helmkamp
5420c21042 Add auto-compaction to prevent context window overflow in long agent sessions
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
2026-02-24 23:09:38 -05:00
Bryan Helmkamp
52d3536a1d Add LLM conversation events to PipelineEvent for progress.ndjson observability
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
2026-02-24 14:08:22 -05:00
Bryan Helmkamp
0431fdb242 Revert "Replace text-scanning with report_outcome tool for routing"
This reverts commit f166bb4959.
2026-02-24 12:10:39 -05:00
Bryan Helmkamp
c9b7bee2da Change default logs directory to ~/.attractor/logs
Logs from `attractor run` were cluttering project directories. Now defaults
to ~/.attractor/logs/attractor-run-TIMESTAMP instead of ./attractor-run-TIMESTAMP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 09:58:20 -05:00
Bryan Helmkamp
3d8e17aedf Write progress.ndjson and live.json to logs dir during pipeline runs
Every PipelineEvent is now logged as a JSON envelope with timestamp,
run_id, and event fields — matching the Kilroy reference implementation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 09:50:19 -05:00
Bryan Helmkamp
9665fad133 Revert clippy config to defaults, remove all pedantic/nursery/cargo lint suppressions
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>
2026-02-24 09:42:28 -05:00
Bryan Helmkamp
f166bb4959 Replace text-scanning with report_outcome tool for routing
The previous approach scanned LLM response text for JSON containing
routing fields (extract_status_fields), which was fragile and violated
the spec's abstraction boundary. Replace with two clean mechanisms:

- Backend registers a report_outcome tool that the LLM calls to declare
  routing decisions (status, preferred_next_label, context_updates, etc.)
- Handler auto-generates a routing preamble listing available edge labels,
  appended to the prompt only when 2+ labeled unconditional edges exist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 09:29:25 -05:00
Bryan Helmkamp
7222da1230 Store response.<node_id> in context after each LLM node
Downstream nodes in multi-model pipelines reference response.<node_id>
context keys in their prompts. The codergen handler was only storing
last_response (truncated) and last_stage, so these references resolved
to nothing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:12:29 -05:00
Bryan Helmkamp
28cdefec67 Add token usage and cost tracking to pipeline runs
Surface LLM token consumption and dollar cost at every verbosity level:
default mode appends per-stage tokens/cost, verbose modes include it in
event summary/detail, and the Pipeline Result section shows a total.
Cost is computed from the catalog pricing for Anthropic models; providers
without pricing (OpenAI, Gemini) show token counts only. Dry runs with
zero tokens omit the cost line entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:01:17 -05:00
Bryan Helmkamp
aa9b05a552 Add timing output to default (non-verbose) pipeline runs
Show per-stage completion/failure timing and total pipeline duration
in the result block, even without -v flag. Uses a new
format_duration_human helper for human-readable durations (ms/s/m s).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:16:12 -05:00
Bryan Helmkamp
028353c82e Replace manual CLI prompts with dialoguer for arrow-key navigation
Interactive TTY sessions now use dialoguer widgets (Select, MultiSelect,
Confirm, Input) instead of raw eprintln/read_line. Non-TTY input falls
back to the existing line-based reader. Suppresses redundant "Stage
started" inform message for wait.human nodes since the prompt itself
serves as notification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:58:18 -05:00
Bryan Helmkamp
3dfa0f9044 Add shape selectors, LLM stream timeouts, MultiSelect questions, and test coverage
- 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>
2026-02-23 17:43:05 -05:00
Bryan Helmkamp
a3605ec0d4 Speed up slow tests: drop SSE broadcast on completion, switch to rustls-tls, replace hardcoded sleeps with poll loops, and prevent real API calls in ullm tests
- Drop event_tx from ManagedPipeline when pipeline completes/cancels/fails so
  SSE streams end promptly instead of blocking until timeout (3.5s → 0.02s)
- Switch reqwest from native-tls to rustls-tls to avoid 500ms macOS cert store
  load per process (0.67s → 0.005s per OpenAI adapter test)
- Replace hardcoded sleep(500ms)/sleep(200ms)/sleep(100ms) in server and
  integration tests with 10ms poll loops (0.2-0.5s → 0.02-0.03s each)
- Add env_clear() to ullm prompt tests to prevent .env from triggering real
  Anthropic API calls (0.45s → 0.15s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:19:09 -05:00
Bryan Helmkamp
36e37e5458 Print logs directory at pipeline start in verbose mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:33:28 -05:00
Bryan Helmkamp
480364c2b0 Add flow-control data to STAGE_COMPLETED event
Add status, preferred_label, and suggested_next_ids fields to the
StageCompleted event so pipeline flow decisions are visible in CLI
output and the web UI, making it easier to debug why a pipeline
took a particular path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:32:42 -05:00
Bryan Helmkamp
95a4ab24d5 Thread EngineServices through Handler::execute() to eliminate circular dependency
ParallelHandler and SubPipelineHandler needed Arc<HandlerRegistry> at
construction time but also lived inside the registry, creating a circular
dependency. The previous fix special-cased ParallelHandler as a separate
field on PipelineEngine with a resolve_handler() override.

Instead, add an EngineServices struct (registry + emitter) passed through
Handler::execute(). ParallelHandler and SubPipelineHandler become unit
structs that get what they need at execution time. No special-casing,
both register normally in default_registry() like every other handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:31:55 -05:00
Bryan Helmkamp
9f9b461971 Restore exactly-one terminal node validation per spec
The spec says "exactly one" exit node in the shape table (line 184),
exit handler docs (line 648), and test criteria (line 1834). The lint
rule table (line 1437) says "at least one" but is the minority. The
previous commit incorrectly reverted this — the terminal node change
was not causing the test failures (all three were from retry-on-Fail).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:12:45 -05:00
Bryan Helmkamp
6406fccd19 Fix regressions from ceaa9bf: restore Fail as non-retryable and allow multiple terminal nodes
Revert two incorrect behavioral changes introduced in ceaa9bf:

1. StageStatus::Fail must return immediately, not retry. Fail is a
   deliberate routing outcome (e.g. to take a "fail" edge). Retrying it
   caused conditional_branching and manager_loop tests to hang.

2. Pipelines can legitimately have multiple terminal nodes. The
   "exactly one" constraint broke branching_loop_back_on_failure.
   Restore "at least one" validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:09:36 -05:00
Bryan Helmkamp
06480db417 Register parallel handler to prevent dry-run hang on parallel pipelines
The parallel handler was never registered in default_registry() due to a
circular dependency (ParallelHandler::new needs Arc<HandlerRegistry>).
Break the cycle by storing ParallelHandler as a separate field on
PipelineEngine, created after Arc-wrapping the registry and emitter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:04:16 -05:00
Bryan Helmkamp
ceaa9bf560 Improve session abort handling, emit tool output deltas, and tighten validation
- 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>
2026-02-23 15:39:04 -05:00
Bryan Helmkamp
6fee3d82f1 Parse routing directives from LLM response text in CodergenHandler
When CodergenHandler receives CodergenResult::Text, it now extracts
preferred_next_label, suggested_next_ids, and context_updates from
the last JSON object in the response. This enables edge selection
via condition matching and preferred label instead of always falling
through to unconditional edges.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:31:35 -05:00
Bryan Helmkamp
242e82fffd Use Claude Opus 4.6 with 1M context window as default Anthropic model
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>
2026-02-23 14:23:45 -05:00
Bryan Helmkamp
f4f58078de Update default Gemini model to gemini-3.1-pro-preview and print model name on startup
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>
2026-02-23 14:05:16 -05:00
Bryan Helmkamp
379e90c11d Add --docker flag to attractor run and serve commands
When --docker is passed, agent tools execute inside a Docker container
via DockerExecutionEnvironment instead of running on the host. The host
working directory is bind-mounted into the container at /workspace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:42:10 -05:00