commandmate 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +266 -266
- package/.next/app-path-routes-manifest.json +15 -15
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +3 -3
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/chat/page.js +2 -2
- package/.next/server/app/chat/page.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page.js +2 -2
- package/.next/server/app/login/page.js.nft.json +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +2 -2
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +2 -2
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +2 -2
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js +2 -2
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +6 -6
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +15 -15
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3346.js +1 -1
- package/.next/server/chunks/4455.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/5571.js +1 -1
- package/.next/server/chunks/5959.js +4 -4
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6274.js +12 -9
- package/.next/server/chunks/6285.js +1 -1
- package/.next/server/chunks/7458.js +6 -6
- package/.next/server/chunks/848.js +1 -1
- package/.next/server/chunks/8730.js +1 -0
- package/.next/server/chunks/880.js +1 -1
- package/.next/server/chunks/9328.js +1 -1
- package/.next/server/chunks/9373.js +4 -3
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/2053-dfac2d49227cc942.js +1 -0
- package/.next/static/chunks/3898-ef488bfa804507d9.js +1 -0
- package/.next/static/chunks/5229-35f9acab97a553c5.js +1 -0
- package/.next/static/chunks/{6381-18a6a02a94d00d76.js → 6381-9303430933084b56.js} +1 -1
- package/.next/static/chunks/{9599-d29d2f8eeaf7c249.js → 8649-f551b0010dba4986.js} +1 -1
- package/.next/static/chunks/9263.f2034ec525abcf72.js +1 -0
- package/.next/static/chunks/app/chat/page-439b35c9cb90dbe0.js +1 -0
- package/.next/static/chunks/app/login/page-eefd515d8c37e5ee.js +1 -0
- package/.next/static/chunks/app/more/page-889b7546a8a553dc.js +1 -0
- package/.next/static/chunks/app/page-a8d04ac0e3e4c9fc.js +1 -0
- package/.next/static/chunks/app/repositories/page-f3c4d8839b1ca203.js +1 -0
- package/.next/static/chunks/app/review/page-6dc88649fe88ac16.js +1 -0
- package/.next/static/chunks/app/sessions/page-2c9ed9e969097688.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/page-19beef6121c4c982.js +1 -0
- package/.next/static/chunks/app/skills/installed/page-d5b9cef6d21fabda.js +1 -0
- package/.next/static/chunks/app/skills/page-06ef637e07dd9377.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/{page-9ddcb224594f620f.js → page-5fed3984fafcd910.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-fbdf4621a2911ac1.js +1 -0
- package/.next/static/chunks/{webpack-3534d858912a6c92.js → webpack-9d892a9ff07c289d.js} +1 -1
- package/.next/static/css/e865c4979a41aa03.css +1 -0
- package/.next/trace +12 -12
- package/README.md +96 -45
- package/dist/cli/commands/task.d.ts.map +1 -1
- package/dist/cli/commands/task.js +2 -1
- package/dist/cli/commands/verify.d.ts +14 -0
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +109 -3
- package/dist/cli/commands/wait.d.ts +2 -0
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +184 -4
- package/dist/cli/types/api-responses.d.ts +172 -0
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +31 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/types/index.js +26 -0
- package/dist/cli/utils/verify-runner.d.ts +36 -1
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +114 -6
- package/dist/server/src/config/activity-bar-config.js +5 -1
- package/dist/server/src/lib/auto-yes-poller.js +40 -4
- package/dist/server/src/lib/auto-yes-state.js +108 -3
- package/dist/server/src/lib/cli-tools/antigravity.js +8 -4
- package/dist/server/src/lib/cli-tools/codex.js +63 -30
- package/dist/server/src/lib/cli-tools/copilot.js +5 -1
- package/dist/server/src/lib/cli-tools/gemini.js +15 -15
- package/dist/server/src/lib/cli-tools/opencode.js +9 -3
- package/dist/server/src/lib/detection/cli-patterns.js +148 -6
- package/dist/server/src/lib/detection/status-detector.js +28 -0
- package/dist/server/src/lib/detection/upstream-faults.js +120 -0
- package/dist/server/src/lib/hooks/permission-decision-service.js +13 -5
- package/dist/server/src/lib/hooks/sources/antigravity/hooks-config.js +18 -11
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +10 -9
- package/dist/server/src/lib/hooks/sources/claude/source.js +5 -2
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +26 -18
- package/dist/server/src/lib/hooks/sources/codex/source.js +6 -9
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +22 -12
- package/dist/server/src/lib/hooks/sources/copilot/source.js +1 -1
- package/dist/server/src/lib/hooks/sources/define-source.js +6 -4
- package/dist/server/src/lib/hooks/sources/gemini/settings-generator.js +14 -8
- package/dist/server/src/lib/hooks/sources/gemini/source.js +29 -29
- package/dist/server/src/lib/hooks/sources/index.js +4 -1
- package/dist/server/src/lib/hooks/sources/launch-command.js +61 -0
- package/dist/server/src/lib/hooks/sources/legacy-relay.js +2 -1
- package/dist/server/src/lib/hooks/sources/opencode/source.js +10 -7
- package/dist/server/src/lib/polling/prompt-dedup-state.js +95 -0
- package/dist/server/src/lib/polling/response-checker.js +12 -0
- package/dist/server/src/lib/polling/response-poller-core.js +11 -1
- package/dist/server/src/lib/session/agent-session-lifecycle.js +28 -7
- package/dist/server/src/lib/session/claude-session.js +5 -1
- package/dist/server/src/lib/session/current-output-builder.js +34 -0
- package/dist/server/src/lib/verification/env-snapshot.js +21 -3
- package/dist/server/src/lib/verification/gate-runner.js +258 -7
- package/dist/server/src/lib/verification/machine-lock.js +204 -0
- package/dist/server/src/lib/verification/scope-gate.js +126 -13
- package/dist/server/src/lib/verification/verify-config.js +85 -3
- package/dist/server/src/lib/verification/worktree-index.js +140 -0
- package/package.json +1 -1
- package/.next/server/chunks/3451.js +0 -1
- package/.next/static/chunks/2053-52d3c82014e1cd54.js +0 -1
- package/.next/static/chunks/5229-0610b4e3288e777d.js +0 -1
- package/.next/static/chunks/744-3ad06d8c8ca482fc.js +0 -1
- package/.next/static/chunks/9263.5259f73f89220d64.js +0 -1
- package/.next/static/chunks/app/chat/page-15d13fc024d78f5d.js +0 -1
- package/.next/static/chunks/app/login/page-0247a3fb569bb22b.js +0 -1
- package/.next/static/chunks/app/more/page-b8ba537baeac8d5b.js +0 -1
- package/.next/static/chunks/app/page-afc64708362f31e5.js +0 -1
- package/.next/static/chunks/app/repositories/page-3469dacb6be7842f.js +0 -1
- package/.next/static/chunks/app/review/page-2d9cb7e068f8f35a.js +0 -1
- package/.next/static/chunks/app/sessions/page-7470c2bfd89e0df9.js +0 -1
- package/.next/static/chunks/app/skills/[skillId]/page-5e24481162f7ea78.js +0 -1
- package/.next/static/chunks/app/skills/installed/page-efd2d710a27f9735.js +0 -1
- package/.next/static/chunks/app/skills/page-0498adfc6e48684b.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-e611d30e47989e5d.js +0 -1
- package/.next/static/css/3ac44cfc082d02ad.css +0 -1
- /package/.next/static/{smu4mnL7qMf8w38n9dQJE → hNdNiFes2xLls68SWhAU9}/_buildManifest.js +0 -0
- /package/.next/static/{smu4mnL7qMf8w38n9dQJE → hNdNiFes2xLls68SWhAU9}/_ssgManifest.js +0 -0
|
@@ -149,7 +149,11 @@ class CopilotTool extends base_1.BaseCLITool {
|
|
|
149
149
|
// Fails open in every branch: with `CM_AGENT_HOOKS_INJECT=0`, or with a
|
|
150
150
|
// settings file that cannot be read or written, this is byte-for-byte the
|
|
151
151
|
// `gh copilot` this line has always sent.
|
|
152
|
-
const launchCommand = (0, agent_session_lifecycle_1.
|
|
152
|
+
const launchCommand = (0, agent_session_lifecycle_1.buildAgentLaunchCommandLine)({
|
|
153
|
+
target: { worktreeId, cliToolId: tool_id_1.COPILOT_CLI_TOOL_ID, instanceId },
|
|
154
|
+
executablePath: hook_settings_1.COPILOT_LAUNCH_COMMAND,
|
|
155
|
+
worktreePath,
|
|
156
|
+
});
|
|
153
157
|
// Start Copilot CLI in interactive mode
|
|
154
158
|
await (0, tmux_1.sendKeys)(sessionName, launchCommand, true);
|
|
155
159
|
// Wait for Copilot to initialize
|
|
@@ -16,7 +16,6 @@ const submit_verified_sender_1 = require("./submit-verified-sender");
|
|
|
16
16
|
const tmux_capture_cache_1 = require("../tmux/tmux-capture-cache");
|
|
17
17
|
const cli_patterns_1 = require("../detection/cli-patterns");
|
|
18
18
|
const sources_1 = require("../../lib/hooks/sources");
|
|
19
|
-
const source_1 = require("../../lib/hooks/sources/gemini/source");
|
|
20
19
|
const agent_session_lifecycle_1 = require("../../lib/session/agent-session-lifecycle");
|
|
21
20
|
const logger_1 = require("../../lib/logger");
|
|
22
21
|
const cli_tool_timing_config_1 = require("../../config/cli-tool-timing-config");
|
|
@@ -92,23 +91,24 @@ class GeminiTool extends base_1.BaseCLITool {
|
|
|
92
91
|
});
|
|
93
92
|
// Wait a moment for the session to be created
|
|
94
93
|
await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.TUI_SESSION_CREATE_WAIT_MS));
|
|
95
|
-
// Issue #1762: hand this worktree its own hooks config, merged into any
|
|
96
|
-
// `.gemini/settings.json` that is already there. Written from here rather
|
|
97
|
-
// than from the source's `prepareLaunch` because the worktree path is the
|
|
98
|
-
// one input `AgentInstanceRef` does not carry, and gemini is the only tool
|
|
99
|
-
// whose config is scoped to a worktree. Fail-open: a config that cannot be
|
|
100
|
-
// written costs the events and nothing else.
|
|
101
|
-
(0, source_1.injectGeminiHookSettings)(worktreePath, {
|
|
102
|
-
worktreeId,
|
|
103
|
-
cliToolId: sources_1.GEMINI_CLI_TOOL_ID,
|
|
104
|
-
instanceId,
|
|
105
|
-
});
|
|
106
94
|
// Start Gemini CLI in interactive mode (no flags = interactive REPL).
|
|
107
|
-
//
|
|
95
|
+
//
|
|
96
|
+
// Issue #1762 hands this worktree its own hooks config, merged into any
|
|
97
|
+
// `.gemini/settings.json` that is already there; Issue #1846 moved that
|
|
98
|
+
// write inside `prepareLaunch`, where it belongs — the worktree path is
|
|
99
|
+
// now part of the launch context, so the second entry point this file
|
|
100
|
+
// used to call (`injectGeminiHookSettings`) is gone.
|
|
101
|
+
//
|
|
102
|
+
// The rendered line prefixes `CM_HOOK_URL`, which is what tells the
|
|
108
103
|
// receiver which instance an event came from — `.gemini/settings.json` is
|
|
109
104
|
// per worktree and cannot. `CM_AGENT_HOOKS_INJECT=0` returns the bare
|
|
110
|
-
// command, unchanged from before
|
|
111
|
-
|
|
105
|
+
// command, unchanged from before these Issues. Fail-open throughout: a
|
|
106
|
+
// config that cannot be written costs the events and nothing else.
|
|
107
|
+
const launchCommand = (0, agent_session_lifecycle_1.buildAgentLaunchCommandLine)({
|
|
108
|
+
target: { worktreeId, cliToolId: sources_1.GEMINI_CLI_TOOL_ID, instanceId },
|
|
109
|
+
executablePath: this.command,
|
|
110
|
+
worktreePath,
|
|
111
|
+
});
|
|
112
112
|
await (0, tmux_1.sendKeys)(sessionName, launchCommand, true);
|
|
113
113
|
// Wait for Gemini to initialize (minimum wait for banner/auth)
|
|
114
114
|
await new Promise((resolve) => setTimeout(resolve, GEMINI_INIT_WAIT_MS));
|
|
@@ -148,9 +148,15 @@ class OpenCodeTool extends base_1.BaseCLITool {
|
|
|
148
148
|
// that nothing can read back (§5.9). Null means "no structured events",
|
|
149
149
|
// and the launch below is then the pre-#1763 bare command.
|
|
150
150
|
await (0, runtime_1.reserveOpencodeServerPort)(target, worktreePath);
|
|
151
|
-
// Start OpenCode TUI. `
|
|
152
|
-
// `AgentEventSource` for the
|
|
153
|
-
|
|
151
|
+
// Start OpenCode TUI. `buildAgentLaunchCommandLine` asks the tool's own
|
|
152
|
+
// `AgentEventSource` for the plan (S3/S4/S5) and never throws. opencode's
|
|
153
|
+
// environment is empty — it is the one source with no correlation
|
|
154
|
+
// variable, because CommandMate holds the connection (#1846).
|
|
155
|
+
const launchCommand = (0, agent_session_lifecycle_1.buildAgentLaunchCommandLine)({
|
|
156
|
+
target,
|
|
157
|
+
executablePath: this.command,
|
|
158
|
+
worktreePath,
|
|
159
|
+
});
|
|
154
160
|
await (0, tmux_1.sendKeys)(sessionName, launchCommand, true);
|
|
155
161
|
// Wait for OpenCode to initialize (GPU model loading via Ollama)
|
|
156
162
|
await new Promise((resolve) => setTimeout(resolve, exports.OPENCODE_INIT_WAIT_MS));
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* Shared between response-poller.ts and API routes
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.CLAUDE_SESSION_ERROR_REGEX_PATTERNS = exports.CLAUDE_SESSION_ERROR_PATTERNS = exports.extractAnsiSequences = exports.stripAnsi = exports.ANTIGRAVITY_SKIP_PATTERNS = exports.ANTIGRAVITY_SELECTION_LIST_PATTERN = exports.ANTIGRAVITY_SEPARATOR_PATTERN = exports.ANTIGRAVITY_THINKING_PATTERN = exports.ANTIGRAVITY_PROMPT_PATTERN = exports.VIBE_LOCAL_THINKING_PATTERN = exports.VIBE_LOCAL_PROMPT_PATTERN = exports.COPILOT_SKIP_PATTERNS = exports.COPILOT_SELECTION_LIST_PATTERN = exports.COPILOT_SEPARATOR_PATTERN = exports.COPILOT_THINKING_PATTERN = exports.COPILOT_PROMPT_PATTERN = exports.OPENCODE_SKIP_PATTERNS = exports.OPENCODE_SEPARATOR_PATTERN = exports.CLAUDE_SELECTION_LIST_FOOTER = exports.CLAUDE_MODEL_OVERLAY_FOOTER_PATTERN = exports.OPENCODE_SELECTION_LIST_PATTERN = exports.OPENCODE_PROCESSING_INDICATOR = exports.OPENCODE_RESPONSE_COMPLETE = exports.OPENCODE_LOADING_PATTERN = exports.OPENCODE_THINKING_PATTERN = exports.OPENCODE_PROMPT_AFTER_RESPONSE = exports.OPENCODE_PROMPT_PATTERN = exports.GEMINI_THINKING_PATTERN = exports.GEMINI_PROMPT_PATTERN = exports.MAX_PASTED_TEXT_RETRIES = exports.PASTED_TEXT_DETECT_DELAY = exports.PASTED_TEXT_PATTERN = exports.CODEX_STATUS_BAR_PATTERN = exports.CODEX_PAGER_FOOTER_PATTERN = exports.CODEX_APPROVAL_FOOTER_PATTERN = exports.CODEX_SELECTION_LIST_PATTERN = exports.CODEX_SEPARATOR_PATTERN = exports.CODEX_DIALOG_PATTERN = exports.CODEX_PROMPT_PATTERN = exports.CLAUDE_TRUST_DIALOG_PATTERN = exports.CLAUDE_SEPARATOR_PATTERN = exports.CLAUDE_PROMPT_PATTERN = exports.CODEX_INTERRUPT_HINT_PATTERN = exports.CODEX_THINKING_PATTERN = exports.CLAUDE_INTERRUPT_HINT_PATTERN = exports.CLAUDE_THINKING_PATTERN = exports.CLAUDE_SPINNER_CHARS = void 0;
|
|
7
|
+
exports.CLAUDE_SESSION_ERROR_REGEX_PATTERNS = exports.CLAUDE_SESSION_ERROR_PATTERNS = exports.extractAnsiSequences = exports.stripAnsi = exports.ANTIGRAVITY_SKIP_PATTERNS = exports.ANTIGRAVITY_SELECTION_LIST_PATTERN = exports.ANTIGRAVITY_SEPARATOR_PATTERN = exports.ANTIGRAVITY_THINKING_PATTERN = exports.ANTIGRAVITY_PROMPT_PATTERN = exports.VIBE_LOCAL_THINKING_PATTERN = exports.VIBE_LOCAL_PROMPT_PATTERN = exports.COPILOT_SKIP_PATTERNS = exports.COPILOT_SELECTION_LIST_PATTERN = exports.COPILOT_SEPARATOR_PATTERN = exports.COPILOT_THINKING_PATTERN = exports.COPILOT_PROMPT_PATTERN = exports.OPENCODE_SKIP_PATTERNS = exports.OPENCODE_SEPARATOR_PATTERN = exports.CLAUDE_SELECTION_LIST_FOOTER = exports.CLAUDE_MODEL_OVERLAY_FOOTER_PATTERN = exports.OPENCODE_SELECTION_LIST_PATTERN = exports.OPENCODE_PROCESSING_INDICATOR = exports.OPENCODE_RESPONSE_COMPLETE = exports.OPENCODE_LOADING_PATTERN = exports.OPENCODE_THINKING_PATTERN = exports.OPENCODE_PROMPT_AFTER_RESPONSE = exports.OPENCODE_PROMPT_PATTERN = exports.GEMINI_THINKING_PATTERN = exports.GEMINI_PROMPT_PATTERN = exports.MAX_PASTED_TEXT_RETRIES = exports.PASTED_TEXT_DETECT_DELAY = exports.PASTED_TEXT_PATTERN = exports.CODEX_STATUS_BAR_PATTERN = exports.CODEX_PAGER_FOOTER_PATTERN = exports.CODEX_APPROVAL_FOOTER_PATTERN = exports.CODEX_SELECTION_LIST_PATTERN = exports.CODEX_SEPARATOR_PATTERN = exports.CODEX_HOOKS_REVIEW_ANCHORS = exports.CODEX_DIALOG_PATTERN = exports.CODEX_PROMPT_PATTERN = exports.CLAUDE_TRUST_DIALOG_PATTERN = exports.CLAUDE_SEPARATOR_PATTERN = exports.CLAUDE_PROMPT_PATTERN = exports.CODEX_INTERRUPT_HINT_PATTERN = exports.CODEX_THINKING_PATTERN = exports.CLAUDE_INTERRUPT_HINT_PATTERN = exports.CLAUDE_THINKING_PATTERN = exports.CLAUDE_SPINNER_CHARS = void 0;
|
|
8
8
|
exports.isCodexTurnActive = isCodexTurnActive;
|
|
9
9
|
exports.findClaudeChromeStart = findClaudeChromeStart;
|
|
10
10
|
exports.isCodexPromptReady = isCodexPromptReady;
|
|
11
11
|
exports.getCodexActiveDialog = getCodexActiveDialog;
|
|
12
|
+
exports.getCodexLifecycleDialog = getCodexLifecycleDialog;
|
|
12
13
|
exports.detectThinking = detectThinking;
|
|
13
14
|
exports.getCliToolPatterns = getCliToolPatterns;
|
|
14
15
|
exports.stripBoxDrawing = stripBoxDrawing;
|
|
@@ -330,7 +331,18 @@ function isCodexPromptReady(output) {
|
|
|
330
331
|
* update dialog wins over its own "Press enter to continue" footer, because Enter
|
|
331
332
|
* on the update dialog could confirm the default "1. Update now" (npm install).
|
|
332
333
|
*/
|
|
333
|
-
|
|
334
|
+
/**
|
|
335
|
+
* The lines of Codex's ACTIVE region: everything strictly below the bottom-most
|
|
336
|
+
* genuine input-prompt line, or the whole frame when there is no prompt line
|
|
337
|
+
* (Issue #892).
|
|
338
|
+
*
|
|
339
|
+
* This is the one rule that keeps every Codex dialog classifier honest.
|
|
340
|
+
* capturePane returns scrollback, so a dialog that was answered minutes ago is
|
|
341
|
+
* still in the frame; only what sits BELOW the live prompt is still awaiting a
|
|
342
|
+
* key. Shared by getCodexActiveDialog and getCodexLifecycleDialog so the two
|
|
343
|
+
* cannot drift into disagreeing about what "active" means.
|
|
344
|
+
*/
|
|
345
|
+
function codexActiveRegionLines(output) {
|
|
334
346
|
const lines = output.split('\n');
|
|
335
347
|
// Index of the bottom-most genuine input-prompt line (-1 if none).
|
|
336
348
|
let promptIdx = -1;
|
|
@@ -340,10 +352,12 @@ function getCodexActiveDialog(output) {
|
|
|
340
352
|
break;
|
|
341
353
|
}
|
|
342
354
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
355
|
+
return lines.slice(promptIdx + 1);
|
|
356
|
+
}
|
|
357
|
+
function getCodexActiveDialog(output) {
|
|
358
|
+
// Residual dialog text above a live prompt is excluded, so a dialog lingering
|
|
359
|
+
// in scrollback is never treated as active.
|
|
360
|
+
const active = codexActiveRegionLines(output).join('\n');
|
|
347
361
|
if (active === '') {
|
|
348
362
|
return null;
|
|
349
363
|
}
|
|
@@ -359,6 +373,134 @@ function getCodexActiveDialog(output) {
|
|
|
359
373
|
}
|
|
360
374
|
return null;
|
|
361
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Anchors of codex's "Hooks need review" launch dialog — screen 1 of the three
|
|
378
|
+
* it can put in front of a session (Issue #1760, re-measured on codex-cli
|
|
379
|
+
* 0.148.0 for Issue #1829):
|
|
380
|
+
*
|
|
381
|
+
* ```
|
|
382
|
+
* Hooks need review
|
|
383
|
+
* 4 hooks are new or changed.
|
|
384
|
+
* Hooks can run outside the sandbox after you trust them.
|
|
385
|
+
*
|
|
386
|
+
* > 1. Review hooks
|
|
387
|
+
* 2. Trust all and continue
|
|
388
|
+
* 3. Continue without trusting (hooks won't run)
|
|
389
|
+
* Press enter to confirm or esc to go back
|
|
390
|
+
* ```
|
|
391
|
+
*
|
|
392
|
+
* The hook COUNT is data — 0.147.0 said 5, 0.148.0 said 4 — so neither anchor
|
|
393
|
+
* reads it. Both strings are required so a "hooks" mention elsewhere cannot
|
|
394
|
+
* select an option on a live prompt.
|
|
395
|
+
*/
|
|
396
|
+
exports.CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trusting'];
|
|
397
|
+
/**
|
|
398
|
+
* Footer of screen 2, the hooks LIST, new in codex-cli 0.148.0 (Issue #1829):
|
|
399
|
+
* `Press t to trust all; enter to review hooks; esc to close`.
|
|
400
|
+
*
|
|
401
|
+
* The semicolon is what separates it from screen 3's footer — "trust all;" and
|
|
402
|
+
* "trust;" are disjoint — and matching the footer rather than the table above it
|
|
403
|
+
* keeps the two screens distinguishable by a single line each.
|
|
404
|
+
*/
|
|
405
|
+
const CODEX_HOOKS_LIST_FOOTER_PATTERN = /press\s+t\s+to\s+trust\s+all\s*;/i;
|
|
406
|
+
/**
|
|
407
|
+
* Footer of screen 3, the per-hook review DETAIL (Issue #1829):
|
|
408
|
+
* `Press t to trust; esc to go back`. Where both live sessions in the Issue were
|
|
409
|
+
* found parked.
|
|
410
|
+
*/
|
|
411
|
+
const CODEX_HOOKS_DETAIL_FOOTER_PATTERN = /press\s+t\s+to\s+trust\s*;/i;
|
|
412
|
+
/**
|
|
413
|
+
* How much of the active region {@link getCodexLifecycleDialog} judges, in
|
|
414
|
+
* non-blank lines counted from the bottom (Issue #1829).
|
|
415
|
+
*
|
|
416
|
+
* `getCodexActiveDialog` searches the whole active region, which is right for
|
|
417
|
+
* its caller: `waitForReady` only ever runs during `startSession`, when nothing
|
|
418
|
+
* else can be on screen. This classifier runs on every Auto-Yes poll for the
|
|
419
|
+
* life of the session, where "active region" alone is not enough — a codex
|
|
420
|
+
* approval request renders no `› ` composer line, so an approval that comes up
|
|
421
|
+
* while a dismissed hooks screen is still inside the capture window would have
|
|
422
|
+
* the whole frame as its active region and would be mistaken for the dialog.
|
|
423
|
+
* Requiring the dialog to be in the TAIL is what separates the screen the user
|
|
424
|
+
* is looking at from the one they have already left.
|
|
425
|
+
*
|
|
426
|
+
* 12 lines fits the tallest screen this has to recognise (the review dialog's
|
|
427
|
+
* two anchors sit 6 lines apart) and none of the shorter frames below it.
|
|
428
|
+
*/
|
|
429
|
+
const CODEX_LIFECYCLE_TAIL_LINES = 12;
|
|
430
|
+
/**
|
|
431
|
+
* The interactive update dialog, by its option-3 label or its option-1 line.
|
|
432
|
+
*
|
|
433
|
+
* Deliberately stricter than `getCodexActiveDialog`'s `Update` AND `Skip`
|
|
434
|
+
* fallback: that pair can occur in ordinary agent output, and here a false
|
|
435
|
+
* positive silently stops Auto-Yes answering a real prompt. Both anchors below
|
|
436
|
+
* are dialog chrome that agent output does not produce.
|
|
437
|
+
*/
|
|
438
|
+
const CODEX_UPDATE_DIALOG_ANCHORS = [
|
|
439
|
+
/skip until next version/i,
|
|
440
|
+
/^\s*[›❯]?\s*\d+\.\s*Update now/im,
|
|
441
|
+
];
|
|
442
|
+
/** The directory-trust dialog's question line. */
|
|
443
|
+
const CODEX_TRUST_DIALOG_ANCHOR = /Do you trust/;
|
|
444
|
+
/**
|
|
445
|
+
* Classify the bottom-most ACTIVE codex lifecycle screen (Issue #1829).
|
|
446
|
+
*
|
|
447
|
+
* Position-based, via {@link codexActiveRegionLines}: a dialog left in
|
|
448
|
+
* scrollback above a live prompt is not active and returns `null`. That is not
|
|
449
|
+
* a detail — the auto-answer guard in the Auto-Yes poller is built on this
|
|
450
|
+
* function, and a whole-frame version of it would switch Auto-Yes off for the
|
|
451
|
+
* rest of a codex session the moment any launch dialog scrolled past.
|
|
452
|
+
*
|
|
453
|
+
* The two hooks screens are matched FIRST and bottom-up, because a stuck pane
|
|
454
|
+
* holds screen 2 above screen 3 and the way out of each differs. The remaining
|
|
455
|
+
* three are region-level substring tests, which is all their anchors allow:
|
|
456
|
+
* the review dialog's are on two different lines.
|
|
457
|
+
*
|
|
458
|
+
* Deliberately NOT used to decide whether a prompt exists. `detectPrompt` still
|
|
459
|
+
* reports these screens, so a human still sees them; what this function gates is
|
|
460
|
+
* only whether a machine may answer on their behalf.
|
|
461
|
+
*
|
|
462
|
+
* @param output - ANSI-stripped pane capture
|
|
463
|
+
* @returns The active lifecycle screen, or null when none is
|
|
464
|
+
*/
|
|
465
|
+
function getCodexLifecycleDialog(output) {
|
|
466
|
+
const activeLines = codexActiveRegionLines(output);
|
|
467
|
+
const window = [];
|
|
468
|
+
for (let i = activeLines.length - 1; i >= 0 && window.length < CODEX_LIFECYCLE_TAIL_LINES; i--) {
|
|
469
|
+
if (activeLines[i].trim() === '')
|
|
470
|
+
continue;
|
|
471
|
+
window.unshift(activeLines[i]);
|
|
472
|
+
}
|
|
473
|
+
if (window.length === 0)
|
|
474
|
+
return null;
|
|
475
|
+
const text = window.join('\n');
|
|
476
|
+
// One bottom-up pass, returning on the first line that decides the question --
|
|
477
|
+
// including the lines that decide it NEGATIVELY. A stuck pane holds screen 2
|
|
478
|
+
// above screen 3, and an approval request can come up with a hooks screen
|
|
479
|
+
// still inside the capture window; in both cases the screen the user is
|
|
480
|
+
// looking at is the lower one.
|
|
481
|
+
for (let i = window.length - 1; i >= 0; i--) {
|
|
482
|
+
const line = window[i];
|
|
483
|
+
if (CODEX_HOOKS_LIST_FOOTER_PATTERN.test(line))
|
|
484
|
+
return 'hooks-list';
|
|
485
|
+
if (CODEX_HOOKS_DETAIL_FOOTER_PATTERN.test(line))
|
|
486
|
+
return 'hooks-detail';
|
|
487
|
+
// The agent asking the human for permission mid-turn (Issue #1628's
|
|
488
|
+
// "esc to cancel" footer, which no lifecycle screen wears). This is exactly
|
|
489
|
+
// the prompt Auto-Yes exists to answer, so whatever lifecycle text is still
|
|
490
|
+
// above it has been left behind and must not withhold the answer.
|
|
491
|
+
if (exports.CODEX_APPROVAL_FOOTER_PATTERN.test(line))
|
|
492
|
+
return null;
|
|
493
|
+
if (CODEX_UPDATE_DIALOG_ANCHORS.some((pattern) => pattern.test(line)))
|
|
494
|
+
return 'update';
|
|
495
|
+
if (CODEX_TRUST_DIALOG_ANCHOR.test(line))
|
|
496
|
+
return 'trust';
|
|
497
|
+
// Both anchors required, so a stray "hooks" mention cannot claim the screen.
|
|
498
|
+
if (line.includes(exports.CODEX_HOOKS_REVIEW_ANCHORS[1]) && text.includes(exports.CODEX_HOOKS_REVIEW_ANCHORS[0])) {
|
|
499
|
+
return 'hooks-review';
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
362
504
|
/**
|
|
363
505
|
* Codex separator pattern
|
|
364
506
|
*/
|
|
@@ -53,6 +53,8 @@ exports.STATUS_REASON = {
|
|
|
53
53
|
CODEX_SELECTION_LIST: 'codex_selection_list',
|
|
54
54
|
/** Issue #1017: Codex pager / edit-previous (transcript) mode. */
|
|
55
55
|
CODEX_PAGER: 'codex_pager',
|
|
56
|
+
/** Issue #1829: Codex's hooks review screens, which only `t`/`esc` leave. */
|
|
57
|
+
CODEX_HOOKS_REVIEW: 'codex_hooks_review',
|
|
56
58
|
ANTIGRAVITY_SELECTION_LIST: 'antigravity_selection_list',
|
|
57
59
|
OPENCODE_RESPONSE_COMPLETE: 'opencode_response_complete',
|
|
58
60
|
INPUT_PROMPT: 'input_prompt',
|
|
@@ -73,6 +75,9 @@ exports.SELECTION_LIST_REASONS = new Set([
|
|
|
73
75
|
exports.STATUS_REASON.CODEX_SELECTION_LIST,
|
|
74
76
|
// Issue #1017: Codex pager/edit-previous mode also drives NavigationButtons.
|
|
75
77
|
exports.STATUS_REASON.CODEX_PAGER,
|
|
78
|
+
// Issue #1829: the hooks review screens have no numbered options — `t` and
|
|
79
|
+
// `esc` are the only ways out, and NavigationButtons is how a human sends them.
|
|
80
|
+
exports.STATUS_REASON.CODEX_HOOKS_REVIEW,
|
|
76
81
|
exports.STATUS_REASON.ANTIGRAVITY_SELECTION_LIST,
|
|
77
82
|
]);
|
|
78
83
|
/**
|
|
@@ -288,6 +293,29 @@ function detectSessionStatus(output, cliToolId, lastOutputTimestamp) {
|
|
|
288
293
|
promptDetection: codexPagerPromptDetection,
|
|
289
294
|
};
|
|
290
295
|
}
|
|
296
|
+
// 0.75. Codex: the hooks review screens (Issue #1829)
|
|
297
|
+
// codex-cli 0.148.0 answers "1. Review hooks" with a two-screen review UI:
|
|
298
|
+
// screen 2 "Press t to trust all; enter to review hooks; esc to close"
|
|
299
|
+
// screen 3 "Press t to trust; esc to go back"
|
|
300
|
+
// Neither carries a numbered option, a "press enter to confirm" footer, or any
|
|
301
|
+
// thinking indicator, so every branch below falls through to the `running`
|
|
302
|
+
// default -- which is how two live sessions sat parked on screen 3 while the UI
|
|
303
|
+
// and `cmate wait` both reported them as busy. They are the bottom-most
|
|
304
|
+
// interactive element and nothing but a keypress moves them: that is `waiting`.
|
|
305
|
+
// Checked ahead of prompt detection because the transcript rows on screen 2 are
|
|
306
|
+
// ordinary text that must not be read as options.
|
|
307
|
+
if (cliToolId === 'codex') {
|
|
308
|
+
const codexLifecycleDialog = (0, cli_patterns_1.getCodexLifecycleDialog)(cleanOutput);
|
|
309
|
+
if (codexLifecycleDialog === 'hooks-list' || codexLifecycleDialog === 'hooks-detail') {
|
|
310
|
+
return {
|
|
311
|
+
status: 'waiting',
|
|
312
|
+
confidence: 'high',
|
|
313
|
+
reason: exports.STATUS_REASON.CODEX_HOOKS_REVIEW,
|
|
314
|
+
hasActivePrompt: false,
|
|
315
|
+
promptDetection: (0, prompt_detector_1.detectPrompt)((0, cli_patterns_1.stripBoxDrawing)(cleanOutput), (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId)),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
291
319
|
// 0.8. Codex: selection list detection BEFORE prompt detection (Issue #622)
|
|
292
320
|
// CODEX_SELECTION_LIST_PATTERN matches "press enter to confirm/select" footer.
|
|
293
321
|
// Without this early check, detectPrompt() at priority 1 would detect the numbered
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Signatures of an upstream (model API) fault, as they appear on an agent's
|
|
4
|
+
* terminal frame (Issue #1839).
|
|
5
|
+
*
|
|
6
|
+
* Moved here from `scripts/canary/expectations.ts`, where Issue #1727 first
|
|
7
|
+
* wrote them, because the canary is no longer the only reader: `capture --json`
|
|
8
|
+
* publishes the match as `upstreamFault` and `wait --fail-on-upstream-fault`
|
|
9
|
+
* branches on it. Two copies of a pattern list whose whole job is *not* to be
|
|
10
|
+
* over-eager would drift, and the drift would be silent on both sides.
|
|
11
|
+
*
|
|
12
|
+
* A leaf module by design — it imports nothing but {@link stripAnsi}, so the
|
|
13
|
+
* canary (which runs outside Next) and the server payload builder can share it
|
|
14
|
+
* without either pulling in the other's dependencies.
|
|
15
|
+
*
|
|
16
|
+
* ## What a match means, and what it does not
|
|
17
|
+
*
|
|
18
|
+
* A match means the signature was on the frame. A **non**-match means nothing at
|
|
19
|
+
* all about upstream health: the pane may have scrolled, the agent may render a
|
|
20
|
+
* failure with wording nobody has seen yet, and Issue #1834 measured a case
|
|
21
|
+
* where the pane went blank instead of carrying a banner. Nothing in this
|
|
22
|
+
* module — and nothing reading it — may report "no fault" as "upstream is
|
|
23
|
+
* healthy".
|
|
24
|
+
*
|
|
25
|
+
* @module lib/detection/upstream-faults
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.UPSTREAM_FAULT_TRUNCATION_MARKER = exports.UPSTREAM_FAULT_EXCERPT_MAX_BYTES = exports.UPSTREAM_FAULTS = void 0;
|
|
29
|
+
exports.matchUpstreamFault = matchUpstreamFault;
|
|
30
|
+
exports.findUpstreamFault = findUpstreamFault;
|
|
31
|
+
const ansi_1 = require("./ansi");
|
|
32
|
+
/**
|
|
33
|
+
* Patterns are anchored on ERROR wording, not on the words "usage limit".
|
|
34
|
+
* Claude's own banner advertises "up to 50% of your weekly usage limit on
|
|
35
|
+
* Fable 5" on a perfectly healthy frame — a looser pattern marked every
|
|
36
|
+
* scenario of a run as `blocked` (measured 2026-08-06), which would have hidden
|
|
37
|
+
* real regressions behind a fake infrastructure excuse.
|
|
38
|
+
*
|
|
39
|
+
* Order is precedence: the first match wins, so the specific overload wording
|
|
40
|
+
* is listed ahead of the generic `API Error` catch-all. The line Claude 2.1.236
|
|
41
|
+
* prints on a 529 storm contains both (`API Error: Repeated 529 Overloaded
|
|
42
|
+
* errors …`, measured for Issue #1839), and `overloaded` is the more useful of
|
|
43
|
+
* the two answers because it carries `selfRetrying: true`.
|
|
44
|
+
*/
|
|
45
|
+
exports.UPSTREAM_FAULTS = [
|
|
46
|
+
{ id: 'overloaded', pattern: /\b5\d{2}\s+Overloaded\b/i, selfRetrying: true },
|
|
47
|
+
{ id: 'retrying', pattern: /Retrying in \d+s\s*[·•]\s*attempt \d+\/\d+/i, selfRetrying: true },
|
|
48
|
+
{ id: 'limit-reached', pattern: /\blimit reached\b/i, selfRetrying: false },
|
|
49
|
+
{ id: 'api-error', pattern: /\bAPI Error(?::|\s+\d{3})/i, selfRetrying: false },
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Bound on {@link UpstreamFaultMatch.matchedText}, in UTF-8 **bytes**.
|
|
53
|
+
*
|
|
54
|
+
* Bytes rather than characters for the reason Issue #1694 gives for its own
|
|
55
|
+
* excerpt: a Japanese frame runs three bytes to the character, so a
|
|
56
|
+
* character-counted bound publishes three times the payload it promises. The
|
|
57
|
+
* excerpt rides every `current-output` response of a faulted session, and those
|
|
58
|
+
* responses are polled every few seconds.
|
|
59
|
+
*/
|
|
60
|
+
exports.UPSTREAM_FAULT_EXCERPT_MAX_BYTES = 200;
|
|
61
|
+
/** Appended when {@link UPSTREAM_FAULT_EXCERPT_MAX_BYTES} cut the excerpt. */
|
|
62
|
+
exports.UPSTREAM_FAULT_TRUNCATION_MARKER = '…[truncated]';
|
|
63
|
+
/**
|
|
64
|
+
* Truncate to a UTF-8 byte budget on a code-point boundary.
|
|
65
|
+
*
|
|
66
|
+
* A local copy rather than `truncateToUtf8Bytes` from `lib/auto-yes-state`: that
|
|
67
|
+
* module reaches the database and the Auto-Yes state machine, and this one is a
|
|
68
|
+
* leaf the canary imports from outside Next. Accumulating code points (never
|
|
69
|
+
* UTF-16 units) is what keeps a surrogate pair whole.
|
|
70
|
+
*/
|
|
71
|
+
function truncateExcerpt(text) {
|
|
72
|
+
const encoder = new TextEncoder();
|
|
73
|
+
if (encoder.encode(text).length <= exports.UPSTREAM_FAULT_EXCERPT_MAX_BYTES)
|
|
74
|
+
return text;
|
|
75
|
+
// The marker is inside the budget, not on top of it: the bound is a promise
|
|
76
|
+
// about the published field, and a caller sizing a log line by it must not be
|
|
77
|
+
// handed twelve more characters than it asked for.
|
|
78
|
+
const budget = exports.UPSTREAM_FAULT_EXCERPT_MAX_BYTES - encoder.encode(exports.UPSTREAM_FAULT_TRUNCATION_MARKER).length;
|
|
79
|
+
let bytes = 0;
|
|
80
|
+
let out = '';
|
|
81
|
+
for (const char of text) {
|
|
82
|
+
const size = encoder.encode(char).length;
|
|
83
|
+
if (bytes + size > budget)
|
|
84
|
+
break;
|
|
85
|
+
bytes += size;
|
|
86
|
+
out += char;
|
|
87
|
+
}
|
|
88
|
+
return `${out}${exports.UPSTREAM_FAULT_TRUNCATION_MARKER}`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The first upstream fault visible in the frame, with its line.
|
|
92
|
+
*
|
|
93
|
+
* ANSI is stripped first: the signature words are routinely split by colour
|
|
94
|
+
* sequences on a live pane.
|
|
95
|
+
*/
|
|
96
|
+
function matchUpstreamFault(frame) {
|
|
97
|
+
const clean = (0, ansi_1.stripAnsi)(frame);
|
|
98
|
+
for (const fault of exports.UPSTREAM_FAULTS) {
|
|
99
|
+
const match = fault.pattern.exec(clean);
|
|
100
|
+
// The patterns are unanchored and stateless (no /g), so `exec` cannot carry
|
|
101
|
+
// a lastIndex between calls — but reading `index` requires exec regardless.
|
|
102
|
+
if (!match)
|
|
103
|
+
continue;
|
|
104
|
+
const lineStart = clean.lastIndexOf('\n', match.index) + 1;
|
|
105
|
+
const lineEnd = clean.indexOf('\n', match.index);
|
|
106
|
+
const line = clean.slice(lineStart, lineEnd === -1 ? undefined : lineEnd).trim();
|
|
107
|
+
return { fault, matchedText: truncateExcerpt(line || match[0]) };
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* First upstream fault visible in the frame, if any.
|
|
113
|
+
*
|
|
114
|
+
* Kept alongside {@link matchUpstreamFault} because the canary only ever wanted
|
|
115
|
+
* the classification (`id` / `selfRetrying`), and a caller that does not need
|
|
116
|
+
* the excerpt should not have to reach through a wrapper for it.
|
|
117
|
+
*/
|
|
118
|
+
function findUpstreamFault(frame) {
|
|
119
|
+
return matchUpstreamFault(frame)?.fault ?? null;
|
|
120
|
+
}
|
|
@@ -63,6 +63,10 @@ const NO_DECISION = (reason) => ({
|
|
|
63
63
|
behavior: null,
|
|
64
64
|
reason,
|
|
65
65
|
});
|
|
66
|
+
/** Production policy source: the active task's contract, TTL-cached. */
|
|
67
|
+
function readContractPolicy(session) {
|
|
68
|
+
return (0, auto_yes_policy_1.getSessionAutoYesPolicy)(session.worktreeId, session.cliToolId, session.instanceId);
|
|
69
|
+
}
|
|
66
70
|
/**
|
|
67
71
|
* The verdict for one permission request. Pure apart from reading Auto-Yes
|
|
68
72
|
* state and the (TTL-cached) contract policy; the recording side effects live
|
|
@@ -80,8 +84,10 @@ const NO_DECISION = (reason) => ({
|
|
|
80
84
|
*
|
|
81
85
|
* @param session - Worktree / tool / instance the request came from
|
|
82
86
|
* @param payload - Parsed payload, or null when it could not be parsed
|
|
87
|
+
* @param deps - Substitutions for the database-backed lookups; see
|
|
88
|
+
* {@link PermissionDecisionDeps}. Omit in the server.
|
|
83
89
|
*/
|
|
84
|
-
function decidePermissionRequest(session, payload) {
|
|
90
|
+
function decidePermissionRequest(session, payload, deps = {}) {
|
|
85
91
|
if (!payload) {
|
|
86
92
|
return NO_DECISION('unknown-payload');
|
|
87
93
|
}
|
|
@@ -98,7 +104,7 @@ function decidePermissionRequest(session, payload) {
|
|
|
98
104
|
if (!state?.enabled) {
|
|
99
105
|
return NO_DECISION('auto-yes-disabled');
|
|
100
106
|
}
|
|
101
|
-
const policy = (
|
|
107
|
+
const policy = (deps.readPolicy ?? readContractPolicy)({ worktreeId, cliToolId, instanceId });
|
|
102
108
|
const denial = (0, auto_yes_resolver_1.evaluatePolicyAgainstTexts)(exports.PERMISSION_REQUEST_PROMPT_TYPE, (0, permission_request_payload_1.collectToolInputMatchTexts)(payload.toolName, payload.toolInput), policy);
|
|
103
109
|
if (denial) {
|
|
104
110
|
return {
|
|
@@ -214,10 +220,12 @@ function reportPendingDialog(session, payload) {
|
|
|
214
220
|
*
|
|
215
221
|
* @param session - Worktree / tool / instance the request came from
|
|
216
222
|
* @param payload - Parsed payload, or null when it could not be parsed
|
|
223
|
+
* @param deps - Substitutions for the database-backed lookups; see
|
|
224
|
+
* {@link PermissionDecisionDeps}. Omit in the server.
|
|
217
225
|
* @returns The verdict the route serialises
|
|
218
226
|
*/
|
|
219
|
-
function resolvePermissionRequest(session, payload) {
|
|
220
|
-
const decision = decidePermissionRequest(session, payload);
|
|
227
|
+
function resolvePermissionRequest(session, payload, deps = {}) {
|
|
228
|
+
const decision = decidePermissionRequest(session, payload, deps);
|
|
221
229
|
// Issue #1726: `AskUserQuestion` raises a `PermissionRequest` carrying the
|
|
222
230
|
// same `tool_input` its `PreToolUse` does (§5.6), so the questions are
|
|
223
231
|
// recorded from here too. Redundant on a session this server started — both
|
|
@@ -263,7 +271,7 @@ function resolvePermissionRequest(session, payload) {
|
|
|
263
271
|
});
|
|
264
272
|
}
|
|
265
273
|
if (decision.behavior === 'allow' && payload) {
|
|
266
|
-
recordAllowedPermission(session, payload);
|
|
274
|
+
(deps.recordAllow ?? recordAllowedPermission)(session, payload);
|
|
267
275
|
}
|
|
268
276
|
return decision;
|
|
269
277
|
}
|
|
@@ -87,6 +87,7 @@ const logger_1 = require("../../../../lib/logger");
|
|
|
87
87
|
// The `~/.gemini` tree belongs to gemini; agy lives inside it. The merge that
|
|
88
88
|
// keeps the two from erasing each other is written once, there.
|
|
89
89
|
const shared_config_tree_1 = require("../gemini/shared-config-tree");
|
|
90
|
+
const launch_command_1 = require("../launch-command");
|
|
90
91
|
const tool_id_1 = require("./tool-id");
|
|
91
92
|
const logger = (0, logger_1.createLogger)('lib/hooks/sources/antigravity/hooks-config');
|
|
92
93
|
/**
|
|
@@ -347,26 +348,32 @@ function writeAntigravityHooksConfig(options = {}) {
|
|
|
347
348
|
* terminal, so the variable is set here and nowhere else.
|
|
348
349
|
*
|
|
349
350
|
* The executable is quoted but not otherwise touched, so a caller may append its
|
|
350
|
-
* own flags — `AntigravityTool.startSession` adds `--model` — after the
|
|
351
|
-
*
|
|
351
|
+
* own flags — `AntigravityTool.startSession` adds `--model` — after the rendered
|
|
352
|
+
* line. Since Issue #1846 the two variables come back as `env` rather than as a
|
|
353
|
+
* prefix on the command, which is also what keeps `--model` appendable: the
|
|
354
|
+
* caller appends to the *rendered* line and the assignments stay in front of it
|
|
355
|
+
* by construction rather than by the caller remembering to.
|
|
352
356
|
*
|
|
353
|
-
* Never throws, and returns the executable
|
|
357
|
+
* Never throws, and returns the executable with an empty environment when
|
|
358
|
+
* injection is off.
|
|
354
359
|
*
|
|
355
360
|
* @param executablePath - `agy`, or a resolved path to it
|
|
356
361
|
* @param target - The instance being started
|
|
357
|
-
* @returns The command
|
|
362
|
+
* @returns The command to type into the pane and the environment it needs
|
|
358
363
|
*/
|
|
359
364
|
function buildAntigravityLaunchCommand(executablePath, target, options = {}) {
|
|
360
365
|
if (!(0, hook_settings_generator_1.isHookInjectionEnabled)())
|
|
361
|
-
return executablePath;
|
|
366
|
+
return { command: executablePath, env: {} };
|
|
362
367
|
if (!(0, types_1.isValidInstanceId)((0, hook_settings_generator_1.resolveTargetInstanceId)(target))) {
|
|
363
368
|
logger.warn('antigravity-hook-invalid-instance-id', { worktreeId: target.worktreeId });
|
|
364
|
-
return executablePath;
|
|
369
|
+
return { command: executablePath, env: {} };
|
|
365
370
|
}
|
|
366
371
|
const scoped = { ...target, cliToolId: tool_id_1.ANTIGRAVITY_CLI_TOOL_ID };
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
+
return {
|
|
373
|
+
command: (0, hook_settings_generator_1.shellQuote)(executablePath),
|
|
374
|
+
env: {
|
|
375
|
+
[launch_command_1.AGENT_EVENT_URL_ENV_VAR]: (0, hook_settings_generator_1.buildAgentEventUrl)(scoped, options),
|
|
376
|
+
[exports.ANTIGRAVITY_PERMISSION_URL_ENV_VAR]: (0, hook_settings_generator_1.buildPermissionRequestUrl)(scoped, options),
|
|
377
|
+
},
|
|
378
|
+
};
|
|
372
379
|
}
|
|
@@ -215,15 +215,16 @@ exports.antigravityAgentEventSource = (0, define_source_1.definePushHookSource)(
|
|
|
215
215
|
encodeVerdict: encodeAntigravityVerdict,
|
|
216
216
|
// Unlike gemini, the whole config is reachable from here: the file is global,
|
|
217
217
|
// so no worktree path is needed and `prepareLaunch` really does write it.
|
|
218
|
-
prepareLaunch: (target, executablePath) => {
|
|
218
|
+
prepareLaunch: ({ target, executablePath }) => {
|
|
219
219
|
const settingsPath = (0, hooks_config_1.writeAntigravityHooksConfig)();
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
};
|
|
220
|
+
// #1846: the two correlation URLs are the plan's `env`. `worktreePath` is
|
|
221
|
+
// in the context now and deliberately unused here — agy's config is one
|
|
222
|
+
// file for the machine, so there is nothing per-worktree to write.
|
|
223
|
+
const { command, env } = (0, hooks_config_1.buildAntigravityLaunchCommand)(executablePath, {
|
|
224
|
+
worktreeId: target.worktreeId,
|
|
225
|
+
instanceId: target.instanceId,
|
|
226
|
+
cliToolId: tool_id_1.ANTIGRAVITY_CLI_TOOL_ID,
|
|
227
|
+
});
|
|
228
|
+
return { command, settingsPath, env };
|
|
228
229
|
},
|
|
229
230
|
});
|
|
@@ -128,7 +128,7 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
|
|
|
128
128
|
// S3 / S4 / S5. Delegated rather than reimplemented: `buildClaudeLaunchCommand`
|
|
129
129
|
// writes the settings file, falls back to the bare path on any failure, and is
|
|
130
130
|
// covered byte-for-byte by `tests/unit/hooks/hook-settings-generator.test.ts`.
|
|
131
|
-
prepareLaunch: (target, executablePath) => {
|
|
131
|
+
prepareLaunch: ({ target, executablePath }) => {
|
|
132
132
|
const command = (0, hook_settings_generator_1.buildClaudeLaunchCommand)(executablePath, {
|
|
133
133
|
worktreeId: target.worktreeId,
|
|
134
134
|
instanceId: target.instanceId,
|
|
@@ -145,6 +145,9 @@ exports.claudeAgentEventSource = (0, define_source_1.definePushHookSource)({
|
|
|
145
145
|
cliToolId: target.cliToolId,
|
|
146
146
|
})
|
|
147
147
|
: null;
|
|
148
|
-
|
|
148
|
+
// Empty, and the only source for which that is uninteresting: `--settings`
|
|
149
|
+
// carries the correlation keys inside the file, so Claude never needed the
|
|
150
|
+
// environment prefix the other four sources reached for (#1846).
|
|
151
|
+
return { command, settingsPath, env: {} };
|
|
149
152
|
},
|
|
150
153
|
});
|