Skip to content

feat: agentic-loop automation + multi-agent CLI mode (codex live; 7 agents staged)#23

Merged
miguelrisero merged 9 commits into
mainfrom
mr/1ac7-agent-retry-schedule-cli
Jun 30, 2026
Merged

feat: agentic-loop automation + multi-agent CLI mode (codex live; 7 agents staged)#23
miguelrisero merged 9 commits into
mainfrom
mr/1ac7-agent-retry-schedule-cli

Conversation

@miguelrisero

Copy link
Copy Markdown
Owner

Two additive features that keep agentic loops running and bring every supported agent into CLI mode. The older managed/UIX executors are untouched — everything here is additive.

Part 1 — Loop automation (keep going when a chat stops for a non-completion reason)

Opt-in per workspace (default OFF). The supervisor watches the CLI pane, and when the agent stalls on a usage limit or a transient rate limit it schedules a wake-up and re-prompts the agent — so loops survive throttling instead of waiting for a human.

  • DB: loop_automations (per-workspace policy) + scheduled_wakeups migration + models.
  • Supervisor (local_deployment::loop_supervisor, a tokio-interval task): tmux capture-pane to detect the banner, schedule a wake-up (short retry for a rate limit, parsed reset time for a usage limit), and re-prompt via tmux send-keys. Idle-safe — a limit-kind wake-up only fires while the banner is still showing, so a manually-resumed agent is never interrupted.
  • API: GET/PUT per-workspace policy, POST manual wake-up ("ping at 05:00 UTC"), DELETE wake-up.
  • Frontend: a "Keep going" toggle + settings popover (interval / continuation prompt / max attempts) + next-wakeup status in the CLI pane header.
  • Kill-switch env DISABLE_LOOP_AUTOMATION. Banner + reset-time parsing unit-tested; send-keys/capture-pane mechanics validated live.

Part 2 — Multi-agent CLI mode

The persistent tmux CLI pane was Claude-only. It's now generic: any agent runs its interactive TUI in the pane, reusing the same per-agent settings the managed UI already exposes (model / reasoning / sandbox / approval).

  • New CliLaunchSpec + interactive_cli_spec() trait method; agents opt in, None falls back to claude.
  • cli_bootstrap/PtyCommand::TmuxCli are agent-agnostic; the agent is resolved from Session.executor; start_workspace_cli honors the selected executor.
  • Autonomous by default in CLI (worktrees are app-created/isolated); Supervised/Plan still map through.

Agent status

  • Claude ✅ refactored behind the new abstraction (no behavior change).
  • Codex ✅ implemented and live-verified in a real tmux pane (YOLO autonomy + model + worktree). Includes seeders for codex's per-folder trust prompt and its blocking "Update available" startup modal.
  • Gemini, opencode, cursor, droid, amp, qwen, copilotinteractive_cli_spec implemented + unit-tested, wired through the same path. Not installed locally, so they're staged behind your approval: see docs/superpowers/specs/2026-06-30-cli-agents-install-and-e2e-plan.md for each agent's exact install command, auth/onboarding requirements, the code already written, and the e2e checklist. No tools are installed by this PR.

Verification

  • cargo test green for the changed crates: executors (73), local-deployment (42).
  • generate-types:check ✅ and prepare-db:check ✅ (CI guards).
  • Frontend tsc (web-core/local-web/remote-web), eslint, and i18n checks ✅.
  • Codex CLI mode exercised live in tmux; tmux send/capture mechanics validated live.
  • cargo check --workspace fails only on the tauri-app GUI crate (glib-sys, no GTK in this headless env) and the remote crate's private billing dep — both pre-existing and unrelated to this change.

Design docs

  • docs/superpowers/specs/2026-06-30-cli-agents-and-loop-automation-design.md
  • docs/superpowers/specs/2026-06-30-cli-agents-install-and-e2e-plan.md

Generalize the tmux-backed CLI pane beyond claude so any agent can run its
interactive TUI in the main workspace, reusing the same per-agent settings as
headless mode (without touching the managed/UIX executors).

- Add CliLaunchSpec (program/base_args/resume/prompt/continue forms) + an
  interactive_cli_spec() trait method; agents opt in, None falls back to claude.
- Implement it for ClaudeCode (refactor of the old hardcoded launch — no
  behavior change) and Codex (-m model, -c model_reasoning_effort, -s sandbox,
  -a approval, --no-alt-screen, 'codex resume <id>').
- Make cli_bootstrap/PtyCommand::TmuxCli agent-agnostic; resolve the agent from
  Session.executor in terminal.rs; honor the selected executor in
  start_workspace_cli instead of hardcoding claude.
- Pre-seed codex local-env friction (per-folder trust + the blocking
  'Update available' startup modal) so an unattended launch reaches the TUI.

Codex CLI mode verified live in a tmux pane (YOLO autonomy + model + worktree).
…wake-ups, re-prompt)

Keep an opt-in CLI workspace's agent going when a chat stops for a non-completion
reason (usage limit / transient rate limit), so agentic loops survive provider
throttling instead of stalling until a human notices.

- DB: loop_automations (per-workspace opt-in policy, default OFF) +
  scheduled_wakeups (pending/delivered re-prompts) migration + models.
- Loop supervisor (tokio interval task, spawned from LocalDeployment::new()):
  capture-pane to detect the limit banner, schedule a wake-up (short retry for a
  rate limit, parsed reset time for a usage limit), and re-prompt via send-keys.
  Idle-safe: limit-kind wake-ups only fire while the banner is still showing.
- tmux capture_cli_pane + send_cli_keys helpers (pane output is otherwise
  ephemeral; this is the only server-side view of / write to a live detached pane).
- REST API: GET/PUT per-workspace policy, POST manual wake-up, DELETE wake-up.
- Kill-switch env DISABLE_LOOP_AUTOMATION; banner + reset-time parsing unit-tested;
  tmux send/capture mechanics validated live.
…ilot CLI specs

Implement interactive_cli_spec for the remaining 7 agents so any of them can run
in the CLI pane via the same generic path as claude/codex. Each maps its existing
managed config (model / reasoning / autonomy) to interactive flags, autonomous by
default (Supervised dials back):

- gemini/qwen: --approval-mode yolo, -i prompt, --resume
- opencode: -m provider/model, --prompt, -s/-c (autonomy via opencode.json)
- cursor-agent: resolved --model, --force, positional, --resume/--continue
- droid: --model, --reasoning-effort, --auto/--skip-permissions-unsafe
- amp: stdin-piped prompt (new CliPromptArg::StdinPipe), 'amp threads continue'
- copilot: --model, --allow-all-tools, --no-banner, -i

These are NOT installed locally, so they're staged with unit tests + an exact
per-agent install/auth/seeder/e2e plan (docs/.../cli-agents-install-and-e2e-plan.md)
awaiting approval before any install. cli_spec_tests verifies all 9 agents wire up
with the right binary + autonomous defaults.
Front-end for part 1: a per-workspace, default-OFF 'Keep going' toggle in the CLI
pane header with a settings popover (retry interval, continuation prompt, max
attempts) and a next-wakeup status line ('Retrying at 14:32' / 'Waking at 05:00
UTC') with a cancel button.

- loopAutomationApi (get status / update policy / create + delete wakeup) in api.ts
- useLoopAutomation react-query hook (status query + mutations, cache seeding)
- LoopAutomationControl wired into CliMainPane header; i18n strings added

Typechecks + lints clean (web-core/local-web/remote-web, eslint, i18n).
…ft on installed versions

Installed gemini/qwen/opencode/amp/copilot (npm) + cursor-agent/droid (curl) and
launched each in a real tmux pane with the exact flags interactive_cli_spec
emits. All 7 binaries resolve and every coded flag is accepted; each reaches its
own UI (TUI / login / provider menu) — opencode even answered on its free
built-in model. Only auth keys/login remain.

Flag fixes for the newer installed versions:
- droid 0.161: interactive launch no longer takes --model/--reasoning-effort/
  --skip-permissions-unsafe; emit only --auto low|medium|high (Skip→high).
- copilot 1.0.65: no --no-banner (banner off by default); removed.
- opencode: use confirmed long-form --session/--continue.

Verification table + remaining per-agent friction recorded in the install plan.
…an agent isn't installed

Previously, launching CLI mode for an agent whose binary isn't on PATH (the
'command -v <prog> && ...' gate failed) dropped silently into a bare shell — the
user picked an agent and got an empty terminal with no reason. Now the pane
prints a clear '[!] <agent> is not installed — Install: <cmd>' notice with the
per-agent install command, then leaves a usable shell so they can install it
there or switch agents. (Installed-but-not-authed is unchanged: the agent shows
its own login screen, which is the right place for it.)
… don't hide)

Proactive complement to the in-pane install notice: the create-flow agent picker
now floats installed agents to the top and tags uninstalled ones '· not installed',
so you see it before launching rather than after.

- GET /api/agents/cli-availability returns which agents' interactive CLI binary
  is on PATH (a CLI-specific 'command -v' check via the which crate — distinct
  from the config-file-based AvailabilityInfo; managed mode runs via npx and is
  unaffected).
- useCliAgentAvailability hook + configApi.cliAgentAvailability.
- CreateChatBoxContainer sorts installed-first and annotates via the existing
  formatExecutorLabel prop (no @vibe/ui change). Loading state reports all
  installed so it never flashes a misleading tag.

Picker stays honest/consistent with the managed UI (shows all agents); the
in-pane notice still covers launch if a missing agent is picked anyway.
… the hot path)

The TmuxCli variant carries the resolved CliLaunchSpec and is the common case
(CLI mode is the default pane), so the size gap vs the unit Shell variant is
expected; boxing the hot path would only add an allocation. Keeps
`cargo clippy -- -D warnings` (as CI runs it) green.
…ntend-checks)

The 'Keep going' UI strings were added to en/common.json only; CI's check-i18n
requires every key in every locale (es, fr, ja, ko, zh-Hans, zh-Hant). Add
translations for all 16 keys across the 6 locales, inserted in en's key order
(after cliMode). Preserves {{time}}/{{used}}/{{max}} interpolation placeholders.
@miguelrisero miguelrisero merged commit 19e0dbf into main Jun 30, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant