Introduces sandbox reconnection via persisted SandboxRecord, adds
upload_file_from_local to the Sandbox trait, and migrates arc-sprites
shell quoting to shlex::try_quote.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow setting pull_request.enabled in ~/.arc/cli.toml so auto-PR
works when running `arc run` with a .dot file (no run.toml needed).
Cascade precedence: run.toml > cli.toml > server.toml > defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five new CLI-level tests covering file creation, shell execution,
read-only permission enforcement, JSON output format, and read+edit
multi-step tool use. All gated with #[ignore = "requires API key"].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a top-level `verbose` bool to CliConfig so `arc run start` and
`arc doctor` pick it up without requiring `-v` every invocation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the server-side session handlers (create, retrieve, send message,
stream events, list) with in-memory storage and LLM generation, wire them
into the router replacing not_implemented stubs, add run_chat_via_server
CLI function with SSE streaming, and add mode dispatch so `arc llm chat
--mode server` delegates to the API server.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a completions API endpoint that supports both streaming (SSE) and
non-streaming (JSON) modes, with structured output via JSON Schema.
Wires up the CLI `arc llm prompt` command to use the server when
`--mode server` is specified.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidates the two separate String parameters (git_author_name,
git_author_email) threaded through ~10 function signatures into a
single GitAuthor struct with Default providing "arc"/"arc@local".
Also quotes git config values in parallel.rs shell commands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now configure the git author name/email used for checkpoint
commits via [git.author] in server.toml (default) and cli.toml (override).
Defaults to "arc" / "arc@local" preserving current behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`arc serve` writes to `serve-YYYY-MM-DD.log` and all other commands
write to `cli-YYYY-MM-DD.log` so the two are easy to tail independently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Commands can now delegate to a running Arc API server instead of
executing in-process. Adds ExecutionMode, ServerDefaults, and
ClientTlsConfig to cli.toml parsing with CLI flag > config > default
precedence. The models list command fetches from GET /models when in
server mode, with mTLS client certificate auth when [server.tls] is
configured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces flat ModelInfo fields with nested sub-structs (ModelLimits,
ModelFeatures, ModelCosts) and adds family, training, and
cache_input_cost_per_mtok fields to enrich the model catalog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Share a single reqwest::Client across GitHub API calls in resolve_clone_credentials
to reuse the TLS connection pool
- Accept raw PEM (not just base64-encoded) in build_github_app_credentials, matching
the existing decode_pem_env/decode_pem_value convention
- Move github_app into DaytonaSandbox::new() instead of cloning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace `gh auth token` with GitHub App IATs scoped to `contents: read` for
Daytona sandbox git cloning. Public repos are auto-detected and cloned without
credentials. Private repos get short-lived, repo-scoped tokens. Clear error
messages for each failure mode (app not installed, suspended, no repo access,
auth failure). Falls back gracefully when no GitHub App is configured.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add both models with aliases (gpt54, gpt54-pro). Neither replaces
gpt-5.2 as the OpenAI default. Update fallback chain test since
GPT-5.4 ($2.50) is now closer to Opus ($15) than GPT-5.2 ($1.75).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parses a DOT file and outputs its AST as pretty-printed JSON, useful for
debugging and tooling. Adds Serialize/Deserialize to all AST types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Deserialize permissions/output_format as typed enums instead of strings
so invalid values in cli.toml fail at parse time
- Use Option::or/or_else combinators instead of if-is_none pattern
- Load cli.toml only for agent/llm commands, not all CLI invocations
- Standalone arc-agent binary calls apply_cli_defaults for single source
of hardcoded defaults
- Remove redundant #[serde(default)] on Option fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users who always use the same provider/model/permissions no longer need
to pass flags every time. Precedence: CLI flag > cli.toml > hardcoded default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
load_server_config() now accepts an optional explicit path. When
provided, it reads from that path (erroring if missing) instead of
the default ~/.arc/server.toml. The --config flag is wired through
ServeArgs and the hot-reload polling loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move CheckReport, CheckResult, CheckDetail, and CheckStatus types from
arc-cli doctor into arc-util so they can be reused. Refactor the workflow
run_preflight to render a styled check report instead of ad-hoc key=value
output and separate stderr errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Install ring CryptoProvider at CLI startup to prevent rustls panic
- Skip TLS in demo mode so the server uses plain HTTP
- Add ARC_DEMO=1 env var to web app config to bypass GitHub OAuth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- 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>
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>
- 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>
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>
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>
- 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>
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>
- Consolidate 4 duplicate parser functions into one `parse_version(re, output)`
- Use `LazyLock<Regex>` statics (matching codebase patterns in arc-util, arc-workflows)
- Replace 5-element tuple with named `DepSpec` struct
- Replace `raw_output: Option<String>` with `found: bool` (content was never used)
- Remove unnecessary `pub` from internal types and functions
- Parse stdout/stderr separately instead of concatenating
- Consolidate 10 parser tests into 6 via shared `parse_version`
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Checks openssl, node, gh, and dot for presence, version, and command
success. Reports errors for missing/broken required tools and warnings
for optional ones. Also fixes pre-existing build break from
ApiAuthenticationStrategy -> ApiAuthStrategy rename.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract apply_live_result() helper to deduplicate connectivity-result
handling across check_api, check_web, and check_brave_search
- Merge probe_api/probe_web into single probe_url function
- Share one reqwest::Client across all HTTP probes
- Run LLM probes concurrently via futures::future::join_all instead of
sequential loop (saves wall-clock time with multiple providers)
- Compute daytona_configured once before the live/offline branch
- Move live flag from DoctorReport struct field to render() parameter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Styles fields change from &'static str (raw ANSI escape codes) to
console::Style, removing unsafe Send/Sync impls and manual reset
handling. The console crate handles TTY detection and NO_COLOR natively.
Also adds live connectivity probes to arc doctor (--live flag).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move auth config under [web.auth] in arc.toml to group web-specific
settings together. Add WebConfig with url field (default localhost:5173).
Add `arc doctor` command with checks for config, API, web, LLM providers,
Brave Search, sandbox, and GitHub App. Extract Provider::api_key_env_vars
and has_api_key to deduplicate validation logic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename AppConfig → ServerConfig with flattened RunDefaults so users can
set default llm, sandbox, setup, directory and vars in ~/.arc/arc.toml.
Precedence: CLI flags > workflow TOML > server config defaults > DOT
graph attrs > hardcoded defaults. Vars merge (defaults first, task
config overwrites collisions).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add node_id to Stage* enum variants so both the programmatic ID and
display label are available. Add rename_fields() post-processing in
flatten_event() to give flattened JSONL fields self-describing names:
- timestamp → ts (save space)
- name → node_label (Stage*), workflow_name, snapshot_name
- index → stage_index, branch_index, command_index
- stage → node_id (Agent.*, Interview*, Prompt)
- branch → node_id (ParallelBranch*)
- node → node_id (StallWatchdogTimeout)
- from_node/to_node → from_node_id/to_node_id
- start_node → start_node_id
- provider → sandbox_provider (Sandbox.*)
- text → prompt_text (Prompt)
- Insert node_label defaulting to node_id where only an id exists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Event data was nested inside a tagged enum (`"event": {"StageStarted": {fields}}`).
Now `event` is a string name and fields merge into the top-level object
(`"event": "StageStarted", "name": "plan", ...`).
Nested events use dot notation:
- Agent wrapper: "Agent.ToolCallStarted" with stage at top level
- Sandbox wrapper: "Sandbox.Initializing" with fields at top level
- SubAgentEvent: "Agent.SubAgentEvent.ToolCallStarted" flattened one level
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new `chat` subcommand under `arc llm` that reads user input in a
loop, maintains conversation history, streams LLM responses, and supports
`--model` and `--system` options. Includes an e2e test verifying multi-turn
context and system prompt behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update command descriptions and test event name strings to use
workflow/run terminology instead of pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>