Add Claude Code delegation to Maple Agent - #976
benthecarman wants to merge 5 commits into
Conversation
Let Maple tasks delegate to an installed Claude Code CLI through a Rust transport adapted from Goose. Share Codex's activity, approval, question, and cancellation controls while keeping process ownership in Maple. Cover streaming, resumption, provider isolation, permissions, failures, and process cleanup with native CLI fixtures.
Show Codex and Claude in the composer only when enabled in Settings. Require each task to opt in, and block saved selections while Settings is disabled. Preserve task choices across restarts and re-enablement. Exercise admission, composer visibility, and cached tool refresh for both providers, including rejection of direct requests when disabled.
Explain Claude CLI setup, native transport provenance, and the separate Settings and task controls. Record the fixture validation workflow so future provider changes preserve the shared lifecycle contract.
abe8113 to
5b259ee
Compare
AnthonyRonning
left a comment
There was a problem hiding this comment.
Two non-blocking findings from a local review against claude 2.1.258 (stream-json protocol, interrupt, resume, and AskUserQuestion all verified outside the GUI). Details inline.
| let existing_thread = self.state.lock().await.thread_id.clone(); | ||
| let claude_thread = existing_thread | ||
| .clone() | ||
| .unwrap_or_else(claude::new_session_id); |
There was a problem hiding this comment.
A failed first Claude launch strands the agent. For Claude, ThreadStart echoes this locally generated UUID, so state.thread_id is committed (below, after the handshake) before the CLI has persisted anything. If the first turn dies at startup (not signed in, an --effort/--model value the CLI rejects, any usage error), every later agent_send on that agent runs --resume <uuid>. On 2.1.258 that returns result subtype=error_during_execution with stderr No conversation found with session ID: ..., which Maple renders as the same generic "could not complete this request" text, so the user cannot tell the agent is permanently broken. Codex only records a thread after thread/start succeeds.
Suggestion: commit the Claude session ID only once the child has emitted system/init (or the first successful result), or fall back to --session-id with the same UUID when a resume fails immediately with no turns.
| .filter(|(_, question)| question.is_object()) | ||
| .map(|(i, question)| { | ||
| let mut question = question.clone(); | ||
| question["id"] = format!("q{i}").into(); |
There was a problem hiding this comment.
Multi-select questions become single-select. AskUserQuestion sends multiSelect: true per question (verified on 2.1.258), but parse_user_questions in developer_tools.rs only keeps id/header/question/options, so the question card lets the user pick one option. The answer path in respond already joins several values with , , so only the card side is missing. Not blocking, but worth carrying multiSelect through the projection here so the card can allow multiple picks.
Adds Claude Code delegation alongside Codex in Maple Agent. Tasks can stream activity, answer approval and question cards, resume delegated sessions, and stop their child processes. The native Rust transport is adapted from the pinned Goose provider and requires only the installed Claude CLI.
The Claude card uses its logo and checks
claude auth status --jsonto show signed-in, signed-out, or unknown status. Status probes are bounded and account details are not retained. Failed launches before session confirmation retry with a fresh session instead of trying to resume an unsaved UUID. Claude'smultiSelectquestions support multiple choices and optional notes in Maple's question card.For both providers, Settings controls availability in the composer. Each task must explicitly select a provider; disabling it in Settings hides it and blocks saved selections on the next run. Task choices persist across restarts.
Validation:
just cirecipe passed on NixOS using installed host tools: formatting, four Clippy configurations, warning-denied workspace builds, 809 workspace tests, and 35 headless tests. This was not a pinnednix developrun.sleepexecutable.Native GUI checks ran on Linux only.