commandmate 0.30.2 → 0.31.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 +160 -160
- package/.next/app-path-routes-manifest.json +27 -27
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- 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/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_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.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +3 -3
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +4 -4
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +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/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/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.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +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.js.nft.json +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/remote/pair/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.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +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/settings/default-agents/route.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/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.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.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/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.js.nft.json +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]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.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.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]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +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]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +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]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +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.js +4 -3
- 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.js +4 -3
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +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.js +2 -2
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +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.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +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]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +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/config/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]/cancel/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/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +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_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 +1 -1
- 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_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +10 -10
- 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 +27 -27
- package/.next/server/chunks/1058.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1262.js +1 -1
- package/.next/server/chunks/1886.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2328.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/261.js +1 -1
- package/.next/server/chunks/3123.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3480.js +5 -4
- package/.next/server/chunks/4299.js +1 -1
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/4443.js +1 -5
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5043.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/552.js +2 -2
- package/.next/server/chunks/6072.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/663.js +4 -3
- package/.next/server/chunks/6894.js +2 -2
- package/.next/server/chunks/7187.js +1 -0
- package/.next/server/chunks/7472.js +1 -1
- package/.next/server/chunks/{880.js → 7859.js} +6 -6
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8800.js +2 -2
- package/.next/server/chunks/8918.js +7 -0
- package/.next/server/chunks/9123.js +2 -2
- package/.next/server/chunks/9130.js +4 -4
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/9696.js +1 -1
- package/.next/server/chunks/9798.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
- package/.next/static/chunks/4718-de1224c9e8a6e7fc.js +1 -0
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
- package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
- package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
- package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
- package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
- package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
- package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
- package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
- package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
- package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
- package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
- package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-97205088520255a5.js +1 -0
- package/.next/static/css/5c13ea243dfdcb66.css +1 -0
- package/.next/trace +13 -13
- package/README.md +37 -11
- package/dist/cli/commands/attach.d.ts +50 -0
- package/dist/cli/commands/attach.d.ts.map +1 -0
- package/dist/cli/commands/attach.js +204 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +114 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +23 -2
- package/dist/cli/commands/ls.d.ts.map +1 -1
- package/dist/cli/commands/ls.js +41 -1
- package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
- package/dist/cli/config/cli-dependencies.js +34 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +5 -0
- package/dist/cli/types/index.d.ts +36 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/config/tmux-pane-config.d.ts +153 -0
- package/dist/config/tmux-pane-config.d.ts.map +1 -0
- package/dist/config/tmux-pane-config.js +172 -0
- package/dist/lib/cli-tools/session-name.d.ts +44 -0
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
- package/dist/lib/cli-tools/session-name.js +57 -0
- package/dist/lib/cli-tools/types.d.ts +1 -1
- package/dist/lib/cli-tools/types.d.ts.map +1 -1
- package/dist/lib/cli-tools/types.js +6 -1
- package/dist/lib/cli-tools/validation.d.ts +34 -0
- package/dist/lib/cli-tools/validation.d.ts.map +1 -0
- package/dist/lib/cli-tools/validation.js +41 -0
- package/dist/lib/detection/status-reason.d.ts +18 -0
- package/dist/lib/detection/status-reason.d.ts.map +1 -1
- package/dist/lib/detection/status-reason.js +18 -0
- package/dist/lib/detection/tools/verified-against.d.ts +57 -7
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +59 -8
- package/dist/lib/detection/version-probes.d.ts +26 -5
- package/dist/lib/detection/version-probes.d.ts.map +1 -1
- package/dist/lib/detection/version-probes.js +28 -6
- package/dist/lib/session/tmux-session-surface.d.ts +369 -0
- package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
- package/dist/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/config/cli-tool-timing-config.js +12 -1
- package/dist/server/src/config/detection-evidence-config.js +5 -0
- package/dist/server/src/config/schedule-config.js +28 -1
- package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
- package/dist/server/src/lib/cli-tools/base.js +13 -8
- package/dist/server/src/lib/cli-tools/claude.js +20 -0
- package/dist/server/src/lib/cli-tools/codex.js +205 -61
- package/dist/server/src/lib/cli-tools/command-code.js +349 -0
- package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
- package/dist/server/src/lib/cli-tools/copilot.js +2 -2
- package/dist/server/src/lib/cli-tools/gemini.js +2 -2
- package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
- package/dist/server/src/lib/cli-tools/index.js +4 -1
- package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
- package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
- package/dist/server/src/lib/cli-tools/manager.js +2 -0
- package/dist/server/src/lib/cli-tools/opencode.js +2 -2
- package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
- package/dist/server/src/lib/cli-tools/types.js +6 -1
- package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
- package/dist/server/src/lib/cmate-parser.js +6 -0
- package/dist/server/src/lib/detection/cli-patterns.js +441 -8
- package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
- package/dist/server/src/lib/detection/selection-shape.js +341 -0
- package/dist/server/src/lib/detection/sgr-background.js +210 -0
- package/dist/server/src/lib/detection/status-detector.js +6 -0
- package/dist/server/src/lib/detection/status-reason.js +18 -0
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
- package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
- package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
- package/dist/server/src/lib/detection/tools/registry.js +6 -4
- package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
- package/dist/server/src/lib/detection/version-probes.js +28 -6
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +77 -16
- package/dist/server/src/lib/hooks/sources/claude/history.js +94 -18
- package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
- package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
- package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
- package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
- package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
- package/dist/server/src/lib/hooks/sources/index.js +3 -1
- package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
- package/dist/server/src/lib/hooks/sources/registry.js +4 -0
- package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
- package/dist/server/src/lib/job-executor.js +12 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
- package/dist/server/src/lib/polling/response-checker.js +112 -7
- package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
- package/dist/server/src/lib/realtime/types.js +15 -5
- package/dist/server/src/lib/response-cleaner.js +24 -1
- package/dist/server/src/lib/response-extractor.js +11 -0
- package/dist/server/src/lib/session/claude-executor.js +223 -4
- package/dist/server/src/lib/session/cli-session.js +52 -0
- package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
- package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
- package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
- package/dist/server/src/lib/tmux/read-mode.js +44 -2
- package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
- package/dist/server/src/lib/tmux/session-hooks.js +122 -0
- package/dist/server/src/lib/tmux/session-status-options.js +213 -0
- package/dist/server/src/lib/tmux/tmux.js +79 -2
- package/dist/server/src/lib/version-checker.js +110 -0
- package/dist/server/src/lib/ws-server.js +16 -10
- package/dist/server/src/types/agent-transcript.js +73 -1
- package/dist/server/src/types/terminal-keys.js +131 -3
- package/dist/types/terminal-keys.d.ts +100 -3
- package/dist/types/terminal-keys.d.ts.map +1 -1
- package/dist/types/terminal-keys.js +131 -3
- package/package.json +1 -1
- package/.next/server/chunks/3099.js +0 -5
- package/.next/server/chunks/7824.js +0 -1
- package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
- package/.next/static/chunks/6381-147dde2a967e9458.js +0 -1
- package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-2f73d69187936627.js +0 -1
- package/.next/static/css/23f9c40ecc458c77.css +0 -1
- /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → nXW4dPkpE_9xUf_9ySRff}/_buildManifest.js +0 -0
- /package/.next/static/{QXxQbXWoo7ldUyOcv7PCZ → nXW4dPkpE_9xUf_9ySRff}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Codex's dialog rules, read off the frame's STRUCTURE rather than its wording
|
|
4
|
+
* (Issue #2310).
|
|
5
|
+
*
|
|
6
|
+
* ## The defect these rules exist for
|
|
7
|
+
*
|
|
8
|
+
* Until #2310 the only thing that told `detect.ts` "a codex dialog is on screen"
|
|
9
|
+
* was a footer whitelist — `CODEX_SELECTION_LIST_PATTERN`, i.e. the literal
|
|
10
|
+
* words `press enter to confirm` / `press enter to select`. Every dialog codex
|
|
11
|
+
* closes with any other sentence fell straight through to the two branches that
|
|
12
|
+
* read `^›` as the idle composer (branch B of `afterThinking`, and the shared
|
|
13
|
+
* chain's step 3), and those publish **`ready`**. Two live captures of
|
|
14
|
+
* codex-cli 0.153.2 at the production 200x1000 geometry, both blocked on a
|
|
15
|
+
* keypress and both reported `ready` before this module existed
|
|
16
|
+
* (`tests/unit/lib/detection/fixtures/codex-live-2310/`):
|
|
17
|
+
*
|
|
18
|
+
* | screen | footer | why the whitelist missed it |
|
|
19
|
+
* |---|---|---|
|
|
20
|
+
* | `/experimental` | `Press space to select or enter to save for next conversation` | `press SPACE to select`, not `press enter to select` |
|
|
21
|
+
* | `/keymap` | `left/right group · enter edit shortcut · … · esc close` | no `press … to …` clause at all |
|
|
22
|
+
*
|
|
23
|
+
* A `ready` there is not cosmetic: Auto-Yes concludes there is nothing to
|
|
24
|
+
* answer, the sidebar dot goes green, and `commandmate wait` takes the frame as
|
|
25
|
+
* its `scraper_ready` completion — a false "Completed" on a session that has not
|
|
26
|
+
* moved since the operator's last keypress.
|
|
27
|
+
*
|
|
28
|
+
* Note what BOTH real leaks have in common and what the Issue's own analysis
|
|
29
|
+
* assumed they would not: **neither list is numbered.** A rule written only
|
|
30
|
+
* around `findNumberedOptionBlock` would still report both as `ready`, so the
|
|
31
|
+
* primary rule here is the attribute one below and the numbered block is the
|
|
32
|
+
* corroborating second reading, not the other way round.
|
|
33
|
+
*
|
|
34
|
+
* ## Why the attributes and not the text
|
|
35
|
+
*
|
|
36
|
+
* codex puts `›` (U+203A) at column 0 in three different places, and after
|
|
37
|
+
* `stripAnsi` all three are the same byte. The measured separation (0.153.2,
|
|
38
|
+
* cross-checked against the 0.148.0 / 0.151.0 captures already in the tree) is:
|
|
39
|
+
*
|
|
40
|
+
* ```text
|
|
41
|
+
* ESC[1m›ESC[0m ESC[2mAsk Codex to do anythingESC[0m composer, empty → composer
|
|
42
|
+
* ESC[1m›ESC[0m 1. buy milk composer, typed → composer
|
|
43
|
+
* ESC[1;2m› ESC[0mCreate a file scripts/greet.sh transcript echo → dim glyph
|
|
44
|
+
* ESC[1mESC[38;5;6m› 1. Yes, proceed (y)ESC[0m approval option → bold label
|
|
45
|
+
* ESC[1mESC[38;5;6m› [ ] Network proxy Apply network… /experimental → bold label
|
|
46
|
+
* ESC[1mESC[38;5;6m› Global - Open Agents unboundESC[0m /keymap → bold label
|
|
47
|
+
* ESC[38;5;6m› 1. Yes, continueESC[39m trust dialog → coloured glyph
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* `composer-residual-leading-number.txt` is the frame that rules out the cheap
|
|
51
|
+
* text guard: it is a composer holding the hand-typed string `1. buy milk`, so
|
|
52
|
+
* "a `›` followed by a digit and a dot is an option" would call an idle session
|
|
53
|
+
* `waiting` — the shape #1883 turned into a send guard that rejected every send.
|
|
54
|
+
*
|
|
55
|
+
* {@link readCodexGlyphRowKind} therefore recognises an option **positively**
|
|
56
|
+
* (bold label, or a non-default foreground on the glyph) instead of defining it
|
|
57
|
+
* as "not the composer". Every unrecognised shape falls to `composer`, which is
|
|
58
|
+
* the direction that costs nothing: it is what the code did before #2310.
|
|
59
|
+
*
|
|
60
|
+
* ## Why this duplicates a little of `composer-text.ts`
|
|
61
|
+
*
|
|
62
|
+
* That module has the same SGR scan and the same three-way measurement, and it
|
|
63
|
+
* is the right module to share it from. It is outside this Issue's `scope.allow`
|
|
64
|
+
* and its `isCodexComposerRow` is not exported, so the scan is re-stated here.
|
|
65
|
+
* The two differ on purpose in one place — `composer-text.ts` accepts a row with
|
|
66
|
+
* a plain glyph and a plain label as the composer, which is right when the job
|
|
67
|
+
* is "find the input box near the bottom" and wrong here, where the same shape
|
|
68
|
+
* is the 0.151+ trust dialog's option. If they are ever merged, that difference
|
|
69
|
+
* is the one to carry across, not to smooth over.
|
|
70
|
+
*/
|
|
71
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
72
|
+
exports.CODEX_DIALOG_FOOTER_PATTERN = exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST = exports.CODEX_GLYPH = void 0;
|
|
73
|
+
exports.readCodexGlyphRowKind = readCodexGlyphRowKind;
|
|
74
|
+
exports.findCodexBottomGlyphRow = findCodexBottomGlyphRow;
|
|
75
|
+
exports.readCodexDialogFrame = readCodexDialogFrame;
|
|
76
|
+
exports.reportCodexDialogFooterDrift = reportCodexDialogFooterDrift;
|
|
77
|
+
exports.resetCodexDialogFooterDriftForTests = resetCodexDialogFooterDriftForTests;
|
|
78
|
+
const logger_1 = require("../../../../lib/logger");
|
|
79
|
+
const dialog_block_1 = require("../dialog-block");
|
|
80
|
+
const logger = (0, logger_1.createLogger)('codex-dialog-rules');
|
|
81
|
+
/** codex's selection-cursor / composer glyph, U+203A. */
|
|
82
|
+
exports.CODEX_GLYPH = '›';
|
|
83
|
+
/**
|
|
84
|
+
* The codex build these dialog rules were read off.
|
|
85
|
+
*
|
|
86
|
+
* Separate from `CODEX_VERIFIED_AGAINST` on purpose: that stamp is the whole
|
|
87
|
+
* detector's (`tools/verified-against.ts`, outside this Issue's scope) and still
|
|
88
|
+
* names 0.148.0, while the frames below are 0.153.2. Recording the newer
|
|
89
|
+
* measurement here rather than leaving it unrecorded keeps a later reader able
|
|
90
|
+
* to tell "this rule is wrong" from "this rule was right for 0.153.2"; the
|
|
91
|
+
* detector-wide stamp should be raised to match the next time that file is in
|
|
92
|
+
* scope.
|
|
93
|
+
*/
|
|
94
|
+
exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST = {
|
|
95
|
+
version: '0.153.2',
|
|
96
|
+
capturedAt: '2026-09-04',
|
|
97
|
+
paneGeometry: '200x1000',
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* The footer vocabulary codex closes its dialogs with — a SECONDARY signal.
|
|
101
|
+
*
|
|
102
|
+
* Deliberately not a gate. #2310 exists because a footer whitelist was load
|
|
103
|
+
* bearing, and widening the whitelist would only move the next wording change
|
|
104
|
+
* one sentence further away. What this pattern is for is the opposite: when
|
|
105
|
+
* {@link readCodexDialogFrame} recognises a dialog by structure and this pattern
|
|
106
|
+
* does NOT recognise its footer, that is a codex rewording worth a line in the
|
|
107
|
+
* log ({@link reportCodexDialogFooterDrift}) rather than a silent miss.
|
|
108
|
+
*
|
|
109
|
+
* Every measured footer matches one of the two alternatives:
|
|
110
|
+
*
|
|
111
|
+
* | footer | screen | alternative |
|
|
112
|
+
* |---|---|---|
|
|
113
|
+
* | `Press enter to confirm or esc to cancel` | approval | both |
|
|
114
|
+
* | `Press enter to confirm or esc to go back` | `/model`, `/permissions` | both |
|
|
115
|
+
* | `Press enter to continue` | trust, sign-in | 1st |
|
|
116
|
+
* | `Press t to trust all; enter to review hooks; esc to close` | hooks list | both |
|
|
117
|
+
* | `Press t to trust; esc to go back` | hooks detail | both |
|
|
118
|
+
* | `Press space to select or enter to save for next conversation` | `/experimental` | 1st |
|
|
119
|
+
* | `left/right group · enter edit shortcut · … · esc close` | `/keymap` | 2nd |
|
|
120
|
+
*
|
|
121
|
+
* No `/g` (keeps `.test()` stateless) and no nested quantifiers (ReDoS-safe).
|
|
122
|
+
*/
|
|
123
|
+
exports.CODEX_DIALOG_FOOTER_PATTERN = /press\s+\S+\s+to\s+\S|esc\s+(?:to\s+)?(?:cancel|close|dismiss|quit|exit|back|go\s+back)/i;
|
|
124
|
+
const INITIAL_SGR = { bold: false, dim: false, coloured: false };
|
|
125
|
+
/**
|
|
126
|
+
* Apply one SGR parameter list to the running attribute state.
|
|
127
|
+
*
|
|
128
|
+
* The extended-colour introducers are consumed with their arguments because
|
|
129
|
+
* those arguments would otherwise be read as attributes: `ESC[38;5;2m` is
|
|
130
|
+
* "foreground = palette colour 2", and a naive scan sees the `2` and marks the
|
|
131
|
+
* rest of the row dim — which is exactly codex's own option colouring
|
|
132
|
+
* (`ESC[38;5;6m`) and would turn every dialog row into a transcript echo.
|
|
133
|
+
*/
|
|
134
|
+
function applySgr(params, state) {
|
|
135
|
+
const parts = params === '' ? ['0'] : params.split(';');
|
|
136
|
+
let { bold, dim, coloured } = state;
|
|
137
|
+
for (let i = 0; i < parts.length; i++) {
|
|
138
|
+
const code = parts[i] === '' ? 0 : Number(parts[i]);
|
|
139
|
+
if (Number.isNaN(code))
|
|
140
|
+
continue;
|
|
141
|
+
if (code === 38) {
|
|
142
|
+
const mode = parts[i + 1] === '' || parts[i + 1] === undefined ? -1 : Number(parts[i + 1]);
|
|
143
|
+
// 5 = 256-colour (one argument), 2 = 24-bit RGB (three arguments).
|
|
144
|
+
if (mode === 5)
|
|
145
|
+
i += 2;
|
|
146
|
+
else if (mode === 2)
|
|
147
|
+
i += 4;
|
|
148
|
+
else
|
|
149
|
+
i += 1;
|
|
150
|
+
coloured = true;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (code === 48 || code === 58) {
|
|
154
|
+
// Background / underline colour: same argument shapes, no bearing here.
|
|
155
|
+
const mode = parts[i + 1] === '' || parts[i + 1] === undefined ? -1 : Number(parts[i + 1]);
|
|
156
|
+
if (mode === 5)
|
|
157
|
+
i += 2;
|
|
158
|
+
else if (mode === 2)
|
|
159
|
+
i += 4;
|
|
160
|
+
else
|
|
161
|
+
i += 1;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (code === 0) {
|
|
165
|
+
bold = false;
|
|
166
|
+
dim = false;
|
|
167
|
+
coloured = false;
|
|
168
|
+
}
|
|
169
|
+
else if (code === 1)
|
|
170
|
+
bold = true;
|
|
171
|
+
else if (code === 2)
|
|
172
|
+
dim = true;
|
|
173
|
+
else if (code === 22) {
|
|
174
|
+
bold = false;
|
|
175
|
+
dim = false;
|
|
176
|
+
}
|
|
177
|
+
else if (code === 39)
|
|
178
|
+
coloured = false;
|
|
179
|
+
else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97))
|
|
180
|
+
coloured = true;
|
|
181
|
+
}
|
|
182
|
+
return { bold, dim, coloured };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Split one raw pane row into rendered characters tagged with their attributes.
|
|
186
|
+
*
|
|
187
|
+
* Escape sequences are consumed, never emitted: CSI (`ESC[…letter`) updates the
|
|
188
|
+
* attribute state when it ends in `m` and is otherwise skipped, and OSC
|
|
189
|
+
* (`ESC]…BEL` or `ESC]…ESC\`, which tmux emits for hyperlinks) is skipped whole.
|
|
190
|
+
*/
|
|
191
|
+
function scanAttributedChars(row) {
|
|
192
|
+
const out = [];
|
|
193
|
+
let state = INITIAL_SGR;
|
|
194
|
+
let i = 0;
|
|
195
|
+
while (i < row.length) {
|
|
196
|
+
const ch = row[i];
|
|
197
|
+
if (ch !== '\x1b') {
|
|
198
|
+
out.push({ ch, attrs: state });
|
|
199
|
+
i++;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const next = row[i + 1];
|
|
203
|
+
if (next === '[') {
|
|
204
|
+
let j = i + 2;
|
|
205
|
+
while (j < row.length && !/[A-Za-z]/.test(row[j]))
|
|
206
|
+
j++;
|
|
207
|
+
if (j >= row.length)
|
|
208
|
+
break; // truncated sequence: nothing renderable follows
|
|
209
|
+
if (row[j] === 'm')
|
|
210
|
+
state = applySgr(row.slice(i + 2, j), state);
|
|
211
|
+
i = j + 1;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (next === ']') {
|
|
215
|
+
let j = i + 2;
|
|
216
|
+
while (j < row.length) {
|
|
217
|
+
if (row[j] === '\x07') {
|
|
218
|
+
j++;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
if (row[j] === '\x1b' && row[j + 1] === '\\') {
|
|
222
|
+
j += 2;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
j++;
|
|
226
|
+
}
|
|
227
|
+
i = j;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
// Any other two-byte escape (charset switch, etc.): drop it.
|
|
231
|
+
i += 2;
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Classify one RAW pane row whose first rendered glyph is `›`.
|
|
237
|
+
*
|
|
238
|
+
* @param rawRow - One row of the capture, ANSI intact
|
|
239
|
+
* @returns the row's kind, or `null` when the row is not a `›` row at all or
|
|
240
|
+
* carries no attributes to read it by
|
|
241
|
+
*
|
|
242
|
+
* `null` for an attribute-free row is the load-bearing case, not a formality:
|
|
243
|
+
* Auto-Yes hands the detection layer a capture that has already been through
|
|
244
|
+
* `stripAnsi`, and on that input every one of the three `›` uses is the same
|
|
245
|
+
* text. Answering `'option'` there would call an idle composer `waiting`, so the
|
|
246
|
+
* absence of attributes is reported as "cannot tell" and the callers fall back
|
|
247
|
+
* to the reading they had before #2310.
|
|
248
|
+
*/
|
|
249
|
+
function readCodexGlyphRowKind(rawRow) {
|
|
250
|
+
if (!rawRow.includes('\x1b'))
|
|
251
|
+
return null;
|
|
252
|
+
const chars = scanAttributedChars(rawRow);
|
|
253
|
+
const glyphIndex = chars.findIndex(c => c.ch.trim() !== '');
|
|
254
|
+
if (glyphIndex < 0 || chars[glyphIndex].ch !== exports.CODEX_GLYPH)
|
|
255
|
+
return null;
|
|
256
|
+
const glyph = chars[glyphIndex].attrs;
|
|
257
|
+
// The transcript echo of a message the operator already sent. Checked first:
|
|
258
|
+
// codex draws it `ESC[1;2m`, so it is bold as well as dim.
|
|
259
|
+
if (glyph.dim)
|
|
260
|
+
return 'transcript-echo';
|
|
261
|
+
const label = chars.slice(glyphIndex + 1).find(c => c.ch.trim() !== '');
|
|
262
|
+
// Positively recognised: the two shapes every measured dialog row has.
|
|
263
|
+
if (label?.attrs.bold || glyph.coloured)
|
|
264
|
+
return 'option';
|
|
265
|
+
return 'composer';
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Find and classify the bottom-most `›` row of a raw capture.
|
|
269
|
+
*
|
|
270
|
+
* "Bottom-most" is the whole point, and it is the same rule `isCodexPromptReady`
|
|
271
|
+
* and `codexActiveRegionLines` already apply for their own questions: codex
|
|
272
|
+
* draws on the normal screen, so a dialog the operator answered minutes ago is
|
|
273
|
+
* still in the frame with its options intact (Issue #1160). Only the LAST `›`
|
|
274
|
+
* row says what the pane is doing now — and when a turn is generating, that row
|
|
275
|
+
* is the composer, which is why this reads `running` frames as `composer` and
|
|
276
|
+
* leaves them to the thinking branches.
|
|
277
|
+
*
|
|
278
|
+
* @param raw - The capture exactly as it arrived, ANSI intact
|
|
279
|
+
*/
|
|
280
|
+
function findCodexBottomGlyphRow(raw) {
|
|
281
|
+
const rows = raw.split('\n');
|
|
282
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
283
|
+
const kind = readCodexGlyphRowKind(rows[i]);
|
|
284
|
+
if (kind !== null)
|
|
285
|
+
return { kind, row: i };
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
/** How many non-blank rows below the dialog are read as its footer. */
|
|
290
|
+
const FOOTER_SCAN_ROWS = 8;
|
|
291
|
+
function readFooterBelow(contentLines, fromExclusive, endExclusive) {
|
|
292
|
+
const rows = [];
|
|
293
|
+
for (let i = fromExclusive + 1; i < endExclusive && rows.length < FOOTER_SCAN_ROWS; i++) {
|
|
294
|
+
const row = contentLines[i].trim();
|
|
295
|
+
if (row === '')
|
|
296
|
+
continue;
|
|
297
|
+
rows.push(row);
|
|
298
|
+
}
|
|
299
|
+
return rows.join('\n');
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Does this frame show a codex dialog the operator has to answer?
|
|
303
|
+
*
|
|
304
|
+
* Two independent readings, either of which is enough:
|
|
305
|
+
*
|
|
306
|
+
* 1. **the glyph rule** — the bottom-most `›` row of the RAW capture is an
|
|
307
|
+
* option row ({@link readCodexGlyphRowKind}). This is the one that catches
|
|
308
|
+
* the unnumbered menus #2310 was raised for.
|
|
309
|
+
* 2. **the numbered block** — `findNumberedOptionBlock` found a `›`-selected
|
|
310
|
+
* run of options ending within a few rows of the content end. This is the
|
|
311
|
+
* reading that survives `stripAnsi`, and it is vetoed by the glyph rule when
|
|
312
|
+
* that positively says the row is the composer, so a composer holding the
|
|
313
|
+
* hand-typed text `1. buy milk` cannot be adopted as a dialog.
|
|
314
|
+
*
|
|
315
|
+
* Neither reading consults the footer. The footer is reported back so the caller
|
|
316
|
+
* can log a codex rewording; see {@link CODEX_DIALOG_FOOTER_PATTERN}.
|
|
317
|
+
*
|
|
318
|
+
* @param raw - The capture with ANSI intact (`NormalizedFrame.raw`)
|
|
319
|
+
* @param contentLines - The ANSI-stripped rows with trailing padding removed
|
|
320
|
+
* @param contentEnd - Exclusive end of the conversation region (the row above
|
|
321
|
+
* codex's status bar, or `contentLines.length` when the bar is not on screen)
|
|
322
|
+
*/
|
|
323
|
+
function readCodexDialogFrame(raw, contentLines, contentEnd) {
|
|
324
|
+
const glyphRow = findCodexBottomGlyphRow(raw);
|
|
325
|
+
const block = (0, dialog_block_1.findNumberedOptionBlock)(contentLines, contentEnd);
|
|
326
|
+
const blockIsDialog = block !== null && block.selectedGlyph === exports.CODEX_GLYPH;
|
|
327
|
+
const by = glyphRow?.kind === 'option'
|
|
328
|
+
? 'glyph'
|
|
329
|
+
: blockIsDialog && glyphRow?.kind !== 'composer' && glyphRow?.kind !== 'transcript-echo'
|
|
330
|
+
? 'numbered-block'
|
|
331
|
+
: null;
|
|
332
|
+
if (by === null)
|
|
333
|
+
return null;
|
|
334
|
+
// The block's own footer when there is a block; otherwise the rows under the
|
|
335
|
+
// highlighted row. `block.lastRow` and the glyph row are indices into the same
|
|
336
|
+
// ANSI-stripped `contentLines`, so both spellings read the same rows.
|
|
337
|
+
const footer = block !== null
|
|
338
|
+
? block.footer
|
|
339
|
+
: readFooterBelow(contentLines, findLastGlyphContentRow(contentLines, contentEnd), contentEnd);
|
|
340
|
+
return {
|
|
341
|
+
by,
|
|
342
|
+
options: block?.options ?? [],
|
|
343
|
+
footer,
|
|
344
|
+
footerRecognised: exports.CODEX_DIALOG_FOOTER_PATTERN.test(footer),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/** Index of the bottom-most `›` row within the content region, or -1. */
|
|
348
|
+
function findLastGlyphContentRow(contentLines, endExclusive) {
|
|
349
|
+
for (let i = Math.min(endExclusive, contentLines.length) - 1; i >= 0; i--) {
|
|
350
|
+
if (contentLines[i].trimStart().startsWith(exports.CODEX_GLYPH))
|
|
351
|
+
return i;
|
|
352
|
+
}
|
|
353
|
+
return -1;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Footers already reported, so a rewording costs one log line and not one per
|
|
357
|
+
* poll tick.
|
|
358
|
+
*
|
|
359
|
+
* Bounded because the key is frame text: a footer that varies (a countdown, a
|
|
360
|
+
* path) would otherwise grow the set without bound. At the cap the tracker stops
|
|
361
|
+
* recording rather than evicting — the point is the FIRST sighting of a new
|
|
362
|
+
* wording, and a process that has already seen 64 of them has been told.
|
|
363
|
+
*/
|
|
364
|
+
const reportedFooters = new Set();
|
|
365
|
+
const REPORTED_FOOTER_CAP = 64;
|
|
366
|
+
/**
|
|
367
|
+
* Record that a structurally recognised codex dialog closed with a footer this
|
|
368
|
+
* layer does not know (Issue #2310).
|
|
369
|
+
*
|
|
370
|
+
* The detection still stands — that is the whole point of judging the structure
|
|
371
|
+
* — so this is not a warning about the verdict. It is the tripwire on the thing
|
|
372
|
+
* that actually rots: codex's wording. #2310 was reported months after
|
|
373
|
+
* `/experimental` and `/keymap` started falling through, because nothing in the
|
|
374
|
+
* pipeline said so out loud.
|
|
375
|
+
*/
|
|
376
|
+
function reportCodexDialogFooterDrift(footer) {
|
|
377
|
+
const key = footer.slice(0, 200);
|
|
378
|
+
if (reportedFooters.has(key))
|
|
379
|
+
return;
|
|
380
|
+
if (reportedFooters.size >= REPORTED_FOOTER_CAP)
|
|
381
|
+
return;
|
|
382
|
+
reportedFooters.add(key);
|
|
383
|
+
logger.warn('codexDialogFooterUnrecognised', {
|
|
384
|
+
footer: key,
|
|
385
|
+
verifiedAgainst: exports.CODEX_DIALOG_RULES_VERIFIED_AGAINST.version,
|
|
386
|
+
hint: 'codex reworded a dialog footer; widen CODEX_DIALOG_FOOTER_PATTERN after re-capturing the frame',
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/** Test-only: forget the footers already reported. */
|
|
390
|
+
function resetCodexDialogFooterDriftForTests() {
|
|
391
|
+
reportedFooters.clear();
|
|
392
|
+
}
|
|
@@ -19,6 +19,7 @@ exports.isCodexStalePrompt = isCodexStalePrompt;
|
|
|
19
19
|
const cli_patterns_1 = require("../../cli-patterns");
|
|
20
20
|
const prompt_detector_1 = require("../../prompt-detector");
|
|
21
21
|
const status_reason_1 = require("../../status-reason");
|
|
22
|
+
const cli_patterns_2 = require("./cli-patterns");
|
|
22
23
|
const prompt_1 = require("./prompt");
|
|
23
24
|
const frame_1 = require("../frame");
|
|
24
25
|
const run_detection_1 = require("../run-detection");
|
|
@@ -139,6 +140,19 @@ function isCodexApprovalRequest(promptDetection, selectionWindow) {
|
|
|
139
140
|
const question = promptDetection.promptData?.question?.trim() ?? '';
|
|
140
141
|
return question.endsWith('?') || cli_patterns_1.CODEX_APPROVAL_FOOTER_PATTERN.test(selectionWindow);
|
|
141
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Issue #2310: does the RAW frame positively show that its bottom-most `›` row
|
|
145
|
+
* is a dialog's highlighted row rather than the composer?
|
|
146
|
+
*
|
|
147
|
+
* The one question the ANSI-stripped `contentLines` cannot answer, asked in the
|
|
148
|
+
* two places that would otherwise publish `ready` off `CODEX_PROMPT_PATTERN`
|
|
149
|
+
* alone. False only means "not shown to be a dialog" — a stripped capture, a
|
|
150
|
+
* transcript echo and a genuine composer all answer false — so this can withhold
|
|
151
|
+
* an `ready` but never create one.
|
|
152
|
+
*/
|
|
153
|
+
function isCodexDialogGlyphTail(raw) {
|
|
154
|
+
return (0, cli_patterns_2.findCodexBottomGlyphRow)(raw)?.kind === 'option';
|
|
155
|
+
}
|
|
142
156
|
exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
143
157
|
tool: 'codex',
|
|
144
158
|
verifiedAgainst: exports.VERIFIED_AGAINST,
|
|
@@ -240,6 +254,61 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
|
240
254
|
};
|
|
241
255
|
}
|
|
242
256
|
}
|
|
257
|
+
// 0.85. Codex: every OTHER dialog — recognised by structure (Issue #2310)
|
|
258
|
+
//
|
|
259
|
+
// Branch 0.8 above is a footer whitelist, and a dialog codex closes with any
|
|
260
|
+
// other sentence walks straight past it into the two branches that read `^›`
|
|
261
|
+
// as the idle composer (branch B below, and the shared chain's step 3), both
|
|
262
|
+
// of which publish `ready`. Measured on codex-cli 0.153.2 at 200x1000:
|
|
263
|
+
// `/experimental` ends on "Press space to select or enter to save for next
|
|
264
|
+
// conversation" and `/keymap` on "left/right group · enter edit shortcut · …
|
|
265
|
+
// · esc close"; both were reported `ready` while blocked on a keypress, which
|
|
266
|
+
// is what makes Auto-Yes see nothing to answer, the sidebar dot go green and
|
|
267
|
+
// `commandmate wait` close on `scraper_ready` mid-task.
|
|
268
|
+
//
|
|
269
|
+
// So this branch does not read the footer at all — `readCodexDialogFrame`
|
|
270
|
+
// judges the shape: the bottom-most `›` row of the RAW frame carrying a
|
|
271
|
+
// dialog's attributes rather than the composer's, or a `›`-selected numbered
|
|
272
|
+
// block at the foot of the content region (the reading that still answers
|
|
273
|
+
// once ANSI has been stripped). Neither of the two live leaks is numbered,
|
|
274
|
+
// which is why the attribute rule is the primary one.
|
|
275
|
+
//
|
|
276
|
+
// The verdict deliberately mirrors what the chain would have said one step
|
|
277
|
+
// later, so no frame that already resolved changes: a dialog `detectPrompt`
|
|
278
|
+
// can parse is still `PROMPT_DETECTED` with `hasActivePrompt` (step 1's
|
|
279
|
+
// answer — the trust dialog and any reworded approval keep exit 10 for
|
|
280
|
+
// `wait --on-prompt agent`), and everything else is a navigable selection
|
|
281
|
+
// list. The #1160 staleness guard applies as it does in 0.8: an answered
|
|
282
|
+
// block with codex working below it is scrollback, not a dialog — and the
|
|
283
|
+
// glyph rule agrees independently, because the bottom-most `›` on such a
|
|
284
|
+
// frame is the composer codex draws while it works.
|
|
285
|
+
const codexDialogFrame = (0, cli_patterns_2.readCodexDialogFrame)(frame.raw, contentLines, findCodexContentEnd(contentLines));
|
|
286
|
+
if (codexDialogFrame && !isCodexStalePrompt(contentLines)) {
|
|
287
|
+
// The footer is not consulted for the verdict; an unrecognised one means
|
|
288
|
+
// codex reworded a screen, which is worth saying out loud exactly once.
|
|
289
|
+
if (!codexDialogFrame.footerRecognised) {
|
|
290
|
+
(0, cli_patterns_2.reportCodexDialogFooterDrift)(codexDialogFrame.footer);
|
|
291
|
+
}
|
|
292
|
+
const codexPromptDetection = (0, prompt_detector_1.detectPrompt)((0, cli_patterns_1.stripBoxDrawing)(frame.clean), (0, cli_patterns_1.buildDetectPromptOptions)('codex'));
|
|
293
|
+
if (codexPromptDetection.isPrompt) {
|
|
294
|
+
return {
|
|
295
|
+
status: 'waiting',
|
|
296
|
+
confidence: 'high',
|
|
297
|
+
reason: status_reason_1.STATUS_REASON.PROMPT_DETECTED,
|
|
298
|
+
hasActivePrompt: true,
|
|
299
|
+
evidence: 'positive',
|
|
300
|
+
promptDetection: codexPromptDetection,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
status: 'waiting',
|
|
305
|
+
confidence: 'high',
|
|
306
|
+
reason: status_reason_1.STATUS_REASON.CODEX_SELECTION_LIST,
|
|
307
|
+
hasActivePrompt: false,
|
|
308
|
+
evidence: 'positive',
|
|
309
|
+
promptDetection: codexPromptDetection,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
243
312
|
return null;
|
|
244
313
|
},
|
|
245
314
|
isStalePrompt(frame) {
|
|
@@ -292,7 +361,17 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
|
292
361
|
//
|
|
293
362
|
// The evidence stays `positive` here: codex has no measured idle rule yet
|
|
294
363
|
// (see the module docstring), so DR2-002 keeps its pre-#1927 reading.
|
|
295
|
-
|
|
364
|
+
//
|
|
365
|
+
// Issue #2310: `^›` alone does not say "composer". codex draws the same
|
|
366
|
+
// glyph on a dialog's highlighted row, and reading one as the input line
|
|
367
|
+
// is what published `ready` for a session blocked on a keypress. Branch
|
|
368
|
+
// 0.85 already turns those frames back before the chain reaches here, so
|
|
369
|
+
// this is the second reading of the same fact rather than the only one —
|
|
370
|
+
// and it is written as a veto, not a test: only a RAW frame that
|
|
371
|
+
// positively shows a dialog row withholds `ready`, so a capture whose
|
|
372
|
+
// ANSI has been stripped still reports idle exactly as it did before.
|
|
373
|
+
if (cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[lastContentIdx].trim()) &&
|
|
374
|
+
!isCodexDialogGlyphTail(frame.raw)) {
|
|
296
375
|
return {
|
|
297
376
|
status: 'ready',
|
|
298
377
|
confidence: 'high',
|
|
@@ -327,7 +406,9 @@ exports.codexStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
|
327
406
|
while (codexTailIdx >= 0 && contentLines[codexTailIdx].trim() === '') {
|
|
328
407
|
codexTailIdx--;
|
|
329
408
|
}
|
|
330
|
-
const codexTailIsIdlePrompt = codexTailIdx >= 0 &&
|
|
409
|
+
const codexTailIsIdlePrompt = codexTailIdx >= 0 &&
|
|
410
|
+
cli_patterns_1.CODEX_PROMPT_PATTERN.test(contentLines[codexTailIdx].trim()) &&
|
|
411
|
+
!isCodexDialogGlyphTail(frame.raw);
|
|
331
412
|
if (!codexTailIsIdlePrompt && (0, cli_patterns_1.detectThinking)('codex', frame.lastLines)) {
|
|
332
413
|
return {
|
|
333
414
|
status: 'running',
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Command Code status detector (Issue #2250, 方針書 §4 D2).
|
|
4
|
+
*
|
|
5
|
+
* Command Code renders inline and pins a claude-shaped composer block to the
|
|
6
|
+
* bottom of the pane, so the shared chain does most of the work: the permission
|
|
7
|
+
* dialog is a numbered list with a `❯` cursor, which step 1's `detectPrompt`
|
|
8
|
+
* already reads, and the status row carries a spinner + `…` and `esc to
|
|
9
|
+
* interrupt`, which step 2's `detectThinking` already reads.
|
|
10
|
+
*
|
|
11
|
+
* What this module adds is `afterThinking`, and it exists because the generic
|
|
12
|
+
* composer check at step 3 would otherwise answer `ready` for a frame in which
|
|
13
|
+
* the composer is drawn and a turn is still in flight. That is not hypothetical
|
|
14
|
+
* on Command Code: the composer block stays on screen for the whole turn (see
|
|
15
|
+
* `turn-thinking.txt`, where `❯ Ask your question...` sits three rows under
|
|
16
|
+
* ` ⌘ Planning… esc to interrupt`). Step 2's window is
|
|
17
|
+
* `THINKING_TAIL_LINE_COUNT` = 5 lines, and the status row is 4 rows above the
|
|
18
|
+
* last content row on that frame, so it fits today — but a wrapped composer adds
|
|
19
|
+
* rows between them and pushes it out, which is exactly the #805 failure claude
|
|
20
|
+
* had to add a wider footer window for. Re-checking thinking here, against the
|
|
21
|
+
* 15-line `lastLines` window, is that wider window.
|
|
22
|
+
*
|
|
23
|
+
* No `readIdleEvidence`: per §4 D1 決定 1's tool-by-tool rollout (DR2-002) a rule
|
|
24
|
+
* has to be read off the tool's OWN frames before it can gate anything, and the
|
|
25
|
+
* five frames captured for this Issue cover launch / thinking / done / dialog /
|
|
26
|
+
* tool-use rather than the awkward idle states (after a `/clear`, after an Esc
|
|
27
|
+
* interrupt) a completion rule has to survive. `detection-evidence-config` ships
|
|
28
|
+
* `legacy` to match.
|
|
29
|
+
*
|
|
30
|
+
* **Issue #2304 captured both of those idle states, and pinned the cost of not
|
|
31
|
+
* having the rule.** `tests/unit/detection/tools/command-code/fixtures.test.ts`
|
|
32
|
+
* defuses the busy vocabulary on a running frame and measures the answer:
|
|
33
|
+
* `ready` / `input_prompt` / `evidence: 'positive'` — a completion declared on
|
|
34
|
+
* the *absence* of a busy marker, which is exactly what D1 forbids. It costs
|
|
35
|
+
* nothing in production while the rollout says `legacy`, because
|
|
36
|
+
* `resolveIdleEvidence` short-circuits before a tool rule is consulted; what it
|
|
37
|
+
* costs is the rollout itself. The two frames a rule needs are now in
|
|
38
|
+
* `tests/fixtures/command-code-live-2250/`:
|
|
39
|
+
*
|
|
40
|
+
* - after `/clear` — `boot-idle-1490.txt`, because the pane after `/clear` is
|
|
41
|
+
* **byte-identical** to the launch screen. Unlike claude, which leaves
|
|
42
|
+
* `new task? /clear to save …` behind and is the reason its own rule went
|
|
43
|
+
* back to `observe` (#2011), Command Code repaints the banner;
|
|
44
|
+
* - after an Esc interrupt — `idle-after-interrupt-1490.txt`, where Esc landed
|
|
45
|
+
* before the agent had written anything, so the newest turn is a prompt echo
|
|
46
|
+
* followed straight by `✻ Worked for 4s` with no `⠶` reply row at all.
|
|
47
|
+
*
|
|
48
|
+
* Building the rule, and measuring its `observe` rate before it enforces
|
|
49
|
+
* anything, is deliberately a separate Issue: the table it would have to move
|
|
50
|
+
* lives in `@/config/detection-evidence-config`, and `afterThinking`'s idle
|
|
51
|
+
* branch below publishes `'positive'` outright rather than through
|
|
52
|
+
* `resolveIdleEvidence`, so a rule added without changing that would never run.
|
|
53
|
+
*
|
|
54
|
+
* No `detectDialog` either: Epic #2249 決定 3 keeps Auto-Yes on the legacy
|
|
55
|
+
* numbered-response path, because Command Code fires `PreToolUse` AFTER the
|
|
56
|
+
* dialog is answered, so a hook-driven permission decision cannot dismiss it.
|
|
57
|
+
*
|
|
58
|
+
* `afterPrompt` arrived with Issue #2297, for the one screen the shared chain
|
|
59
|
+
* genuinely could not read: the picker `/model` opens. It is a provider-grouped
|
|
60
|
+
* list of model NAMES — no option numbers — over a `› Type to search models...`
|
|
61
|
+
* row, closed by `type to search · ↑/↓ navigate · shift+↑/↓ jump provider ·
|
|
62
|
+
* enter to select · esc to cancel`. None of `detectPrompt`, `detectThinking` or
|
|
63
|
+
* the composer check matches any of that, so the frame reached the `default`
|
|
64
|
+
* floor and the chat surface offered it the answer characters — into the search
|
|
65
|
+
* box. Measured live on v1.40.1 at the production 200x1000 geometry; the capture
|
|
66
|
+
* is `tests/fixtures/chat-dialog-card-2254/command-code-model-1-40-1.txt`.
|
|
67
|
+
*
|
|
68
|
+
* ## What #2304 re-measured, and what it did not change
|
|
69
|
+
*
|
|
70
|
+
* Nothing here changed, and that is the finding. Seven frames were captured
|
|
71
|
+
* live on **1.49.0** — nine minor versions past the build these rules were read
|
|
72
|
+
* off — at the same 200x1000 geometry, and every rule answers identically,
|
|
73
|
+
* state for state. `verifiedAgainst` therefore still records 1.40.1: that is
|
|
74
|
+
* the build the rules were *read off*, and
|
|
75
|
+
* `tests/unit/detection/tools/command-code/fixtures.test.ts` is the receipt that
|
|
76
|
+
* they still hold. It also pins the picker's verdict for the three 1.47.1
|
|
77
|
+
* captures, which had none before — `afterPrompt` reading one build's picker was
|
|
78
|
+
* an assumption about the next.
|
|
79
|
+
*
|
|
80
|
+
* Two 1.49.0 observations are worth carrying here because they bound what the
|
|
81
|
+
* rules rest on:
|
|
82
|
+
*
|
|
83
|
+
* - **A status verb can be three words with no `…`.** ` ✧ Shell command
|
|
84
|
+
* allowed esc to interrupt • 19s • ↓ 1.7k` is not read by
|
|
85
|
+
* `COMMAND_CODE_THINKING_PATTERN`'s spinner branch, which wants
|
|
86
|
+
* `[spinner] <one word>…`. Only the third alternative — the `esc to
|
|
87
|
+
* interrupt` tail — reads it, and the tool drops that tail below 42 columns.
|
|
88
|
+
* CommandMate panes are 200 wide, so it holds; a narrower pane would not.
|
|
89
|
+
* The capture is `turn-shell-running-1490.txt`.
|
|
90
|
+
* - **Evidence can be layered.** That same frame carries ` ✻ Thinking… (72
|
|
91
|
+
* lines) [ctrl+o to expand]` two rows above the status row, so it stays
|
|
92
|
+
* `running` when the status row alone is defused. The single-marker frames
|
|
93
|
+
* (`turn-thinking.txt`, `turn-thinking-1490.txt`) do not, which is the D1 gap
|
|
94
|
+
* described above.
|
|
95
|
+
*/
|
|
96
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
97
|
+
exports.commandCodeStatusDetector = exports.VERIFIED_AGAINST = void 0;
|
|
98
|
+
const cli_patterns_1 = require("../../cli-patterns");
|
|
99
|
+
const selection_shape_1 = require("../../selection-shape");
|
|
100
|
+
const status_reason_1 = require("../../status-reason");
|
|
101
|
+
const run_detection_1 = require("../run-detection");
|
|
102
|
+
const verified_against_1 = require("../verified-against");
|
|
103
|
+
/** Command Code build these rules were read off (value in ../verified-against). */
|
|
104
|
+
exports.VERIFIED_AGAINST = verified_against_1.COMMAND_CODE_VERIFIED_AGAINST;
|
|
105
|
+
exports.commandCodeStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
106
|
+
tool: 'command-code',
|
|
107
|
+
verifiedAgainst: exports.VERIFIED_AGAINST,
|
|
108
|
+
afterPrompt(frame) {
|
|
109
|
+
// Issue #2297. Command Code's pickers (`/model` measured live on v1.40.1 at
|
|
110
|
+
// 200x1000) are arrow-driven overlays with a search box and a lower-case
|
|
111
|
+
// hint-bar footer. Nothing in the shared chain reads that footer, so before
|
|
112
|
+
// this branch the frame fell through to the `default` floor — which the chat
|
|
113
|
+
// surface renders as `unclassified`, i.e. with the `1`-`9` / `y` / `n`
|
|
114
|
+
// answer keys, and every one of those characters is typed into the picker's
|
|
115
|
+
// `Type to search models...` box rather than selecting anything.
|
|
116
|
+
//
|
|
117
|
+
// `waiting` + `positive`, exactly as claude's selection-list branch reports:
|
|
118
|
+
// a human has to move the highlight and press enter, and the frame says so
|
|
119
|
+
// in as many words.
|
|
120
|
+
if (selection_shape_1.COMMAND_CODE_SELECTION_LIST_FOOTER.test(frame.lastLines)) {
|
|
121
|
+
return {
|
|
122
|
+
status: 'waiting',
|
|
123
|
+
confidence: 'high',
|
|
124
|
+
reason: status_reason_1.STATUS_REASON.COMMAND_CODE_SELECTION_LIST,
|
|
125
|
+
hasActivePrompt: false,
|
|
126
|
+
evidence: 'positive',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
},
|
|
131
|
+
afterThinking(frame) {
|
|
132
|
+
// The composer is drawn throughout a turn, so "running" has to be resolved
|
|
133
|
+
// before the generic composer check can say "ready". Widened window; see the
|
|
134
|
+
// module docblock.
|
|
135
|
+
if ((0, cli_patterns_1.detectThinking)('command-code', frame.lastLines)) {
|
|
136
|
+
return {
|
|
137
|
+
status: 'running',
|
|
138
|
+
confidence: 'high',
|
|
139
|
+
reason: status_reason_1.STATUS_REASON.THINKING_INDICATOR,
|
|
140
|
+
hasActivePrompt: false,
|
|
141
|
+
evidence: 'positive',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// Idle: the composer row is on screen and nothing is in flight. Same verdict
|
|
145
|
+
// the generic step 3 would reach, resolved here so the two cannot disagree
|
|
146
|
+
// about which window they read.
|
|
147
|
+
const { promptPattern } = (0, cli_patterns_1.getCliToolPatterns)('command-code');
|
|
148
|
+
if (promptPattern.test(frame.lastLines)) {
|
|
149
|
+
return {
|
|
150
|
+
status: 'ready',
|
|
151
|
+
confidence: 'high',
|
|
152
|
+
reason: status_reason_1.STATUS_REASON.INPUT_PROMPT,
|
|
153
|
+
hasActivePrompt: false,
|
|
154
|
+
evidence: 'positive',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
},
|
|
159
|
+
});
|