Commit graph

469 commits

Author SHA1 Message Date
Bryan Helmkamp
5fd4a5ea2e Collapse whitespace in ProgressUI tool call display to prevent line breaks
Multi-line arguments (e.g. spawn_agent task descriptions) were breaking
the single-line progress output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:25:43 -05:00
Bryan Helmkamp
28b5d485c1 Render Markdown output in terminal using termimad
LLM responses were printing raw Markdown (bold markers, table pipes,
heading hashes). Use termimad to render with proper ANSI formatting
when color is enabled, falling back to plain text when NO_COLOR is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:25:36 -05:00
Bryan Helmkamp
e6bbac771d Show failure error message when a stage fails in ProgressUI
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:17:02 -05:00
Bryan Helmkamp
c959368452 Redesign --verbose mode to use ProgressUI instead of raw event logs
Both verbose and normal modes now use the same indicatif-based ProgressUI
renderer with the same visual hierarchy (indentation, glyphs, colors).
In verbose mode: tool calls persist after stage completion, no 5-call cap,
stage completion shows stats (turns, tool calls, tokens), and additional
events are rendered (edge transitions, loop restarts, setup commands,
retries, context warnings, compaction, subagents).

Remove the old format_event_summary function and its ~70 tests, the
verbose stderr printing from AgentApiBackend, and the verbose/styles
fields that are no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:48:10 -05:00
Bryan Helmkamp
45165c1fa3 Add multi-provider ensemble demo and generate PNG/SVG for all demo workflows
New demo 11-ensemble.dot fans out to Opus (Anthropic), Gemini (Google),
Codex (OpenAI), and Mercury (Inception) in parallel, then synthesizes
results. Also generates PNG and SVG renderings for all existing demo
dot files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:47:54 -05:00
Bryan Helmkamp
13ad7d948a Add --preserve-sandbox flag to keep sandboxes alive for debugging
Adds a `--preserve-sandbox` CLI flag and `sandbox.preserve` TOML config
option that skips sandbox cleanup after a run. Cascade order:
CLI flag > run TOML > server.toml defaults > false.

When preserving, prints sandbox identity (container ID or Daytona
sandbox name) so users can reconnect for debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:32:17 -05:00
Bryan Helmkamp
49ac81624b Simplify SSH access API and add parallel fan-in jump_to_node
- Simplify create_ssh_access to return String directly
- Add jump_to_node field to Outcome for parallel handler fan-in
- Find convergence node from branch outgoing edges
- Use ..Outcome::success() spread in tests and error paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:23:01 -05:00
Bryan Helmkamp
b6bc58073b Simplify create_ssh_access return type and signature
Return just the SSH command string instead of the full SshAccessDto,
and hardcode the 60-minute expiration internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:22:39 -05:00
Bryan Helmkamp
e64f1e3c47 Add === Retro === section header before retro output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:15:12 -05:00
Bryan Helmkamp
932524dd98 Print retro summary inline in CLI output
Show smoothness rating, outcome, friction/open item counts, and file
path after retro completes instead of just the file path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:13:01 -05:00
Bryan Helmkamp
97d370b727 Add --ssh flag to arc run for Daytona SSH access
Creates SSH access after sandbox init and displays the connection
command in the progress output, aligned under the sandbox detail line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:11:39 -05:00
Bryan Helmkamp
6dc359f867 Show parallel branches in progress UI
Handle ParallelBranchStarted/Completed events as nested entries under
the fork stage, using the same indented spinner styling as tool calls.
Branch bars persist after the stage completes so they remain visible
in the final output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 08:58:44 -05:00
Bryan Helmkamp
5ab740b9d3 Fix sandbox detail line positioning with insert_after
Use insert_after instead of add so the detail bar renders directly
below the sandbox bar, not at the bottom of the multi-progress.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 08:49:13 -05:00
Bryan Helmkamp
990b2e9124 Add sandbox details and hyperlink to progress output
Show sandbox name, CPU, and memory on a second indented detail line
beneath the "Sandbox: provider" line. Hyperlink the provider name to
its dashboard URL using OSC 8 terminal escape sequences (TTY only).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 08:45:42 -05:00
Bryan Helmkamp
bde59168c9 Fix sandbox cleanup race and improve warning formatting
Sandbox cleanup was spawned fire-and-forget in a scopeguard, causing DNS
resolution to be cancelled when the tokio runtime shut down before the
HTTP request completed. Now cleanup is awaited explicitly before
returning, with the scopeguard kept only as a safety net for panics.

Also: add blank line before the warning and color-code it yellow to
match other warnings. Update daytona-sdk to include full error source
chain in error messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 08:29:05 -05:00
Bryan Helmkamp
918847af91 Field-level merging for run config defaults
apply_defaults() previously did whole-struct replacement for llm, setup,
and sandbox sections. If run.toml specified only [llm] model, the entire
server.toml [llm] block (including provider) was lost. Now each field
merges individually: task values win per-field, with map-merge for labels
(like vars) and whole-struct semantics for snapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 07:58:56 -05:00
Bryan Helmkamp
2a66e5fde5 Fix UTF-8 string slicing panics with floor_char_boundary helper
Add a shared floor_char_boundary() utility that rounds byte indices down
to the nearest char boundary, preventing panics on multi-byte UTF-8
characters like emoji. Applied to all 9 unsafe slice sites across
arc-agent and arc-workflows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 02:36:56 -05:00
Bryan Helmkamp
53dac89d1b Show model name and script command next to stage names in progress output
Display the LLM model ID (dim, bracketed) next to stage names as soon as
the first AssistantMessage arrives, and show the script command (dim,
truncated to 60 chars) for parallelogram/script stages from stage start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 02:05:25 -05:00
Bryan Helmkamp
c8a1693492 Use Checkpoint::load() instead of manual file read and parse
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:48:59 -05:00
Bryan Helmkamp
0a0f47b218 Print final stage output after run result summary
Reads the checkpoint to find the last stage with a response and
prints it under an "=== Output ===" header so users can see what
the workflow produced without digging into log files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:45:13 -05:00
Bryan Helmkamp
eb2246c626 dots 2026-03-04 01:35:39 -05:00
Bryan Helmkamp
73c741e64e Reduce tool call indent to 2 spaces under stage name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:34:12 -05:00
Bryan Helmkamp
c1ecbccb5c Add subagent demo and complete tool display name coverage
- Add demo/03-subagent.dot, renumber demos 04-08
- Add shell and spawn_agent to tool display name matcher
- Add list_dir, web_search, web_fetch, use_skill display args

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:29:58 -05:00
Bryan Helmkamp
4eea33b797 Enrich tool call display, emit exit node events, add --no-retro and demo
- Show tool args in dim parenthetical: read_file(CLAUDE.md)
- Shorten CWD-relative paths in tool call display
- Show elapsed time on completed tool calls
- Emit StageStarted/StageCompleted for terminal (exit) nodes
- Add --no-retro flag to skip retro generation
- Add demo/02-tool-use.dot, renumber existing demos 03-07

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:25:45 -05:00
Bryan Helmkamp
23a943efca Polish run output: tilde paths, retro timing, dim cost, goal spacing
- Shorten paths with ~ instead of full home directory
- Show retro duration right-aligned like stage lines
- Add "Running retro..." indicator before retro agent runs
- Dim the Cost/Tokens summary line
- Add blank line after Goal before progress section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:16:32 -05:00
Bryan Helmkamp
a71b9d0561 Keep duration on far right in stage completion lines
Swap cost and duration order so cost appears first and duration
stays consistently on the far right edge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:10:39 -05:00
Bryan Helmkamp
aa158ef6a5 Add blank line before human gate prompt
Insert a separator bar through indicatif before hiding progress bars
for interactive prompts, ensuring a visual gap between the spinner
and the dialoguer prompt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:08:54 -05:00
Bryan Helmkamp
81841d28eb Polish CLI run output: cleaner layout and less noise
- Increase indent from 2 to 4 spaces for progress UI lines
- Add blank line separators after Sandbox/Setup and before Retro output
- Dim Sandbox/Setup and workflow metadata lines
- Rename "Parsed workflow:" to "Workflow:"
- Remove redundant inform() calls for run/stage start/complete
- Remove Notes: and Logs: lines from end-of-run summary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 01:01:10 -05:00
Bryan Helmkamp
a1adbe89ca Fix Dependabot security alerts: update aws-lc-sys, jsonwebtoken, git2
- aws-lc-sys 0.37.1 → 0.38.0 (3 high: PKCS7 bypass, AES-CCM timing)
- jsonwebtoken 9 → 10.3.0 (medium: type confusion auth bypass)
- git2 0.19 → 0.20.4 (low: undefined behavior in Buf deref)
- Fix pre-existing clippy warning in arc-devcontainer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:42:23 -05:00
Bryan Helmkamp
dc3867a3c4 Fix cargo fmt formatting across workspace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:36:44 -05:00
Bryan Helmkamp
3fc3387c34 Add GitHub Actions CI workflows for Rust and TypeScript
Rust workflow runs fmt, clippy, and test on crate/cargo/openapi changes.
TypeScript workflow runs typecheck, test, and build on apps/packages changes.
Both use path filters so changes don't cross-trigger.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:35:04 -05:00
Bryan Helmkamp
c574fb7416 Fix Tailscale auth security issues in arc-web
- redirect-home: only check GitHub app config when provider is "github"
- app-shell: hide sign-out button when provider is "tailscale"
- auth-logout: skip session destroy and redirect to /start for Tailscale

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:18:58 -05:00
Bryan Helmkamp
4693c7373c Add 49 unit tests for uncovered pure logic in arc-llm
Cover cli.rs formatting/parsing/resolve/apply_options, common.rs
parse_error_body/extract_system_prompt/parse_retry_after, tools.rs
args_type_name, provider.rs validate_tool_choice, and types.rs
ToolChoice::mode_str.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:14:15 -05:00
Bryan Helmkamp
9447422e18 Simplify progress.rs: cache styles, fix UTF-8 safety, remove dead code
- Cache ProgressStyle and glyph strings with OnceLock (avoid repeated
  template parsing and allocations on every event)
- Fix unsafe byte-based string slicing in tool_display_name (use chars)
- Parse status via StageStatus enum instead of raw string comparison
- Remove unused started_at and logs_bar fields
- Extract shared finish_stage method from duplicate completed/failed logic
- Simplify match arms to if-let where only TTY branch has work

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 00:09:44 -05:00
Bryan Helmkamp
c374ceb391 Add indicatif-based progress UI for arc run start (non-verbose)
Replace plain dimmed text output with cargo/BuildKit-style progress bars
using indicatif MultiProgress. Shows spinners during active stages and
tool calls, right-aligned timers, green/red glyphs for completion status,
and stage costs. Falls back to simple eprintln for non-TTY. Verbose mode
is unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:58:43 -05:00
Bryan Helmkamp
fb47745cc2 Add Tailscale authentication provider
Read Tailscale-User-Login/Name/Profile-Pic headers when web.auth.provider
is "tailscale", checking login against required allowed_usernames list.
Rename githubLogin → login across session/callback/shell for provider
neutrality. Update app-shell loader and auth-login page to handle the
new provider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:46:55 -05:00
Bryan Helmkamp
7b39b42fda Add 87 unit tests for uncovered pure logic in arc-workflows
Cover format_cost, format_tokens_human, compute_stage_cost, all
format_event_summary variants, validate_command, context_diff, and
parse_label_filters with fast unit tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:42:34 -05:00
Bryan Helmkamp
fe9f6f6882 Remove 3 redundant doctor CLI integration tests
These tests only assert that section headings appear in stdout, which is
fully covered by unit tests in src/doctor.rs (check_llm_*, check_api_*,
check_web_*, and render tests). Removing them saves ~2.4s of parallel
nextest wall time from cold binary loads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:18:18 -05:00
Bryan Helmkamp
79a6a5e973 Simplify setup.rs: extract openssl helpers, remove unwraps, flatten state
- Extract run_openssl/run_openssl_with_stdin to deduplicate 8 command
  invocations into 2 reusable helpers
- Replace all .unwrap() in production code with .context() for proper
  error messages (stdin handles, path UTF-8 conversions)
- Collect API keys directly into env_pairs, removing redundant
  intermediate api_keys Vec

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:28:34 -05:00
Bryan Helmkamp
be72df55c8 Add arc setup interactive setup wizard
Automates first-time setup: generates server.toml, Ed25519 JWT keypair,
mTLS CA+server certificates, session secret, and .env file with proper
permissions. Includes pre-flight system dependency checks shared with
doctor, LLM provider API key collection, and optional doctor verification.

Also renames config file from arc.toml to server.toml across the codebase,
and loads ~/.arc/.env before CWD .env for centralized secret management.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:24:09 -05:00
Bryan Helmkamp
7660cea15c Restore abbreviated token formatting (1.2k, 3.4m) instead of HumanCount
HumanCount's comma-separated output (1,234) is less scannable for token
counts. Restore k/m suffix formatting with added millions support. Remove
indicatif dependency from arc-agent since it no longer uses it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:11:47 -05:00
Bryan Helmkamp
66d3f62131 Use indicatif formatters for human-readable durations, tokens, and bytes
Replace hand-rolled format_duration_human, format_tokens_human, and
format_token_count with indicatif's HumanDuration, HumanCount, and
HumanBytes. Token counts now display as comma-separated (e.g. "1,234")
instead of abbreviated (e.g. "1.2k"), and byte counts show units
(e.g. "1.50 KiB").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:09:18 -05:00
Bryan Helmkamp
d373ffd10f Clean up doctor types: ProbeOutcome enum, typed status structs, Ord
- Replace found/success/version bools with ProbeOutcome enum to
  eliminate impossible state (found=false, success=true)
- Remove DepProbeResult; check_system_deps takes DepSpec + ProbeOutcome
  directly, eliminating redundant field copying and the clone
- Use typed Vec<ApiAuthStrategy> and AuthProvider in ApiStatus/WebStatus
  instead of converting enums to strings at construction time
- Derive Ord on CheckStatus, replace manual severity-max with .max()
- Extract dep_issue helper to deduplicate required/optional formatting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:55:34 -05:00
Bryan Helmkamp
78a8f93bc5 Replace version tuples with semver::Version in doctor
Use the semver crate's Version type instead of manual (u32, u32, u32)
tuples for version comparison and display, eliminating the custom
format_version helper in favor of Version's built-in Display and Ord.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:47:08 -05:00
Bryan Helmkamp
71f7af267a Add URL context to API fetch errors for easier debugging
When the API server is unreachable, the raw "fetch failed" error gives
no indication of what URL was being requested. Wrapping the error
includes the target URL in the message while chaining the original
cause.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:41:35 -05:00
Bryan Helmkamp
3e28e6acda Reduce stall watchdog test sleep times for faster test runs
Shrink timeouts and handler durations by ~5-10x. The tests verify
the same relative timing behavior (keepalive interval < stall timeout,
hung handler outlasts timeout) with smaller absolute values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:41:09 -05:00
Bryan Helmkamp
9243c94ded Replace fragile string filter with structural error tracking
The remediation list was derived by filtering details for strings not
containing ": valid", which could silently exclude real errors. Replace
with CryptoCheckState that accumulates errors structurally as they
occur, and unify all validation paths through record/record_unit/
push_error methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:25:27 -05:00
Bryan Helmkamp
d688a6c095 Simplify crypto validation in arc doctor after code review
- Extract record_validation() helper to deduplicate Ok/Err → detail handling
- Make expand_tilde public in tls.rs and reuse it in doctor instead of
  duplicating the tilde expansion logic
- Make now_epoch injectable in CryptoInput for deterministic tests
- Change tls_files to Option<Result<...>> to distinguish "not configured"
  from "files unreadable"
- Use struct update syntax in tests to reduce boilerplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:21:34 -05:00
Bryan Helmkamp
64a6b0278a Bypass GitHub OAuth when auth provider is insecure_disabled
The app-shell and redirect-home loaders unconditionally required GitHub
OAuth, which broke demo mode. Now they check the auth provider config
and use a hardcoded demo user when auth is disabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:36:30 -05:00
Bryan Helmkamp
dc7b0af2bc Add cryptographic key validation to arc doctor
Validates mTLS certs (PEM parsing, expiry), JWT public/private keys
(Ed25519 PEM with base64 support), and session secret (hex, 256-bit
minimum) when the corresponding auth strategies are configured.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 20:35:36 -05:00