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
package/dist/cli/types/index.js
CHANGED
|
@@ -29,6 +29,26 @@ var ExitCode;
|
|
|
29
29
|
exports.WaitExitCode = {
|
|
30
30
|
SUCCESS: 0,
|
|
31
31
|
PROMPT_DETECTED: 10,
|
|
32
|
+
/**
|
|
33
|
+
* `--fail-on-upstream-fault`: the agent came back to its composer with an
|
|
34
|
+
* upstream (model API) failure on the frame (Issue #1839).
|
|
35
|
+
*
|
|
36
|
+
* Its own code rather than SUCCESS because the two mean opposite things to a
|
|
37
|
+
* caller: SUCCESS says "the turn ran, judge the result", this says "the turn
|
|
38
|
+
* never ran, send it again". Measured on 2026-08-20 against a stub upstream
|
|
39
|
+
* answering 529, Claude 2.1.236 returns to the composer ~3 s after the send
|
|
40
|
+
* having executed nothing, and `wait --verify` reports 21 (no work evidence) —
|
|
41
|
+
* which reads as "the agent worked and produced nothing" and is why #1834 saw
|
|
42
|
+
* twelve retries burned on a session that only needed to be re-sent later.
|
|
43
|
+
*
|
|
44
|
+
* Its own code rather than riding PROMPT_DETECTED (10) because nothing is
|
|
45
|
+
* waiting to be answered: `respond` has nothing to send here.
|
|
46
|
+
*
|
|
47
|
+
* 11 is deliberately shared with {@link SkillExitCode.BLOCKED}: the two
|
|
48
|
+
* commands' codes are separate namespaces, and 11 is the first value free of
|
|
49
|
+
* PROMPT_DETECTED.
|
|
50
|
+
*/
|
|
51
|
+
UPSTREAM_FAULT: 11,
|
|
32
52
|
TIMEOUT: 124,
|
|
33
53
|
};
|
|
34
54
|
/**
|
|
@@ -56,6 +76,12 @@ exports.VerifyExitCode = {
|
|
|
56
76
|
*/
|
|
57
77
|
exports.WAIT_EXIT_CODE_PRIORITY = [
|
|
58
78
|
exports.WaitExitCode.PROMPT_DETECTED,
|
|
79
|
+
// Issue #1839: below PROMPT_DETECTED because a prompt is actionable right now
|
|
80
|
+
// and an upstream fault is not, and above the verify verdicts because a turn
|
|
81
|
+
// that never ran makes those verdicts meaningless — reporting VERIFY_FAILED
|
|
82
|
+
// for a worktree whose agent never executed is the misattribution #1839 exists
|
|
83
|
+
// to end.
|
|
84
|
+
exports.WaitExitCode.UPSTREAM_FAULT,
|
|
59
85
|
exports.VerifyExitCode.VERIFY_FAILED,
|
|
60
86
|
exports.VerifyExitCode.NOT_STARTED,
|
|
61
87
|
exports.WaitExitCode.TIMEOUT,
|
|
@@ -10,12 +10,47 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module cli/utils/verify-runner
|
|
12
12
|
*/
|
|
13
|
-
import type { VerificationRunStatus, VerificationRunView } from '../types/api-responses';
|
|
13
|
+
import type { VerificationFlakyDetail, VerificationRunStatus, VerificationRunView } from '../types/api-responses';
|
|
14
14
|
import { ApiClient } from './api-client';
|
|
15
15
|
/** Matches the wait command's cadence; runs are minutes long, not seconds. */
|
|
16
16
|
export declare const VERIFY_POLL_INTERVAL_MS = 5000;
|
|
17
17
|
/** Built-in gate id; mirrors WORK_EVIDENCE_GATE_ID in lib/verification/gate-runner.ts. */
|
|
18
18
|
export declare const WORK_EVIDENCE_GATE_ID = "work-evidence";
|
|
19
|
+
/**
|
|
20
|
+
* Marker a mutexed gate writes into its log tail; mirrors MUTEX_LOG_PREFIX in
|
|
21
|
+
* lib/verification/gate-runner.ts (Issue #1771).
|
|
22
|
+
*
|
|
23
|
+
* Mirrored rather than imported because `tsconfig.cli.json` compiles
|
|
24
|
+
* `src/cli/**` alone with no path aliases, so the CLI bundle never pulls in the
|
|
25
|
+
* server's dependency graph. `tests/unit/verification/gate-mutex.test.ts` pins
|
|
26
|
+
* the two together by importing both.
|
|
27
|
+
*/
|
|
28
|
+
export declare const MUTEX_LOG_PREFIX = "[mutex]";
|
|
29
|
+
/**
|
|
30
|
+
* Marker a retried gate writes into its log tail; mirrors FLAKY_LOG_PREFIX in
|
|
31
|
+
* lib/verification/gate-runner.ts (Issue #1772).
|
|
32
|
+
*
|
|
33
|
+
* Mirrored rather than imported for the same reason the mutex prefix is, and
|
|
34
|
+
* pinned to the runner's spelling by `tests/unit/verification/gate-flaky.test.ts`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const FLAKY_LOG_PREFIX = "[flaky]";
|
|
37
|
+
/**
|
|
38
|
+
* Label a gate whose two runs disagreed. Not a `VerificationGateStatus`: the
|
|
39
|
+
* schema has no such status and #1772 added no migration, so FLAKY is a reading
|
|
40
|
+
* of the marker laid over the stored `passed`/`failed` verdict.
|
|
41
|
+
*/
|
|
42
|
+
export declare const FLAKY_GATE_LABEL = "FLAKY";
|
|
43
|
+
/**
|
|
44
|
+
* Read a retried gate's two runs back out of its log tail (Issue #1772).
|
|
45
|
+
*
|
|
46
|
+
* `verification_gate_results` stores one status, one exit code and one duration,
|
|
47
|
+
* so the second run's numbers only exist in the log — the same carrier
|
|
48
|
+
* work-evidence's counts and the scope gate's evidence already use.
|
|
49
|
+
*
|
|
50
|
+
* @returns null when the gate was never retried, which is every gate that did
|
|
51
|
+
* not declare `retryOnFail: 1` and every one that passed first time.
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseFlakyMarker(logTail: string | null | undefined): VerificationFlakyDetail | null;
|
|
19
54
|
/**
|
|
20
55
|
* Lines of a failing gate's log echoed to stderr before the rest becomes a
|
|
21
56
|
* count (#1683).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-runner.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/verify-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"verify-runner.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/verify-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EACV,uBAAuB,EAEvB,qBAAqB,EACrB,mBAAmB,EAGpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,SAAS,EAAiC,MAAM,cAAc,CAAC;AAExE,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAU1C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAoBxC;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,uBAAuB,GAAG,IAAI,CAehC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACnC,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,mBAAmB,CAAC;CAC3B;AAUD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAW1E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAOnF;AAuID;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CAyD9B"}
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* @module cli/utils/verify-runner
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.MAX_PRINTED_LOG_TAIL_LINES = exports.WORK_EVIDENCE_GATE_ID = exports.VERIFY_POLL_INTERVAL_MS = void 0;
|
|
15
|
+
exports.MAX_PRINTED_LOG_TAIL_LINES = exports.FLAKY_GATE_LABEL = exports.FLAKY_LOG_PREFIX = exports.MUTEX_LOG_PREFIX = exports.WORK_EVIDENCE_GATE_ID = exports.VERIFY_POLL_INTERVAL_MS = void 0;
|
|
16
|
+
exports.parseFlakyMarker = parseFlakyMarker;
|
|
16
17
|
exports.exitCodeForRunStatus = exitCodeForRunStatus;
|
|
17
18
|
exports.parseGateIds = parseGateIds;
|
|
18
19
|
exports.runVerification = runVerification;
|
|
@@ -22,6 +23,79 @@ const api_client_1 = require("./api-client");
|
|
|
22
23
|
exports.VERIFY_POLL_INTERVAL_MS = 5000;
|
|
23
24
|
/** Built-in gate id; mirrors WORK_EVIDENCE_GATE_ID in lib/verification/gate-runner.ts. */
|
|
24
25
|
exports.WORK_EVIDENCE_GATE_ID = 'work-evidence';
|
|
26
|
+
/**
|
|
27
|
+
* Marker a mutexed gate writes into its log tail; mirrors MUTEX_LOG_PREFIX in
|
|
28
|
+
* lib/verification/gate-runner.ts (Issue #1771).
|
|
29
|
+
*
|
|
30
|
+
* Mirrored rather than imported because `tsconfig.cli.json` compiles
|
|
31
|
+
* `src/cli/**` alone with no path aliases, so the CLI bundle never pulls in the
|
|
32
|
+
* server's dependency graph. `tests/unit/verification/gate-mutex.test.ts` pins
|
|
33
|
+
* the two together by importing both.
|
|
34
|
+
*/
|
|
35
|
+
exports.MUTEX_LOG_PREFIX = '[mutex]';
|
|
36
|
+
/**
|
|
37
|
+
* Time a gate spent queued for its `mutex`, as written by the runner.
|
|
38
|
+
*
|
|
39
|
+
* Anchored to the start of a line so a gate whose own output happens to contain
|
|
40
|
+
* `waited=` cannot supply the number.
|
|
41
|
+
*/
|
|
42
|
+
const MUTEX_WAITED_PATTERN = /^\[mutex\] [^\n]*?\bwaited=([0-9]+(?:\.[0-9]+)?s)/m;
|
|
43
|
+
/**
|
|
44
|
+
* Marker a retried gate writes into its log tail; mirrors FLAKY_LOG_PREFIX in
|
|
45
|
+
* lib/verification/gate-runner.ts (Issue #1772).
|
|
46
|
+
*
|
|
47
|
+
* Mirrored rather than imported for the same reason the mutex prefix is, and
|
|
48
|
+
* pinned to the runner's spelling by `tests/unit/verification/gate-flaky.test.ts`.
|
|
49
|
+
*/
|
|
50
|
+
exports.FLAKY_LOG_PREFIX = '[flaky]';
|
|
51
|
+
/**
|
|
52
|
+
* Label a gate whose two runs disagreed. Not a `VerificationGateStatus`: the
|
|
53
|
+
* schema has no such status and #1772 added no migration, so FLAKY is a reading
|
|
54
|
+
* of the marker laid over the stored `passed`/`failed` verdict.
|
|
55
|
+
*/
|
|
56
|
+
exports.FLAKY_GATE_LABEL = 'FLAKY';
|
|
57
|
+
/**
|
|
58
|
+
* The runner's marker line, anchored to the start of a line so a gate whose own
|
|
59
|
+
* output happens to print `outcome=` cannot supply the numbers.
|
|
60
|
+
*/
|
|
61
|
+
const FLAKY_PATTERN = /^\[flaky\] runs=(\d+) outcome=(flaky|fail) exit=(\S+) duration=(\S+) verdict=(pass|fail)$/m;
|
|
62
|
+
/** `n/a` is what the runner writes for a run killed by a signal. */
|
|
63
|
+
function parseExitField(value) {
|
|
64
|
+
return /^-?\d+$/.test(value) ? Number(value) : null;
|
|
65
|
+
}
|
|
66
|
+
/** `45.0s` back into milliseconds; anything else is a value we cannot read. */
|
|
67
|
+
function parseDurationField(value) {
|
|
68
|
+
const match = /^([0-9]+(?:\.[0-9]+)?)s$/.exec(value);
|
|
69
|
+
return match ? Math.round(Number(match[1]) * 1000) : null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Read a retried gate's two runs back out of its log tail (Issue #1772).
|
|
73
|
+
*
|
|
74
|
+
* `verification_gate_results` stores one status, one exit code and one duration,
|
|
75
|
+
* so the second run's numbers only exist in the log — the same carrier
|
|
76
|
+
* work-evidence's counts and the scope gate's evidence already use.
|
|
77
|
+
*
|
|
78
|
+
* @returns null when the gate was never retried, which is every gate that did
|
|
79
|
+
* not declare `retryOnFail: 1` and every one that passed first time.
|
|
80
|
+
*/
|
|
81
|
+
function parseFlakyMarker(logTail) {
|
|
82
|
+
if (!logTail)
|
|
83
|
+
return null;
|
|
84
|
+
const match = FLAKY_PATTERN.exec(logTail);
|
|
85
|
+
if (!match)
|
|
86
|
+
return null;
|
|
87
|
+
return {
|
|
88
|
+
runs: Number(match[1]),
|
|
89
|
+
outcome: match[2],
|
|
90
|
+
exitCodes: match[3].split(',').map(parseExitField),
|
|
91
|
+
durationsMs: match[4].split(',').map(parseDurationField),
|
|
92
|
+
verdict: match[5],
|
|
93
|
+
// Kept verbatim so the GATE line prints exactly what the runner wrote,
|
|
94
|
+
// rather than a re-rendering that could round differently.
|
|
95
|
+
exit: match[3],
|
|
96
|
+
duration: match[4],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
25
99
|
/**
|
|
26
100
|
* Lines of a failing gate's log echoed to stderr before the rest becomes a
|
|
27
101
|
* count (#1683).
|
|
@@ -83,11 +157,27 @@ function formatDetail(gate) {
|
|
|
83
157
|
return reason ? reason.slice(0, 160) : 'not run';
|
|
84
158
|
}
|
|
85
159
|
const parts = [];
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
160
|
+
// A retried gate reports both runs (#1772). The stored columns hold only the
|
|
161
|
+
// run whose verdict was recorded, so printing them would silently drop half
|
|
162
|
+
// of the evidence the retry exists to produce.
|
|
163
|
+
const flaky = parseFlakyMarker(gate.logTail);
|
|
164
|
+
if (flaky) {
|
|
165
|
+
parts.push(`exit=${flaky.exit}`, flaky.duration);
|
|
90
166
|
}
|
|
167
|
+
else {
|
|
168
|
+
if (gate.exitCode !== null && gate.exitCode !== undefined)
|
|
169
|
+
parts.push(`exit=${gate.exitCode}`);
|
|
170
|
+
if (gate.durationMs !== null && gate.durationMs !== undefined) {
|
|
171
|
+
parts.push(`${(gate.durationMs / 1000).toFixed(1)}s`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// After the duration and never merged into it (#1771): the duration is what
|
|
175
|
+
// the gate's command took, the wait is what the machine made it queue for.
|
|
176
|
+
// Adding them would hide contention inside a number that timeout budgets and
|
|
177
|
+
// "did this gate get slower" are read from.
|
|
178
|
+
const waited = MUTEX_WAITED_PATTERN.exec(gate.logTail ?? '');
|
|
179
|
+
if (waited)
|
|
180
|
+
parts.push(`waited=${waited[1]}`);
|
|
91
181
|
return parts.join(', ');
|
|
92
182
|
}
|
|
93
183
|
/**
|
|
@@ -105,8 +195,26 @@ function formatDetail(gate) {
|
|
|
105
195
|
function formatGateSource(gate) {
|
|
106
196
|
return gate.source === 'contract' ? ' [contract]' : '';
|
|
107
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* The verdict word on a gate's line.
|
|
200
|
+
*
|
|
201
|
+
* FLAKY displaces PASS/FAIL rather than being appended to it (Issue #1772),
|
|
202
|
+
* because the whole point is that neither of those two words was true of this
|
|
203
|
+
* gate: it failed and then it passed. How the run *counted* it is not lost —
|
|
204
|
+
* `flakyIsPass` decided the stored status, which is what the RESULT line and
|
|
205
|
+
* the exit code are built from, so a FLAKY line on a `RESULT failed` run reads
|
|
206
|
+
* exactly as it should.
|
|
207
|
+
*
|
|
208
|
+
* A gate that failed twice keeps FAIL: the retry agreed, and nothing about it
|
|
209
|
+
* was flaky.
|
|
210
|
+
*/
|
|
211
|
+
function gateLabel(gate) {
|
|
212
|
+
if (parseFlakyMarker(gate.logTail)?.outcome === 'flaky')
|
|
213
|
+
return exports.FLAKY_GATE_LABEL;
|
|
214
|
+
return GATE_LABELS[gate.status] ?? gate.status.toUpperCase();
|
|
215
|
+
}
|
|
108
216
|
function formatGateLine(gate) {
|
|
109
|
-
const label =
|
|
217
|
+
const label = gateLabel(gate);
|
|
110
218
|
const detail = formatDetail(gate);
|
|
111
219
|
const head = detail ? `GATE ${gate.gateId} ${label} (${detail})` : `GATE ${gate.gateId} ${label}`;
|
|
112
220
|
return `${head}${formatGateSource(gate)}`;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - `src/components/worktree/ActivityPane.tsx`
|
|
10
10
|
* - `src/components/worktree/WorktreeDetailRefactored.tsx`
|
|
11
11
|
*
|
|
12
|
-
* The Activity Bar is a 48px-wide vertical bar that hosts
|
|
12
|
+
* The Activity Bar is a 48px-wide vertical bar that hosts the activities below.
|
|
13
13
|
* Re-clicking the active icon toggles the ActivityPane closed (null).
|
|
14
14
|
*/
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -33,6 +33,10 @@ exports.ACTIVITIES = [
|
|
|
33
33
|
{ id: 'todo', labelKey: 'activityBar.todo', icon: lucide_react_1.ListTodo },
|
|
34
34
|
// Issue #1441: worktree-scoped Skill install/uninstall management.
|
|
35
35
|
{ id: 'skills', labelKey: 'activityBar.skills', icon: lucide_react_1.Sparkles },
|
|
36
|
+
// Issue #1816: the execution contract and the verification gates. Appended
|
|
37
|
+
// rather than inserted so the existing ArrowUp/ArrowDown order — which users
|
|
38
|
+
// and tests both index by position — is unchanged.
|
|
39
|
+
{ id: 'verification', labelKey: 'activityBar.verification', icon: lucide_react_1.ShieldCheck },
|
|
36
40
|
];
|
|
37
41
|
/**
|
|
38
42
|
* Set of valid ActivityId values for runtime validation.
|
|
@@ -296,7 +296,43 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
|
|
|
296
296
|
if (isDuplicatePrompt(pollerState, promptKey)) {
|
|
297
297
|
return 'duplicate';
|
|
298
298
|
}
|
|
299
|
-
// 3.
|
|
299
|
+
// 3. Issue #1829: codex's own launch dialogs are CodexTool.waitForReady()'s
|
|
300
|
+
// to answer, not the poller's. Every one of them defaults to option 1, and
|
|
301
|
+
// the base rules answer the default:
|
|
302
|
+
//
|
|
303
|
+
// "Hooks need review" -> 1. Review hooks (undoes Issue #1760; the pane
|
|
304
|
+
// then sits two screens deep in a review UI that
|
|
305
|
+
// only `t`/`esc` leave, reported as `running`)
|
|
306
|
+
// "Update available" -> 1. Update now (undoes Issue #890; runs
|
|
307
|
+
// `npm install -g @openai/codex`, killing codex)
|
|
308
|
+
// "Do you trust …" -> 1. Yes, continue
|
|
309
|
+
//
|
|
310
|
+
// waitForReady answers the same screens deliberately and differently ('3',
|
|
311
|
+
// '2', '1' — each without a trailing Enter), but only during startSession,
|
|
312
|
+
// while this poller runs on its own 2s phase for the life of the session.
|
|
313
|
+
// Whichever sees the dialog first decides, so the fix is to leave them all
|
|
314
|
+
// to the tool. Auto-answer layer only: detectPrompt above still reports the
|
|
315
|
+
// prompt, so the human keeps seeing the screen and the response poller
|
|
316
|
+
// still notifies them about it.
|
|
317
|
+
const launchDialog = cliToolId === 'codex' ? (0, cli_patterns_1.getCodexLifecycleDialog)(cleanOutput) : null;
|
|
318
|
+
if (launchDialog) {
|
|
319
|
+
// Recorded through the #1684 channel so `capture --json` and `cmate wait`
|
|
320
|
+
// can name the reason instead of showing a worker that went quiet.
|
|
321
|
+
(0, auto_yes_suppression_state_1.recordPolicySuppression)(worktreeId, cliToolId, instanceId, {
|
|
322
|
+
reason: 'agent-launch-dialog',
|
|
323
|
+
mode: null,
|
|
324
|
+
promptType: promptDetection.promptData.type,
|
|
325
|
+
});
|
|
326
|
+
logger.warn('poller:auto-yes-skipped-launch-dialog', {
|
|
327
|
+
worktreeId,
|
|
328
|
+
cliToolId,
|
|
329
|
+
instanceId,
|
|
330
|
+
dialog: launchDialog,
|
|
331
|
+
promptType: promptDetection.promptData.type,
|
|
332
|
+
});
|
|
333
|
+
return 'no_answer';
|
|
334
|
+
}
|
|
335
|
+
// 4. Resolve auto answer under the execution contract's policy (Issue #1547).
|
|
300
336
|
// Auto-Yes calls detectPrompt directly instead of going through
|
|
301
337
|
// status-detector, so this is the only place the policy can gate an
|
|
302
338
|
// auto-answer: a prompt the policy withholds is left for a human, and the
|
|
@@ -328,7 +364,7 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
|
|
|
328
364
|
if (answer === null) {
|
|
329
365
|
return 'no_answer';
|
|
330
366
|
}
|
|
331
|
-
//
|
|
367
|
+
// 5. Send answer to tmux (Issue #896: resolve the instance-specific session)
|
|
332
368
|
const manager = manager_1.CLIToolManager.getInstance();
|
|
333
369
|
const cliTool = manager.getTool(cliToolId);
|
|
334
370
|
const sessionName = cliTool.getSessionName(worktreeId, instanceId);
|
|
@@ -343,10 +379,10 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
|
|
|
343
379
|
finally {
|
|
344
380
|
(0, tmux_capture_cache_1.invalidateCache)(sessionName);
|
|
345
381
|
}
|
|
346
|
-
//
|
|
382
|
+
// 6. Update timestamp and reset error count
|
|
347
383
|
updateLastServerResponseTimestamp(compositeKey, Date.now());
|
|
348
384
|
resetErrorCount(compositeKey);
|
|
349
|
-
//
|
|
385
|
+
// 7. Record answered prompt key and timestamp
|
|
350
386
|
pollerState.lastAnsweredPromptKey = promptKey;
|
|
351
387
|
pollerState.lastAnsweredAt = Date.now();
|
|
352
388
|
logger.info('poller:response-sent', { worktreeId, cliToolId, instanceId });
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* auto-yes-poller.ts -> auto-yes-state.ts -> path-validator.ts
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.THINKING_CHECK_LINE_COUNT = exports.MAX_CONCURRENT_POLLERS = exports.MAX_CONSECUTIVE_ERRORS = exports.MAX_BACKOFF_MS = exports.DUPLICATE_RETRY_EXPIRY_MS = exports.COOLDOWN_INTERVAL_MS = exports.POLLING_INTERVAL_MS = exports.executeRegexWithTimeout = exports.COMPOSITE_KEY_SEPARATOR = void 0;
|
|
14
|
+
exports.THINKING_CHECK_LINE_COUNT = exports.MAX_CONCURRENT_POLLERS = exports.MAX_CONSECUTIVE_ERRORS = exports.MAX_BACKOFF_MS = exports.DUPLICATE_RETRY_EXPIRY_MS = exports.COOLDOWN_INTERVAL_MS = exports.POLLING_INTERVAL_MS = exports.STOP_MATCH_EXCERPT_CONTEXT_LINES = exports.STOP_MATCH_EXCERPT_TRUNCATION_MARKER = exports.STOP_MATCH_EXCERPT_MAX_BYTES = exports.executeRegexWithTimeout = exports.COMPOSITE_KEY_SEPARATOR = void 0;
|
|
15
15
|
exports.buildCompositeKey = buildCompositeKey;
|
|
16
16
|
exports.extractWorktreeId = extractWorktreeId;
|
|
17
17
|
exports.extractCliToolId = extractCliToolId;
|
|
@@ -21,6 +21,7 @@ exports.getAutoYesState = getAutoYesState;
|
|
|
21
21
|
exports.setAutoYesEnabled = setAutoYesEnabled;
|
|
22
22
|
exports.disableAutoYes = disableAutoYes;
|
|
23
23
|
exports.clearAllAutoYesStates = clearAllAutoYesStates;
|
|
24
|
+
exports.truncateToUtf8Bytes = truncateToUtf8Bytes;
|
|
24
25
|
exports.checkStopCondition = checkStopCondition;
|
|
25
26
|
exports.deleteAutoYesState = deleteAutoYesState;
|
|
26
27
|
exports.getAutoYesStateCompositeKeys = getAutoYesStateCompositeKeys;
|
|
@@ -204,9 +205,12 @@ function setAutoYesEnabled(worktreeId, cliToolId, enabled, duration, stopPattern
|
|
|
204
205
|
* @param cliToolId - CLI tool type (default: 'claude')
|
|
205
206
|
* @param reason - Optional reason for disabling ('expired' | 'stop_pattern_matched')
|
|
206
207
|
* @param instanceId - Optional instance identifier (Issue #896; defaults to primary)
|
|
208
|
+
* @param stopMatchedText - Optional excerpt of what the stop pattern matched
|
|
209
|
+
* (Issue #1694). Deliberately *not* carried over from the existing state: it
|
|
210
|
+
* belongs to `reason`, so a disable for any other reason stores none.
|
|
207
211
|
* @returns Updated auto-yes state
|
|
208
212
|
*/
|
|
209
|
-
function disableAutoYes(worktreeId, cliToolId = 'claude', reason, instanceId) {
|
|
213
|
+
function disableAutoYes(worktreeId, cliToolId = 'claude', reason, instanceId, stopMatchedText) {
|
|
210
214
|
const key = buildCompositeKey(worktreeId, cliToolId, instanceId);
|
|
211
215
|
const existing = autoYesStates.get(key);
|
|
212
216
|
const state = {
|
|
@@ -215,6 +219,7 @@ function disableAutoYes(worktreeId, cliToolId = 'claude', reason, instanceId) {
|
|
|
215
219
|
expiresAt: existing?.expiresAt ?? 0,
|
|
216
220
|
stopPattern: existing?.stopPattern,
|
|
217
221
|
stopReason: reason,
|
|
222
|
+
stopMatchedText,
|
|
218
223
|
};
|
|
219
224
|
autoYesStates.set(key, state);
|
|
220
225
|
return state;
|
|
@@ -235,6 +240,103 @@ function clearAllAutoYesStates() {
|
|
|
235
240
|
*/
|
|
236
241
|
var auto_yes_config_2 = require("../config/auto-yes-config");
|
|
237
242
|
Object.defineProperty(exports, "executeRegexWithTimeout", { enumerable: true, get: function () { return auto_yes_config_2.executeRegexWithTimeout; } });
|
|
243
|
+
/**
|
|
244
|
+
* Maximum size of the stop-pattern excerpt, in UTF-8 bytes, marker included
|
|
245
|
+
* (Issue #1694).
|
|
246
|
+
*
|
|
247
|
+
* The excerpt answers one question — "is this a real stop or did a build log
|
|
248
|
+
* happen to contain the pattern?" (#1678 A-5) — and a couple of lines answer
|
|
249
|
+
* it. The cap is a hard bound rather than a hint because `cleanOutput` is a
|
|
250
|
+
* whole terminal frame and a greedy pattern can match all of it, and because
|
|
251
|
+
* the value rides in every `capture --json` poll for the rest of the session.
|
|
252
|
+
*/
|
|
253
|
+
exports.STOP_MATCH_EXCERPT_MAX_BYTES = 400;
|
|
254
|
+
/**
|
|
255
|
+
* Appended when the excerpt was cut to fit {@link STOP_MATCH_EXCERPT_MAX_BYTES}.
|
|
256
|
+
*
|
|
257
|
+
* Cutting silently would make a fragment read as the whole match, which is the
|
|
258
|
+
* wrong conclusion in exactly the triage this field exists for.
|
|
259
|
+
*/
|
|
260
|
+
exports.STOP_MATCH_EXCERPT_TRUNCATION_MARKER = '…[truncated]';
|
|
261
|
+
/** Lines of context kept on either side of the match (Issue #1694). */
|
|
262
|
+
exports.STOP_MATCH_EXCERPT_CONTEXT_LINES = 1;
|
|
263
|
+
/** Shared encoder for byte-length math (UTF-8 by spec). */
|
|
264
|
+
const utf8Encoder = new TextEncoder();
|
|
265
|
+
/** UTF-8 byte length of a string. */
|
|
266
|
+
function utf8ByteLength(text) {
|
|
267
|
+
return utf8Encoder.encode(text).length;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Cut `text` down to `maxBytes` UTF-8 bytes, marker included, never splitting a
|
|
271
|
+
* character (Issue #1694).
|
|
272
|
+
*
|
|
273
|
+
* The budget is measured in bytes rather than characters because the excerpt is
|
|
274
|
+
* copied verbatim into a JSON payload, and a Japanese terminal frame costs 3
|
|
275
|
+
* bytes per character — a character cap would let one frame publish three times
|
|
276
|
+
* the intended payload.
|
|
277
|
+
*
|
|
278
|
+
* @internal Exported for testing purposes only.
|
|
279
|
+
* @param text - Text to bound
|
|
280
|
+
* @param maxBytes - Byte ceiling for the returned string (marker included)
|
|
281
|
+
* @returns `text` unchanged when it already fits, otherwise a prefix of it with
|
|
282
|
+
* {@link STOP_MATCH_EXCERPT_TRUNCATION_MARKER} appended
|
|
283
|
+
*/
|
|
284
|
+
function truncateToUtf8Bytes(text, maxBytes = exports.STOP_MATCH_EXCERPT_MAX_BYTES) {
|
|
285
|
+
if (utf8ByteLength(text) <= maxBytes)
|
|
286
|
+
return text;
|
|
287
|
+
const budget = maxBytes - utf8ByteLength(exports.STOP_MATCH_EXCERPT_TRUNCATION_MARKER);
|
|
288
|
+
if (budget <= 0)
|
|
289
|
+
return exports.STOP_MATCH_EXCERPT_TRUNCATION_MARKER;
|
|
290
|
+
let used = 0;
|
|
291
|
+
let kept = '';
|
|
292
|
+
// for..of iterates code points, so a surrogate pair is never halved.
|
|
293
|
+
for (const char of text) {
|
|
294
|
+
const size = utf8ByteLength(char);
|
|
295
|
+
if (used + size > budget)
|
|
296
|
+
break;
|
|
297
|
+
kept += char;
|
|
298
|
+
used += size;
|
|
299
|
+
}
|
|
300
|
+
return kept + exports.STOP_MATCH_EXCERPT_TRUNCATION_MARKER;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Build the excerpt shown for a stop-pattern hit (Issue #1694).
|
|
304
|
+
*
|
|
305
|
+
* Whole lines, not the raw match: a pattern like `error` matched against a
|
|
306
|
+
* terminal frame yields the six characters `error`, which tells the operator
|
|
307
|
+
* nothing about whether it came from the agent asking a question or from a
|
|
308
|
+
* dependency's build log scrolling past. The surrounding line is the smallest
|
|
309
|
+
* unit that carries that.
|
|
310
|
+
*
|
|
311
|
+
* @param regex - The already-constructed stop pattern (no `g` flag, so `exec`
|
|
312
|
+
* is position-independent and does not disturb the caller's `test`)
|
|
313
|
+
* @param output - ANSI-stripped terminal output the pattern matched
|
|
314
|
+
* @returns Bounded excerpt, or null when the match cannot be located
|
|
315
|
+
*/
|
|
316
|
+
function buildStopMatchExcerpt(regex, output) {
|
|
317
|
+
let match;
|
|
318
|
+
try {
|
|
319
|
+
match = regex.exec(output);
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
if (!match)
|
|
325
|
+
return null;
|
|
326
|
+
const matchStart = match.index;
|
|
327
|
+
const matchEnd = matchStart + match[0].length;
|
|
328
|
+
const lines = output.split('\n');
|
|
329
|
+
const firstLine = output.slice(0, matchStart).split('\n').length - 1;
|
|
330
|
+
const lastLine = output.slice(0, matchEnd).split('\n').length - 1;
|
|
331
|
+
const from = Math.max(0, firstLine - exports.STOP_MATCH_EXCERPT_CONTEXT_LINES);
|
|
332
|
+
const to = Math.min(lines.length - 1, lastLine + exports.STOP_MATCH_EXCERPT_CONTEXT_LINES);
|
|
333
|
+
const raw = lines.slice(from, to + 1).join('\n');
|
|
334
|
+
// Terminal frames are padded with blank lines and trailing spaces; those are
|
|
335
|
+
// pure noise here and eat the byte budget. A whitespace-only match keeps its
|
|
336
|
+
// raw form rather than becoming an empty, unexplained field.
|
|
337
|
+
const trimmed = raw.trim();
|
|
338
|
+
return truncateToUtf8Bytes(trimmed.length > 0 ? trimmed : raw);
|
|
339
|
+
}
|
|
238
340
|
/**
|
|
239
341
|
* Check if the terminal output matches the stop condition pattern.
|
|
240
342
|
* If matched, disables auto-yes for the worktree/agent.
|
|
@@ -275,7 +377,10 @@ function checkStopCondition(compositeKey, cleanOutput, onStopMatched) {
|
|
|
275
377
|
return false;
|
|
276
378
|
}
|
|
277
379
|
if (matched) {
|
|
278
|
-
|
|
380
|
+
// Issue #1694: what matched, not just that something did. Built here
|
|
381
|
+
// because this is the only frame that still holds the output.
|
|
382
|
+
const stopMatchedText = buildStopMatchExcerpt(regex, cleanOutput) ?? undefined;
|
|
383
|
+
disableAutoYes(worktreeId, cliToolId, 'stop_pattern_matched', instanceId, stopMatchedText);
|
|
279
384
|
if (onStopMatched) {
|
|
280
385
|
onStopMatched(compositeKey);
|
|
281
386
|
}
|
|
@@ -136,15 +136,19 @@ class AntigravityTool extends base_1.BaseCLITool {
|
|
|
136
136
|
await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.TUI_SESSION_CREATE_WAIT_MS));
|
|
137
137
|
// Start agy in interactive mode, optionally pinned to a model.
|
|
138
138
|
//
|
|
139
|
-
// Issue #1762:
|
|
139
|
+
// Issue #1762: the launch merges CommandMate's named hook into
|
|
140
140
|
// `~/.gemini/config/hooks.json` — agy's single global config, shared with
|
|
141
141
|
// gemini's tree and with whatever the user has in it — and prefixes
|
|
142
142
|
// `CM_HOOK_URL`. That variable is the *only* correlation channel agy has:
|
|
143
143
|
// its payloads carry no `cwd`, its hooks run in `~/.gemini/config`, and
|
|
144
144
|
// one file serves every worktree on the machine. `--model` is appended
|
|
145
|
-
// after, so the env
|
|
146
|
-
// `CM_AGENT_HOOKS_INJECT=0` returns bare `agy`, unchanged
|
|
147
|
-
const base = (0, agent_session_lifecycle_1.
|
|
145
|
+
// after the rendered line, so the env assignments stay in front of the
|
|
146
|
+
// command. `CM_AGENT_HOOKS_INJECT=0` returns bare `agy`, unchanged.
|
|
147
|
+
const base = (0, agent_session_lifecycle_1.buildAgentLaunchCommandLine)({
|
|
148
|
+
target: { worktreeId, cliToolId: sources_1.ANTIGRAVITY_CLI_TOOL_ID, instanceId },
|
|
149
|
+
executablePath: this.command,
|
|
150
|
+
worktreePath,
|
|
151
|
+
});
|
|
148
152
|
const launchCommand = model ? `${base} --model ${shellSingleQuote(model)}` : base;
|
|
149
153
|
await (0, tmux_1.sendKeys)(sessionName, launchCommand, true);
|
|
150
154
|
// Wait for agy to initialize
|
|
@@ -31,33 +31,6 @@ const CODEX_POLL_INTERVAL_MS = 1000;
|
|
|
31
31
|
const CODEX_INIT_MAX_ATTEMPTS = 30;
|
|
32
32
|
/** Timeout for waiting for prompt before sending a message */
|
|
33
33
|
const CODEX_PROMPT_WAIT_TIMEOUT_MS = 15000;
|
|
34
|
-
/**
|
|
35
|
-
* Anchors of codex's "Hooks need review" dialog (Issue #1760, measured on
|
|
36
|
-
* codex-cli 0.147.0):
|
|
37
|
-
*
|
|
38
|
-
* ```
|
|
39
|
-
* Hooks need review
|
|
40
|
-
* 5 hooks are new or changed.
|
|
41
|
-
* Hooks can run outside the sandbox after you trust them.
|
|
42
|
-
*
|
|
43
|
-
* > 1. Review hooks
|
|
44
|
-
* 2. Trust all and continue
|
|
45
|
-
* 3. Continue without trusting (hooks won't run)
|
|
46
|
-
* ```
|
|
47
|
-
*
|
|
48
|
-
* It has to be handled here rather than in `getCodexActiveDialog`, which
|
|
49
|
-
* classifies it as `null`: its wording matches none of that function's three
|
|
50
|
-
* anchors (`Skip until next version` / `Do you trust` / `Press enter to
|
|
51
|
-
* continue`). Measured consequence of leaving it alone, on a pane with the
|
|
52
|
-
* generated `hooks.json` present: `isCodexPromptReady` stays false for the full
|
|
53
|
-
* 30-attempt window and the session is then handed to `sendMessage` still
|
|
54
|
-
* sitting on the dialog. Every launch, because "continue without trusting" is
|
|
55
|
-
* not remembered — verified by relaunching and getting the same screen.
|
|
56
|
-
*
|
|
57
|
-
* Both strings are required so a "hooks" mention elsewhere cannot select an
|
|
58
|
-
* option on a live prompt.
|
|
59
|
-
*/
|
|
60
|
-
const CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trusting'];
|
|
61
34
|
/**
|
|
62
35
|
* Option 3, "Continue without trusting (hooks won't run)".
|
|
63
36
|
*
|
|
@@ -72,21 +45,57 @@ const CODEX_HOOKS_REVIEW_ANCHORS = ['Hooks need review', 'Continue without trust
|
|
|
72
45
|
* Sent alone, like the other numbered dialogs (Issue #890): codex confirms a
|
|
73
46
|
* numbered selection instantly, and a trailing Enter would land on the next
|
|
74
47
|
* screen. Verified live — the prompt was ready on the following poll.
|
|
48
|
+
*
|
|
49
|
+
* Re-verified on codex-cli 0.148.0 for Issue #1829, against the objection that
|
|
50
|
+
* the dialog's own footer says `Press enter to confirm`. With the trust hashes
|
|
51
|
+
* invalidated and Auto-Yes off, a session launched onto this dialog reached
|
|
52
|
+
* `› Ask Codex to do anything` and then ran the message it was sent — on the
|
|
53
|
+
* `'3'` alone. The footer and the number key are not exclusive: the number
|
|
54
|
+
* selects AND confirms, Enter confirms the highlighted option. That is also why
|
|
55
|
+
* a trailing Enter is so costly here — the number having already advanced the
|
|
56
|
+
* screen, the Enter lands on the NEXT one, which is precisely how a pane ends up
|
|
57
|
+
* two screens deep in the hooks review UI.
|
|
75
58
|
*/
|
|
76
59
|
const CODEX_HOOKS_REVIEW_DECLINE_KEY = '3';
|
|
60
|
+
/**
|
|
61
|
+
* How many times `waitForReady` may press `esc` to climb out of codex's hooks
|
|
62
|
+
* review screens (Issue #1829).
|
|
63
|
+
*
|
|
64
|
+
* Two is the depth of the UI — detail -> list -> closed — and the cap exists
|
|
65
|
+
* because the alternative is one press per poll: 30 keystrokes into whatever is
|
|
66
|
+
* really on screen if the classifier is ever wrong about a frame. Two spare
|
|
67
|
+
* presses cover a redraw landing between capture and send.
|
|
68
|
+
*/
|
|
69
|
+
const CODEX_HOOKS_SCREEN_MAX_ESCAPES = 4;
|
|
77
70
|
/**
|
|
78
71
|
* Whether the pane is sitting on the hooks review dialog.
|
|
79
72
|
*
|
|
80
73
|
* Position-independent on purpose, unlike `getCodexActiveDialog`: the only
|
|
81
74
|
* caller checks `isCodexPromptReady` first and returns when a genuine prompt
|
|
82
75
|
* exists, so residual dialog text above a live prompt is never reached, and a
|
|
83
|
-
* one-shot guard stops the key being sent twice.
|
|
76
|
+
* one-shot guard stops the key being sent twice. Callers OUTSIDE this launch
|
|
77
|
+
* sequence must use `getCodexLifecycleDialog` instead, which is position-based.
|
|
78
|
+
*
|
|
79
|
+
* The dialog has to be handled here rather than in `getCodexActiveDialog`, which
|
|
80
|
+
* classifies it as `null`: its wording matches none of that function's three
|
|
81
|
+
* anchors (`Skip until next version` / `Do you trust` / `Press enter to
|
|
82
|
+
* continue`). Measured consequence of leaving it alone, on a pane with the
|
|
83
|
+
* generated `hooks.json` present: `isCodexPromptReady` stays false for the full
|
|
84
|
+
* 30-attempt window and the session is then handed to `sendMessage` still
|
|
85
|
+
* sitting on the dialog. Every launch, because "continue without trusting" is
|
|
86
|
+
* not remembered — verified by relaunching and getting the same screen.
|
|
87
|
+
*
|
|
88
|
+
* The anchors themselves live in `detection/cli-patterns` (Issue #1829): the
|
|
89
|
+
* Auto-Yes poller has to recognise the same screen in order to keep its hands
|
|
90
|
+
* off it, and two copies of the anchors would be two chances to disagree about
|
|
91
|
+
* what this dialog is.
|
|
84
92
|
*
|
|
85
93
|
* @param output - ANSI-stripped pane capture
|
|
86
94
|
* @returns True when both anchors of the dialog are present
|
|
95
|
+
* @see CODEX_HOOKS_REVIEW_ANCHORS
|
|
87
96
|
*/
|
|
88
97
|
function isCodexHooksReviewDialog(output) {
|
|
89
|
-
return CODEX_HOOKS_REVIEW_ANCHORS.every((anchor) => output.includes(anchor));
|
|
98
|
+
return cli_patterns_1.CODEX_HOOKS_REVIEW_ANCHORS.every((anchor) => output.includes(anchor));
|
|
90
99
|
}
|
|
91
100
|
/**
|
|
92
101
|
* Codex CLI tool implementation
|
|
@@ -157,7 +166,11 @@ class CodexTool extends base_1.BaseCLITool {
|
|
|
157
166
|
// Falls back to the bare command on any failure and when
|
|
158
167
|
// `CM_AGENT_HOOKS_INJECT=0`; a session that starts without hooks is the
|
|
159
168
|
// pre-#1760 status quo, and a session that fails to start is not.
|
|
160
|
-
const launchCommand = (0, agent_session_lifecycle_1.
|
|
169
|
+
const launchCommand = (0, agent_session_lifecycle_1.buildAgentLaunchCommandLine)({
|
|
170
|
+
target: { worktreeId, cliToolId: sources_1.CODEX_CLI_TOOL_ID, instanceId },
|
|
171
|
+
executablePath: this.command,
|
|
172
|
+
worktreePath,
|
|
173
|
+
});
|
|
161
174
|
// Start Codex CLI in interactive mode
|
|
162
175
|
await (0, tmux_1.sendKeys)(sessionName, launchCommand, true);
|
|
163
176
|
// Wait for Codex to initialize
|
|
@@ -185,6 +198,7 @@ class CodexTool extends base_1.BaseCLITool {
|
|
|
185
198
|
let updateDialogHandled = false;
|
|
186
199
|
let trustDialogHandled = false;
|
|
187
200
|
let hooksReviewHandled = false;
|
|
201
|
+
let hooksScreenEscapes = 0;
|
|
188
202
|
for (let i = 0; i < CODEX_INIT_MAX_ATTEMPTS; i++) {
|
|
189
203
|
try {
|
|
190
204
|
const rawOutput = await (0, tmux_1.capturePane)(sessionName, 50);
|
|
@@ -208,6 +222,25 @@ class CodexTool extends base_1.BaseCLITool {
|
|
|
208
222
|
await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.CODEX_DIALOG_SETTLE_MS));
|
|
209
223
|
continue;
|
|
210
224
|
}
|
|
225
|
+
// Issue #1829: back out of the two screens the hooks dialog leads to.
|
|
226
|
+
// Confirming its option 1 -- which the Auto-Yes poller did on two live
|
|
227
|
+
// sessions, and which a human can do too -- opens a review UI whose only
|
|
228
|
+
// exits are `t` and `esc`. `t` is out: it writes `[hooks.state…]` into
|
|
229
|
+
// the operator's own ~/.codex/config.toml, the grant Issue #1760
|
|
230
|
+
// declined on their behalf. So `esc`, once per poll until the screens
|
|
231
|
+
// are gone. Before this, nothing sent either key: the whole 30-attempt
|
|
232
|
+
// window elapsed, waitForReady returned as if ready, and the session was
|
|
233
|
+
// left parked there -- reported as `running`, because neither screen
|
|
234
|
+
// carries an option, a confirm footer or a thinking indicator.
|
|
235
|
+
const hooksScreen = (0, cli_patterns_1.getCodexLifecycleDialog)(output);
|
|
236
|
+
if ((hooksScreen === 'hooks-list' || hooksScreen === 'hooks-detail') &&
|
|
237
|
+
hooksScreenEscapes < CODEX_HOOKS_SCREEN_MAX_ESCAPES) {
|
|
238
|
+
await (0, tmux_1.sendSpecialKey)(sessionName, 'Escape');
|
|
239
|
+
hooksScreenEscapes++;
|
|
240
|
+
logger.info('codex-hooks-screen-escaped');
|
|
241
|
+
await new Promise((resolve) => setTimeout(resolve, cli_tool_timing_config_1.CODEX_DIALOG_SETTLE_MS));
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
211
244
|
// Issue #892: classify the bottom-most ACTIVE dialog by position. A dialog
|
|
212
245
|
// whose text is only residual scrollback above a genuine prompt returns
|
|
213
246
|
// null here, so no stray key is sent after it has been dismissed.
|