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
|
@@ -75,15 +75,24 @@
|
|
|
75
75
|
* of `detectSessionStatus` passes the raw `capture-pane -e` output
|
|
76
76
|
* (`lib/tmux/tmux.ts` always passes `-e`).
|
|
77
77
|
*
|
|
78
|
-
* A leaf module by design: it imports the
|
|
79
|
-
* the excerpt bound and nothing else.
|
|
78
|
+
* A leaf module by design: it imports the SGR background scan, the column rule
|
|
79
|
+
* and the excerpt bound and nothing else.
|
|
80
|
+
*
|
|
81
|
+
* The scan itself moved to `sgr-background.ts` in Issue #2323, which needed the
|
|
82
|
+
* same reading for a card's scroll-follow; that move also repaired a
|
|
83
|
+
* foreground/background confusion in the walk (`38;2;r;g;b` channels were read
|
|
84
|
+
* as 16-colour background codes), so a syntax-highlighted transcript row now
|
|
85
|
+
* produces fewer spurious edges here than it did. It cannot produce more, so no
|
|
86
|
+
* rectangle this module used to read can have stopped being one.
|
|
80
87
|
*
|
|
81
88
|
* @module lib/detection/opencode-modal-overlay
|
|
82
89
|
*/
|
|
83
90
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
84
91
|
exports.OPENCODE_OVERLAY_TRUNCATION_MARKER = exports.OPENCODE_OVERLAY_EXCERPT_MAX_BYTES = exports.OPENCODE_OVERLAY_HEADER_ROW_LIMIT = exports.OPENCODE_OVERLAY_MIN_ROWS = exports.OPENCODE_OVERLAY_MIN_WIDTH = exports.OPENCODE_OVERLAY_MIN_LEFT = exports.OPENCODE_MODAL_OVERLAY_RECOVERY_KEY = exports.OPENCODE_MODAL_OVERLAY_ID = void 0;
|
|
85
92
|
exports.detectOpenCodeModalOverlay = detectOpenCodeModalOverlay;
|
|
93
|
+
exports.extractOpenCodeModalOverlayFrame = extractOpenCodeModalOverlayFrame;
|
|
86
94
|
const excerpt_1 = require("./excerpt");
|
|
95
|
+
const sgr_background_1 = require("./sgr-background");
|
|
87
96
|
const terminal_columns_1 = require("./terminal-columns");
|
|
88
97
|
/**
|
|
89
98
|
* Published `sessionStatusReason` for this signature.
|
|
@@ -204,98 +213,6 @@ const ESCAPE_HATCH_WORD = 'esc';
|
|
|
204
213
|
* a theme that paints the gutter itself is covered by the same rule.
|
|
205
214
|
*/
|
|
206
215
|
const BOX_GUTTER = /^[│┃╹]/;
|
|
207
|
-
/**
|
|
208
|
-
* Every ANSI sequence, in the repository's own spelling.
|
|
209
|
-
*
|
|
210
|
-
* Restated from `ANSI_PATTERN` (`ansi.ts`) rather than imported because this
|
|
211
|
-
* module needs to walk the sequences IN ORDER while counting columns, and that
|
|
212
|
-
* one is a shared `g`-flagged instance whose `lastIndex` a caller must not
|
|
213
|
-
* disturb. `tests/unit/detection-opencode-modal-overlay-2112.test.ts` asserts
|
|
214
|
-
* the text this scan produces is byte-identical to `stripAnsi`'s, so the
|
|
215
|
-
* restatement cannot drift silently.
|
|
216
|
-
*/
|
|
217
|
-
const ANSI_SEQUENCE = /\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\[[0-9;]*m/g;
|
|
218
|
-
/** An SGR sequence, with its parameters. Only these can change the background. */
|
|
219
|
-
const SGR_PARAMETERS = /^(?:\x1b\[|\[)([0-9;]*)m$/;
|
|
220
|
-
/**
|
|
221
|
-
* Fold one SGR sequence's parameters into the current background.
|
|
222
|
-
*
|
|
223
|
-
* Handles the three forms tmux emits: the 16-colour codes (`40`–`47`,
|
|
224
|
-
* `100`–`107`), the 256-colour and 24-bit extended forms (`48;5;n`,
|
|
225
|
-
* `48;2;r;g;b`), and the two resets (`0`, `49`). Foreground and attribute codes
|
|
226
|
-
* leave the background alone, which is what keeps a syntax-highlighted
|
|
227
|
-
* transcript row from producing dozens of spurious edges.
|
|
228
|
-
*/
|
|
229
|
-
function applySgr(current, parameters) {
|
|
230
|
-
const parts = (parameters === '' ? '0' : parameters).split(';');
|
|
231
|
-
let bg = current;
|
|
232
|
-
for (let i = 0; i < parts.length; i++) {
|
|
233
|
-
const code = Number(parts[i] === '' ? '0' : parts[i]);
|
|
234
|
-
if (!Number.isFinite(code))
|
|
235
|
-
continue;
|
|
236
|
-
if (code === 0 || code === 49) {
|
|
237
|
-
bg = null;
|
|
238
|
-
}
|
|
239
|
-
else if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107)) {
|
|
240
|
-
bg = parts[i];
|
|
241
|
-
}
|
|
242
|
-
else if (code === 48) {
|
|
243
|
-
if (parts[i + 1] === '2') {
|
|
244
|
-
bg = parts.slice(i, i + 5).join(';');
|
|
245
|
-
i += 4;
|
|
246
|
-
}
|
|
247
|
-
else if (parts[i + 1] === '5') {
|
|
248
|
-
bg = parts.slice(i, i + 3).join(';');
|
|
249
|
-
i += 2;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return bg;
|
|
254
|
-
}
|
|
255
|
-
/** Measure one captured row: its text, its background runs and their edges. */
|
|
256
|
-
function scanRow(line) {
|
|
257
|
-
ANSI_SEQUENCE.lastIndex = 0;
|
|
258
|
-
const segments = [];
|
|
259
|
-
let text = '';
|
|
260
|
-
let bg = null;
|
|
261
|
-
let columns = 0;
|
|
262
|
-
let segmentStart = 0;
|
|
263
|
-
let cursor = 0;
|
|
264
|
-
let match;
|
|
265
|
-
while ((match = ANSI_SEQUENCE.exec(line)) !== null) {
|
|
266
|
-
const chunk = line.slice(cursor, match.index);
|
|
267
|
-
text += chunk;
|
|
268
|
-
columns += (0, terminal_columns_1.visibleWidth)(chunk);
|
|
269
|
-
cursor = match.index + match[0].length;
|
|
270
|
-
const sgr = SGR_PARAMETERS.exec(match[0]);
|
|
271
|
-
if (sgr === null)
|
|
272
|
-
continue;
|
|
273
|
-
const next = applySgr(bg, sgr[1]);
|
|
274
|
-
if (next === bg)
|
|
275
|
-
continue;
|
|
276
|
-
if (columns > segmentStart)
|
|
277
|
-
segments.push({ bg, start: segmentStart, end: columns });
|
|
278
|
-
bg = next;
|
|
279
|
-
segmentStart = columns;
|
|
280
|
-
}
|
|
281
|
-
const tail = line.slice(cursor);
|
|
282
|
-
text += tail;
|
|
283
|
-
columns += (0, terminal_columns_1.visibleWidth)(tail);
|
|
284
|
-
if (columns > segmentStart)
|
|
285
|
-
segments.push({ bg, start: segmentStart, end: columns });
|
|
286
|
-
const edges = new Set(segments.map(segment => segment.start));
|
|
287
|
-
if (segments.length > 0)
|
|
288
|
-
edges.add(segments[segments.length - 1].end);
|
|
289
|
-
return { text, segments, edges, width: columns };
|
|
290
|
-
}
|
|
291
|
-
/** The background painted at one column, or `null` for the terminal default. */
|
|
292
|
-
function backgroundAt(row, column) {
|
|
293
|
-
for (const segment of row.segments) {
|
|
294
|
-
if (segment.start <= column && column < segment.end)
|
|
295
|
-
return segment.bg;
|
|
296
|
-
}
|
|
297
|
-
return null;
|
|
298
|
-
}
|
|
299
216
|
/**
|
|
300
217
|
* Does this row carry the rectangle `[left, right)`?
|
|
301
218
|
*
|
|
@@ -319,16 +236,17 @@ function carriesRectangle(row, left, right) {
|
|
|
319
236
|
if (segment.bg === null)
|
|
320
237
|
return false;
|
|
321
238
|
}
|
|
322
|
-
if (backgroundAt(row, left - 1) === backgroundAt(row, left))
|
|
239
|
+
if ((0, sgr_background_1.backgroundAt)(row, left - 1) === (0, sgr_background_1.backgroundAt)(row, left))
|
|
323
240
|
return false;
|
|
324
|
-
if (right < row.width && backgroundAt(row, right) === backgroundAt(row, right - 1))
|
|
241
|
+
if (right < row.width && (0, sgr_background_1.backgroundAt)(row, right) === (0, sgr_background_1.backgroundAt)(row, right - 1))
|
|
325
242
|
return false;
|
|
326
243
|
if (BOX_GUTTER.test((0, terminal_columns_1.sliceColumns)(row.text, left - 1, left)))
|
|
327
244
|
return false;
|
|
328
245
|
return !BOX_GUTTER.test((0, terminal_columns_1.sliceColumns)(row.text, left, right));
|
|
329
246
|
}
|
|
330
247
|
/**
|
|
331
|
-
* The modal overlay painted over an opencode transcript,
|
|
248
|
+
* The modal overlay painted over an opencode transcript, plus the frame rows it
|
|
249
|
+
* spans — or null.
|
|
332
250
|
*
|
|
333
251
|
* Call it only for opencode: the rule is about opencode's own dialog chrome, and
|
|
334
252
|
* every other tool is left exactly as it was (Issue #2112 changes no other
|
|
@@ -346,12 +264,14 @@ function carriesRectangle(row, left, right) {
|
|
|
346
264
|
*
|
|
347
265
|
* A caveat the seeding makes easy to miss: two identical rows are two entries in
|
|
348
266
|
* `carrying`, so the title-bar check below compares object identity rather than
|
|
349
|
-
* value
|
|
267
|
+
* value — and `frameRowStart` / `frameRowEnd` are read the same way, by asking
|
|
268
|
+
* `rows.indexOf(...)` for the first and last object in `carrying` rather than by
|
|
269
|
+
* re-matching text.
|
|
350
270
|
*
|
|
351
271
|
* @param frame - The capture with its ANSI intact (`capture-pane -e`)
|
|
352
272
|
*/
|
|
353
|
-
function
|
|
354
|
-
const rows = frame.split('\n').map(
|
|
273
|
+
function findOpenCodeModalOverlay(frame) {
|
|
274
|
+
const rows = frame.split('\n').map(sgr_background_1.scanRowBackgrounds);
|
|
355
275
|
const examined = new Set();
|
|
356
276
|
let best = null;
|
|
357
277
|
for (const row of rows) {
|
|
@@ -391,6 +311,8 @@ function detectOpenCodeModalOverlay(frame) {
|
|
|
391
311
|
right,
|
|
392
312
|
rows: carrying.length,
|
|
393
313
|
headerRow,
|
|
314
|
+
frameRowStart: rows.indexOf(carrying[0]),
|
|
315
|
+
frameRowEnd: rows.indexOf(carrying[carrying.length - 1]),
|
|
394
316
|
};
|
|
395
317
|
}
|
|
396
318
|
}
|
|
@@ -398,3 +320,47 @@ function detectOpenCodeModalOverlay(frame) {
|
|
|
398
320
|
}
|
|
399
321
|
return best;
|
|
400
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* The modal overlay painted over an opencode transcript, or null.
|
|
325
|
+
*
|
|
326
|
+
* @param frame - The capture with its ANSI intact (`capture-pane -e`)
|
|
327
|
+
* @see findOpenCodeModalOverlay
|
|
328
|
+
*/
|
|
329
|
+
function detectOpenCodeModalOverlay(frame) {
|
|
330
|
+
const match = findOpenCodeModalOverlay(frame);
|
|
331
|
+
if (match === null)
|
|
332
|
+
return null;
|
|
333
|
+
return {
|
|
334
|
+
id: match.id,
|
|
335
|
+
headerText: match.headerText,
|
|
336
|
+
left: match.left,
|
|
337
|
+
right: match.right,
|
|
338
|
+
rows: match.rows,
|
|
339
|
+
headerRow: match.headerRow,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* The rows of `frame` covered by opencode's modal overlay, full width and with
|
|
344
|
+
* ANSI intact — or `null` when no overlay is found (Issue #2309).
|
|
345
|
+
*
|
|
346
|
+
* opencode paints its overlay mid-transcript rather than clearing the pane for
|
|
347
|
+
* it (measured: `tests/fixtures/opencode-live-2047/w200/command-palette.txt`
|
|
348
|
+
* shows the conversation on both sides of a centred 60-column box). A dialog
|
|
349
|
+
* card that just took "the whole frame minus blank runs" would drag that
|
|
350
|
+
* transcript in with it and render the overlay as a smear across a page of
|
|
351
|
+
* unrelated text; cropping to the rectangle's own row span is what makes the
|
|
352
|
+
* card show the dialog and nothing else.
|
|
353
|
+
*
|
|
354
|
+
* Column-crop is deliberately NOT done here: the card already scrolls
|
|
355
|
+
* sideways for a 200-column frame (`ChatDialogCard`'s `overflow-auto`), and
|
|
356
|
+
* slicing columns would cut an open SGR sequence started to the rectangle's
|
|
357
|
+
* left, losing the colour state the row depends on.
|
|
358
|
+
*
|
|
359
|
+
* @param frame - The capture with its ANSI intact (`capture-pane -e`)
|
|
360
|
+
*/
|
|
361
|
+
function extractOpenCodeModalOverlayFrame(frame) {
|
|
362
|
+
const match = findOpenCodeModalOverlay(frame);
|
|
363
|
+
if (match === null)
|
|
364
|
+
return null;
|
|
365
|
+
return frame.split('\n').slice(match.frameRowStart, match.frameRowEnd + 1).join('\n');
|
|
366
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What a selection-list frame OFFERS, read off the frame itself (Issue #2297).
|
|
4
|
+
*
|
|
5
|
+
* Issue #2254 gave the chat surface a dialog card, and gave every selection list
|
|
6
|
+
* the same controls: `NavigationButtons`, i.e. ▲▼◀▶ Enter Esc. That is the right
|
|
7
|
+
* verb for a moving highlight and it is not the whole story, because the TUIs
|
|
8
|
+
* disagree about what CONFIRMS:
|
|
9
|
+
*
|
|
10
|
+
* | measured screen | what the footer says |
|
|
11
|
+
* |-------------------------------------|---------------------------------------------------------------|
|
|
12
|
+
* | claude 2.1.259/2.1.260 `/model` | `Enter to set as default · s to use this session only · Esc` |
|
|
13
|
+
* | codex 0.151.0 `/model` | `Press enter to confirm or esc to go back` |
|
|
14
|
+
* | copilot 1.0.80 `/permissions` | `1-2 to select · ↑/↓ to navigate · enter to confirm · esc` |
|
|
15
|
+
* | copilot 1.0.80 `/model` | `↑/↓ to navigate · … · enter to select · esc to cancel`, over a `❯ Search models…` row |
|
|
16
|
+
* | Command Code 1.40.1 `/model` | `type to search · ↑/↓ navigate · … · enter to select · esc` |
|
|
17
|
+
* | antigravity `Switch Model` | name rows, no numbers |
|
|
18
|
+
*
|
|
19
|
+
* So the surface cannot pick its buttons from the tool id. It picks them from
|
|
20
|
+
* the frame it is already drawing, which is what this module reads.
|
|
21
|
+
*
|
|
22
|
+
* ## The three readings, and why each one is worth its own field
|
|
23
|
+
*
|
|
24
|
+
* **`optionCount`** — how many numbered options the dialog is offering, so the
|
|
25
|
+
* card can put a `1`…`N` row under it and turn a seven-step arrow walk into one
|
|
26
|
+
* tap. Zero means "no numbered list here", which is the honest answer for
|
|
27
|
+
* antigravity's `Switch Model` and Command Code's name list, and those keep the
|
|
28
|
+
* arrows they already work with.
|
|
29
|
+
*
|
|
30
|
+
* **`offersSessionScope`** — the footer names a key that takes the highlighted
|
|
31
|
+
* row for THIS SESSION. Only claude's `/model` does, and it is the whole reason
|
|
32
|
+
* Issue #2297 exists: `Enter` on that overlay rewrites `model` in
|
|
33
|
+
* `~/.claude/settings.json` (Issue #1495) and `s` does not, and the chat surface
|
|
34
|
+
* published the first and not the second.
|
|
35
|
+
*
|
|
36
|
+
* **`hasFilterInput`** — the dialog has a focused search box. This is the guard
|
|
37
|
+
* that keeps `optionCount` from being a trap: on copilot's `/model` and Command
|
|
38
|
+
* Code's picker a typed character goes into the filter, not into a selection, so
|
|
39
|
+
* a number button there would silently type `4` into a search field.
|
|
40
|
+
*
|
|
41
|
+
* ## MEASURED: on claude's `/model`, a number key is not a cursor move
|
|
42
|
+
*
|
|
43
|
+
* Issue #2297's plan B reads "number buttons move the highlight, then the tool's
|
|
44
|
+
* own confirm key commits". A live probe on claude 2.1.260 (private tmux socket,
|
|
45
|
+
* 200x1000) says otherwise: pressing `4` on the `/model` overlay answered
|
|
46
|
+
* `Set model to Sonnet 5 and saved as your default for new sessions` and
|
|
47
|
+
* rewrote `~/.claude/settings.json` in one keystroke. The number key IS the
|
|
48
|
+
* commit, and on that screen the commit is the global write the Issue is about.
|
|
49
|
+
*
|
|
50
|
+
* That is why {@link shouldOfferOptionNumbers} refuses the number row exactly
|
|
51
|
+
* where {@link SelectionListShape.offersSessionScope} is true. On claude's
|
|
52
|
+
* `/model` the card offers arrows plus the two LABELLED commits (`s` = this
|
|
53
|
+
* session, `Enter` = set as default) and no unlabelled one-tap default write;
|
|
54
|
+
* every other numbered list — codex's picker, copilot's `/permissions`, claude's
|
|
55
|
+
* own `Enter to select`/`Enter to confirm` dialogs — keeps its numbers.
|
|
56
|
+
*
|
|
57
|
+
* ## Pure, leaf, browser-safe
|
|
58
|
+
*
|
|
59
|
+
* `./ansi` is the only import, exactly as `lib/terminal-display-normalize`
|
|
60
|
+
* takes it: the consumer is `ChatSurface`, a client component, and pulling
|
|
61
|
+
* `cli-patterns` (logger, tool registry types) into the browser bundle to reach
|
|
62
|
+
* three regexes would be the wrong trade. The command-code detector imports
|
|
63
|
+
* {@link COMMAND_CODE_SELECTION_LIST_FOOTER} back out of here so the pattern is
|
|
64
|
+
* written once.
|
|
65
|
+
*/
|
|
66
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
67
|
+
exports.COMMAND_CODE_SELECTION_LIST_FOOTER = exports.SET_AS_DEFAULT_FOOTER_PATTERN = exports.SESSION_SCOPE_FOOTER_PATTERN = exports.MAX_OPTION_NUMBER = exports.SELECTION_SHAPE_TAIL_LINE_COUNT = void 0;
|
|
68
|
+
exports.extractCommandCodeSelectionListFrame = extractCommandCodeSelectionListFrame;
|
|
69
|
+
exports.readSelectionListShape = readSelectionListShape;
|
|
70
|
+
exports.shouldOfferOptionNumbers = shouldOfferOptionNumbers;
|
|
71
|
+
const ansi_1 = require("./ansi");
|
|
72
|
+
/**
|
|
73
|
+
* How many rows up from the last content row the shape is read.
|
|
74
|
+
*
|
|
75
|
+
* The dialog is at the END of the content on every capture measured for Issue
|
|
76
|
+
* #2254 — including the top-anchored ones, where "the end of the content" is
|
|
77
|
+
* row 32 of a 1000-row pane and everything below it is padding. Forty rows
|
|
78
|
+
* covers the tallest dialog in `tests/fixtures/chat-dialog-card-2254/`
|
|
79
|
+
* (copilot's `/theme` panel is 15 rows, Command Code's provider-grouped model
|
|
80
|
+
* list is ~70 and is deliberately NOT fully covered — see `optionCount`, which
|
|
81
|
+
* wants the run nearest the footer rather than every number on the pane).
|
|
82
|
+
*
|
|
83
|
+
* Bounded rather than unbounded because the alternative reads the transcript: a
|
|
84
|
+
* markdown answer that happens to contain `1.` / `2.` sits hundreds of rows
|
|
85
|
+
* above the dialog on a 200x1000 pane and must not be counted as options.
|
|
86
|
+
*/
|
|
87
|
+
exports.SELECTION_SHAPE_TAIL_LINE_COUNT = 40;
|
|
88
|
+
/** Highest option number a single keystroke can deliver (`10` is two keys). */
|
|
89
|
+
exports.MAX_OPTION_NUMBER = 9;
|
|
90
|
+
/**
|
|
91
|
+
* One numbered option row.
|
|
92
|
+
*
|
|
93
|
+
* The prefix is `[^0-9A-Za-z]*` rather than `\s*` because every measured dialog
|
|
94
|
+
* puts something in front of the number: a selection caret (`❯` claude/copilot,
|
|
95
|
+
* `›` codex, `●` gemini), a panel border (`│` copilot's boxed pickers), or a
|
|
96
|
+
* bullet. Requiring a non-alphanumeric prefix is what keeps `id 3. foo` and a
|
|
97
|
+
* wrapped sentence ending in a digit out.
|
|
98
|
+
*
|
|
99
|
+
* The trailing `\s+\S` requires the option to have a LABEL, which is what stops
|
|
100
|
+
* a diff gutter (`5 - export default getUser;`, live in
|
|
101
|
+
* `copilot-picker-1895/picker-theme.txt`) from matching: it has no `.` or `)`
|
|
102
|
+
* after the digit, and this pattern requires one.
|
|
103
|
+
*/
|
|
104
|
+
const OPTION_ROW_PATTERN = /^[^0-9A-Za-z]*([1-9])[.)]\s+\S/;
|
|
105
|
+
/**
|
|
106
|
+
* claude's session-scope footer, verbatim from the live captures.
|
|
107
|
+
*
|
|
108
|
+
* `s to use this session only`. Not anchored to a line start because the footer
|
|
109
|
+
* shares its row with the other two hints.
|
|
110
|
+
*/
|
|
111
|
+
exports.SESSION_SCOPE_FOOTER_PATTERN = /\bs\s+to\s+use\s+this\s+session\s+only\b/i;
|
|
112
|
+
/**
|
|
113
|
+
* The footer half that says `Enter` writes a default rather than confirming.
|
|
114
|
+
*
|
|
115
|
+
* Kept separate from {@link SESSION_SCOPE_FOOTER_PATTERN} so the card can label
|
|
116
|
+
* the two buttons from what the frame actually claims, instead of asserting
|
|
117
|
+
* claude's wording for a screen that may not carry it.
|
|
118
|
+
*/
|
|
119
|
+
exports.SET_AS_DEFAULT_FOOTER_PATTERN = /\bEnter\s+to\s+set\s+as\s+default\b/i;
|
|
120
|
+
/**
|
|
121
|
+
* A focused search/filter row inside the dialog.
|
|
122
|
+
*
|
|
123
|
+
* Three measured spellings, and nothing wider — this predicate SUPPRESSES a
|
|
124
|
+
* control, so a false positive costs the user their number buttons:
|
|
125
|
+
* - `Type to search models...` / `type to search` (Command Code 1.40.1);
|
|
126
|
+
* - `Search models…` (copilot 1.0.80's `/model`, recorded verbatim in
|
|
127
|
+
* `cli-patterns.ts`'s `COPILOT_SELECTION_FOOTER_PATTERN` docblock);
|
|
128
|
+
* - `/ search` (copilot's `/session` and `/settings` footers).
|
|
129
|
+
*
|
|
130
|
+
* Deliberately does NOT match claude's `/model` blurb ("Switch between Claude
|
|
131
|
+
* models…") or codex's ("Access legacy models by running codex -m…"), neither of
|
|
132
|
+
* which contains the word.
|
|
133
|
+
*/
|
|
134
|
+
const FILTER_INPUT_PATTERN = /\btype\s+to\s+search\b|\bsearch\s+\w+\s*(?:…|\.\.\.)|(?:^|·)\s*\/\s+search\b/im;
|
|
135
|
+
/**
|
|
136
|
+
* Command Code's picker footer (v1.40.1, measured at 200x1000 for Issue #2297).
|
|
137
|
+
*
|
|
138
|
+
* type to search · ↑/↓ navigate · shift+↑/↓ jump provider · enter to select · esc to cancel
|
|
139
|
+
*
|
|
140
|
+
* Before this Issue no detector branch matched it, so the overlay fell through
|
|
141
|
+
* to the `default` floor and the chat surface raised its `unclassified` card —
|
|
142
|
+
* whose controls are the `1`–`9` / `y` / `n` answer keys, every one of which
|
|
143
|
+
* would have been typed into that `Type to search models...` box. The
|
|
144
|
+
* command-code detector imports this and answers
|
|
145
|
+
* `STATUS_REASON.COMMAND_CODE_SELECTION_LIST` instead, which puts the arrow pad
|
|
146
|
+
* on the card.
|
|
147
|
+
*
|
|
148
|
+
* Lower case is what Command Code draws, and the `·` separator keeps the pattern
|
|
149
|
+
* off ordinary prose — the same two narrowings `COPILOT_SELECTION_FOOTER_PATTERN`
|
|
150
|
+
* settled on for the same reason.
|
|
151
|
+
*/
|
|
152
|
+
exports.COMMAND_CODE_SELECTION_LIST_FOOTER = /\benter\s+to\s+select\b\s*[·•]\s*esc\s+to\s+cancel\b/i;
|
|
153
|
+
/**
|
|
154
|
+
* The horizontal rule Command Code draws directly above a full-screen dialog.
|
|
155
|
+
*
|
|
156
|
+
* Command Code is an INLINE tool (`alternate_on=0`): opening `/model` does not
|
|
157
|
+
* clear the pane, it paints the picker under whatever the session has already
|
|
158
|
+
* printed. On the capture taken for Issue #2326 that is 256 rows of banner and
|
|
159
|
+
* transcript followed by a 77-row picker, and this rule row is the seam between
|
|
160
|
+
* them — 200 columns of U+2500 at the production `TUI_PANE_WIDTH`, the only
|
|
161
|
+
* such row anywhere on the frame while the picker is open (the composer's own
|
|
162
|
+
* two rules are not drawn while a dialog has the screen).
|
|
163
|
+
*
|
|
164
|
+
* Matched as "nothing but the rule glyph", not as "contains one", because a box
|
|
165
|
+
* border (`╭──…──╮`, which is how copilot draws ITS pickers) carries corners and
|
|
166
|
+
* must NOT be read as this seam — see
|
|
167
|
+
* {@link extractCommandCodeSelectionListFrame} for why that non-match is the
|
|
168
|
+
* safe answer rather than a missed case.
|
|
169
|
+
*/
|
|
170
|
+
const COMMAND_CODE_RULE_ROW_PATTERN = /^\u2500+$/;
|
|
171
|
+
/**
|
|
172
|
+
* How wide a rule row must be before it counts as the dialog seam.
|
|
173
|
+
*
|
|
174
|
+
* The measured row is the full pane width (200 columns), and a pure function
|
|
175
|
+
* cannot know that width, so this is a floor rather than an equality: it only
|
|
176
|
+
* has to reject a short dash run inside a reply. Forty columns is a quarter of
|
|
177
|
+
* the production pane and wider than any decorative rule measured in
|
|
178
|
+
* `tests/fixtures/`.
|
|
179
|
+
*/
|
|
180
|
+
const COMMAND_CODE_RULE_MIN_COLUMNS = 40;
|
|
181
|
+
/**
|
|
182
|
+
* The rows of a Command Code dialog, cut out of the pane it is painted on
|
|
183
|
+
* (Issue #2326).
|
|
184
|
+
*
|
|
185
|
+
* ## Why the dialog card needs a rectangle here at all
|
|
186
|
+
*
|
|
187
|
+
* Issue #2309 gave a selection list every compacted row of the frame instead of
|
|
188
|
+
* a 12–20 row tail, because a search-type picker is tens of rows long and a
|
|
189
|
+
* tail slice threw away rows the arrows could still reach. That is right for a
|
|
190
|
+
* tool that clears the screen. Command Code does not: measured on 2026-09-05
|
|
191
|
+
* (v1.47.1, private socket, 200x1000), a five-turn session with `/model` open
|
|
192
|
+
* gives a 333-row frame of which **256 rows are banner and transcript** and 77
|
|
193
|
+
* are the picker. The card drew all 333, so the picker sat below the fold and
|
|
194
|
+
* the arrow-moved highlight — which {@link findHighlightLineIndex} does now
|
|
195
|
+
* locate correctly, Issue #2323 — was scrolled to inside a box whose visible
|
|
196
|
+
* thirty rows were somebody's earlier conversation.
|
|
197
|
+
*
|
|
198
|
+
* `extractOpenCodeModalOverlayFrame` solves the same problem for opencode by
|
|
199
|
+
* reading its painted rectangle. Command Code paints no rectangle (only the
|
|
200
|
+
* selected ROW carries a background, which is exactly what #2323 turned into
|
|
201
|
+
* the highlight rule), so the seam is read from the two things the picker draws
|
|
202
|
+
* that the transcript does not: the rule above it, and the footer below it.
|
|
203
|
+
*
|
|
204
|
+
* ## The cut
|
|
205
|
+
*
|
|
206
|
+
* Bottom edge: the LAST row matching {@link COMMAND_CODE_SELECTION_LIST_FOOTER}
|
|
207
|
+
* — the same pattern the command-code detector already classifies the screen
|
|
208
|
+
* with, so the card cannot disagree with the detector about whether a picker is
|
|
209
|
+
* up. Top edge: the row AFTER the nearest {@link COMMAND_CODE_RULE_ROW_PATTERN}
|
|
210
|
+
* above that footer (the rule itself is the transcript's boundary, not the
|
|
211
|
+
* dialog's first row; the blank that usually follows it is dropped by the
|
|
212
|
+
* caller's blank-run compaction).
|
|
213
|
+
*
|
|
214
|
+
* ## Both non-matches are the safe answer
|
|
215
|
+
*
|
|
216
|
+
* `null` means "do not crop", and the caller then behaves exactly as it did
|
|
217
|
+
* before this Issue. Two frames take that path deliberately:
|
|
218
|
+
*
|
|
219
|
+
* - **no footer** — the picker was closed between the flags being read and the
|
|
220
|
+
* pane being captured, or the frame is some other dialog. Cropping on a
|
|
221
|
+
* guess would blank the card, which Issue #2326 calls out as worse than
|
|
222
|
+
* showing too much;
|
|
223
|
+
* - **a footer but no rule above it** — copilot's `/model` footer is
|
|
224
|
+
* `↑/↓ to navigate · … · enter to select · esc to cancel` and matches the
|
|
225
|
+
* same pattern, but copilot draws its picker in a corner-bordered box, so no
|
|
226
|
+
* row is nothing-but-rule and copilot's card is returned untouched. Verified
|
|
227
|
+
* on every committed fixture by `dialog-frame-2326.test.ts`.
|
|
228
|
+
*
|
|
229
|
+
* The one degradation this accepts: if the picker's own rule has scrolled off
|
|
230
|
+
* the top of the capture, the nearest rule above the footer is an older one and
|
|
231
|
+
* the crop keeps some transcript. That is strictly less than the whole pane,
|
|
232
|
+
* which is what the frame would otherwise be.
|
|
233
|
+
*
|
|
234
|
+
* @param frame - a raw `capture-pane -p -e` frame, ANSI intact
|
|
235
|
+
* @returns the dialog's own rows, ANSI intact, or `null` to crop nothing
|
|
236
|
+
*/
|
|
237
|
+
function extractCommandCodeSelectionListFrame(frame) {
|
|
238
|
+
const lines = frame.replace(/\r\n/g, '\n').split('\n');
|
|
239
|
+
let footer = -1;
|
|
240
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
241
|
+
if (exports.COMMAND_CODE_SELECTION_LIST_FOOTER.test((0, ansi_1.stripAnsi)(lines[i]))) {
|
|
242
|
+
footer = i;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (footer < 0)
|
|
247
|
+
return null;
|
|
248
|
+
for (let i = footer - 1; i >= 0; i -= 1) {
|
|
249
|
+
const row = (0, ansi_1.stripAnsi)(lines[i]).trim();
|
|
250
|
+
if (row.length < COMMAND_CODE_RULE_MIN_COLUMNS)
|
|
251
|
+
continue;
|
|
252
|
+
if (!COMMAND_CODE_RULE_ROW_PATTERN.test(row))
|
|
253
|
+
continue;
|
|
254
|
+
return lines.slice(i + 1, footer + 1).join('\n');
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
/** The reading for a frame that carries no dialog at all. */
|
|
259
|
+
const EMPTY_SHAPE = {
|
|
260
|
+
optionCount: 0,
|
|
261
|
+
offersSessionScope: false,
|
|
262
|
+
commitsDefaultOnEnter: false,
|
|
263
|
+
hasFilterInput: false,
|
|
264
|
+
};
|
|
265
|
+
/** The last {@link SELECTION_SHAPE_TAIL_LINE_COUNT} rows that carry content. */
|
|
266
|
+
function tailLines(frame) {
|
|
267
|
+
const lines = (0, ansi_1.stripAnsi)(frame.replace(/\r\n/g, '\n')).split('\n');
|
|
268
|
+
let last = lines.length - 1;
|
|
269
|
+
while (last >= 0 && lines[last].trim() === '')
|
|
270
|
+
last -= 1;
|
|
271
|
+
if (last < 0)
|
|
272
|
+
return [];
|
|
273
|
+
return lines.slice(Math.max(0, last + 1 - exports.SELECTION_SHAPE_TAIL_LINE_COUNT), last + 1);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Count the LAST run of option rows numbered `1, 2, 3, …`.
|
|
277
|
+
*
|
|
278
|
+
* Restarting the run on every fresh `1` is what makes the codex launch frame
|
|
279
|
+
* safe: whatever numbered rows preceded the picker, the count that survives is
|
|
280
|
+
* the one belonging to the run nearest the footer. A number out of sequence ends
|
|
281
|
+
* the run without erasing what it had already reached, so copilot's `/session`
|
|
282
|
+
* list — which numbers past `9` — still reports its first nine.
|
|
283
|
+
*/
|
|
284
|
+
function countTrailingOptionRun(lines) {
|
|
285
|
+
let reached = 0;
|
|
286
|
+
let running = 0;
|
|
287
|
+
for (const line of lines) {
|
|
288
|
+
const match = OPTION_ROW_PATTERN.exec(line);
|
|
289
|
+
if (match === null)
|
|
290
|
+
continue;
|
|
291
|
+
const value = Number(match[1]);
|
|
292
|
+
if (value === running + 1) {
|
|
293
|
+
running = value;
|
|
294
|
+
reached = value;
|
|
295
|
+
}
|
|
296
|
+
else if (value === 1) {
|
|
297
|
+
running = 1;
|
|
298
|
+
reached = 1;
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
running = 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return Math.min(reached, exports.MAX_OPTION_NUMBER);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Read what the dialog on this frame offers.
|
|
308
|
+
*
|
|
309
|
+
* @param frame - a raw `capture-pane -p -e` frame (`PaneTerminalState.output`)
|
|
310
|
+
* @returns the shape; all-false / zero for an empty or missing frame
|
|
311
|
+
*/
|
|
312
|
+
function readSelectionListShape(frame) {
|
|
313
|
+
if (!frame)
|
|
314
|
+
return EMPTY_SHAPE;
|
|
315
|
+
const lines = tailLines(frame);
|
|
316
|
+
if (lines.length === 0)
|
|
317
|
+
return EMPTY_SHAPE;
|
|
318
|
+
const tail = lines.join('\n');
|
|
319
|
+
return {
|
|
320
|
+
optionCount: countTrailingOptionRun(lines),
|
|
321
|
+
offersSessionScope: exports.SESSION_SCOPE_FOOTER_PATTERN.test(tail),
|
|
322
|
+
commitsDefaultOnEnter: exports.SET_AS_DEFAULT_FOOTER_PATTERN.test(tail),
|
|
323
|
+
hasFilterInput: FILTER_INPUT_PATTERN.test(tail),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Whether the card may draw a `1`…`N` row for this shape.
|
|
328
|
+
*
|
|
329
|
+
* Two refusals, both measured rather than defensive:
|
|
330
|
+
*
|
|
331
|
+
* - **a session-scope footer.** On claude's `/model` a number key commits AND
|
|
332
|
+
* rewrites the global default in one press (probed live on 2.1.260), so a
|
|
333
|
+
* number button there is an unlabelled version of the exact write Issue
|
|
334
|
+
* #2297 is about. That screen gets the two labelled commit buttons instead.
|
|
335
|
+
* - **a filter input.** copilot's `/model` and Command Code's picker put a
|
|
336
|
+
* focused search box on the dialog, where a `4` is four characters of a
|
|
337
|
+
* query and not the fourth model.
|
|
338
|
+
*/
|
|
339
|
+
function shouldOfferOptionNumbers(shape) {
|
|
340
|
+
return shape.optionCount > 0 && !shape.offersSessionScope && !shape.hasFilterInput;
|
|
341
|
+
}
|