commandmate 0.44.1 → 0.44.2
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 +159 -159
- package/.next/app-path-routes-manifest.json +32 -32
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- 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/release-notes/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_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 +2 -2
- 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 +2 -2
- 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/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/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/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/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]/direct-input/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.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.js +1 -2
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js.nft.json +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.js +1 -2
- package/.next/server/app/api/worktrees/[id]/opencode/share/route.js.nft.json +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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.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 +3 -3
- 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_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.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 +2 -2
- 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.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.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.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/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_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +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 +9 -9
- 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 +32 -32
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1210.js +1 -1
- package/.next/server/chunks/2460.js +1 -0
- package/.next/server/chunks/2908.js +1 -0
- package/.next/server/chunks/4372.js +5 -0
- package/.next/server/chunks/5595.js +1 -0
- package/.next/server/chunks/5845.js +1 -0
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6474.js +2 -2
- package/.next/server/chunks/850.js +1 -0
- package/.next/server/chunks/8543.js +1 -1
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/9130.js +1 -5
- package/.next/server/chunks/9390.js +1 -2
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/967.js +1 -1
- package/.next/server/chunks/9731.js +2 -2
- package/.next/server/chunks/9798.js +2 -0
- package/.next/server/chunks/9882.js +3 -3
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-f1f258d4a1d92620.js → 2407-051f6f84226a9f2c.js} +1 -1
- package/.next/static/chunks/591-539fec878c9dec5e.js +1 -0
- package/.next/static/chunks/app/{layout-da66300cc20244ed.js → layout-9da1ab602bcb3051.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-2a81397e60f17e63.js +1 -0
- package/.next/trace +13 -13
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +7 -8
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +36 -2
- package/dist/cli/types/api-responses.d.ts +15 -0
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/lib/session/prompt-view.d.ts +205 -0
- package/dist/lib/session/prompt-view.d.ts.map +1 -0
- package/dist/lib/session/prompt-view.js +267 -0
- package/dist/server/server.js +5 -3
- package/dist/server/src/lib/auto-yes-lifecycle.js +133 -0
- package/dist/server/src/lib/auto-yes-poller.js +19 -4
- package/dist/server/src/lib/cli-tools/antigravity.js +1 -1
- package/dist/server/src/lib/detection/cli-patterns.js +38 -20
- package/dist/server/src/lib/detection/status-detector.js +1 -1
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +7 -31
- package/dist/server/src/lib/detection/tools/antigravity/live-region.js +39 -0
- package/dist/server/src/lib/detection/tools/claude/detect.js +8 -3
- package/dist/server/src/lib/detection/tools/claude/live-region.js +26 -0
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +1 -1
- package/dist/server/src/lib/detection/tools/codex/detect.js +26 -46
- package/dist/server/src/lib/detection/tools/codex/live-region.js +73 -0
- package/dist/server/src/lib/detection/tools/command-code/detect.js +11 -0
- package/dist/server/src/lib/detection/tools/command-code/live-region.js +36 -0
- package/dist/server/src/lib/detection/tools/copilot/detect.js +3 -0
- package/dist/server/src/lib/detection/tools/copilot/live-region.js +52 -0
- package/dist/server/src/lib/detection/tools/frame.js +36 -2
- package/dist/server/src/lib/detection/tools/live-region-specs.js +31 -0
- package/dist/server/src/lib/detection/tools/live-region.js +204 -0
- package/dist/server/src/lib/detection/tools/opencode/detect.js +3 -0
- package/dist/server/src/lib/detection/tools/opencode/live-region.js +24 -0
- package/dist/server/src/lib/detection/tools/opencode-gutter-live-region.js +72 -0
- package/dist/server/src/lib/detection/tools/opencode-v2/detect.js +3 -0
- package/dist/server/src/lib/detection/tools/opencode-v2/live-region.js +24 -0
- package/dist/server/src/lib/detection/tools/run-detection.js +25 -3
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +16 -4
- package/dist/server/src/lib/polling/response-checker.js +25 -20
- package/dist/server/src/lib/prompt-answer-sender.js +1 -1
- package/dist/server/src/lib/realtime/terminal-broadcast.js +3 -0
- package/dist/server/src/lib/relay/relay-delivery.js +3 -0
- package/dist/server/src/lib/relay/relay-triggers.js +9 -0
- package/dist/server/src/lib/resource-cleanup.js +6 -4
- package/dist/server/src/lib/session/current-output-builder.js +4 -0
- package/dist/server/src/lib/session/prompt-view.js +267 -0
- package/dist/server/src/lib/session/prompt-waiting-composition.js +34 -0
- package/dist/server/src/lib/session/waiting-kind.js +3 -0
- package/dist/server/src/lib/session-cleanup.js +5 -3
- package/package.json +1 -1
- package/release-notes/0.44.2.json +33 -0
- package/.next/server/chunks/434.js +0 -1
- package/.next/server/chunks/5775.js +0 -1
- package/.next/server/chunks/650.js +0 -1
- package/.next/server/chunks/6661.js +0 -1
- package/.next/server/chunks/8583.js +0 -1
- package/.next/server/chunks/964.js +0 -1
- package/.next/static/chunks/591-308072f285c34787.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-040c5f0f585e6812.js +0 -1
- /package/.next/static/{57lOiz8zSEHdw97XIm0af → QlCqLjorauDDBXPa-C7TK}/_buildManifest.js +0 -0
- /package/.next/static/{57lOiz8zSEHdw97XIm0af → QlCqLjorauDDBXPa-C7TK}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The live region: "where on this frame does the part the operator can act on
|
|
4
|
+
* begin?" (Issue #3183, `docs/design/3183-live-region-extraction.md`).
|
|
5
|
+
*
|
|
6
|
+
* Before this module every tool answered that question on its own — codex by
|
|
7
|
+
* the bottom-most `›` row (#892) and again by its SGR (#2841), agy by a `>`
|
|
8
|
+
* under the list (#2845 / #2851), Command Code by a footer at the very bottom
|
|
9
|
+
* (#2846), claude by the input box (#2847) — and a fix to one tool reached no
|
|
10
|
+
* other. Here the answer is computed once per frame, by `normalizeFrame`, from
|
|
11
|
+
* each tool's {@link LiveRegionSpec}; the status chain and the Auto-Yes path
|
|
12
|
+
* then apply the SAME two rules to it:
|
|
13
|
+
*
|
|
14
|
+
* - {@link isQuotedNumberedPrompt}: a numbered list on a frame whose input box
|
|
15
|
+
* is the bottom of the pane is conversation text, not a dialog;
|
|
16
|
+
* - {@link vetoesDialog}: likewise for a tool's own dialog reading.
|
|
17
|
+
*
|
|
18
|
+
* This file holds the shared parts the per-tool declarations are built from and
|
|
19
|
+
* the two rules. It must stay free of the detector modules (`<tool>/detect.ts`)
|
|
20
|
+
* so `normalizeFrame` can use it without an import cycle.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.wholeFrameRegion = wholeFrameRegion;
|
|
24
|
+
exports.locateLiveRegion = locateLiveRegion;
|
|
25
|
+
exports.isQuotedNumberedPrompt = isQuotedNumberedPrompt;
|
|
26
|
+
exports.vetoesDialog = vetoesDialog;
|
|
27
|
+
exports.fencedComposer = fencedComposer;
|
|
28
|
+
exports.bottomMostComposerRow = bottomMostComposerRow;
|
|
29
|
+
exports.dialogTopFrom = dialogTopFrom;
|
|
30
|
+
exports.ruleAboveOptionRun = ruleAboveOptionRun;
|
|
31
|
+
exports.lastContentRow = lastContentRow;
|
|
32
|
+
/** The whole frame — the reading every rule had before Issue #3183. */
|
|
33
|
+
function wholeFrameRegion(tool, contentLines) {
|
|
34
|
+
return {
|
|
35
|
+
tool,
|
|
36
|
+
anchor: 'none',
|
|
37
|
+
startRow: 0,
|
|
38
|
+
composerAtBottom: false,
|
|
39
|
+
composerHidesDialogs: false,
|
|
40
|
+
lines: contentLines,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Locate the live region of one frame from one tool's declaration.
|
|
45
|
+
*
|
|
46
|
+
* The composer wins over the dialog top: a tool that draws its input box is,
|
|
47
|
+
* by every measurement in the design doc §7, not showing a dialog above it.
|
|
48
|
+
*/
|
|
49
|
+
function locateLiveRegion(spec, tool, rows) {
|
|
50
|
+
const { contentLines } = rows;
|
|
51
|
+
if (spec === undefined)
|
|
52
|
+
return wholeFrameRegion(tool, contentLines);
|
|
53
|
+
const composer = spec.composer.locate(rows);
|
|
54
|
+
if (composer !== null) {
|
|
55
|
+
return {
|
|
56
|
+
tool,
|
|
57
|
+
anchor: 'composer',
|
|
58
|
+
startRow: composer.start,
|
|
59
|
+
composerEndRow: composer.end ?? composer.start,
|
|
60
|
+
composerAtBottom: composer.atBottom ?? true,
|
|
61
|
+
composerHidesDialogs: spec.composerHidesDialogs,
|
|
62
|
+
lines: contentLines.slice(composer.start),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const dialog = spec.dialogTop?.locate(rows) ?? null;
|
|
66
|
+
if (dialog !== null) {
|
|
67
|
+
return {
|
|
68
|
+
tool,
|
|
69
|
+
anchor: 'dialog',
|
|
70
|
+
startRow: dialog.start,
|
|
71
|
+
composerAtBottom: false,
|
|
72
|
+
composerHidesDialogs: spec.composerHidesDialogs,
|
|
73
|
+
lines: contentLines.slice(dialog.start),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return wholeFrameRegion(tool, contentLines);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Is the numbered list the generic parser read a quotation? (Issue #3183)
|
|
80
|
+
*
|
|
81
|
+
* True when it is a `multiple_choice` reading on a frame whose input box is the
|
|
82
|
+
* bottom of the pane, for a tool whose every answerable screen replaces the
|
|
83
|
+
* input box ({@link LiveRegion.composerHidesDialogs}): the list then sits in
|
|
84
|
+
* the conversation above it — an agent's reply quoting a dialog, or a dialog
|
|
85
|
+
* left in the scrollback.
|
|
86
|
+
*
|
|
87
|
+
* For copilot and the opencode family a composer at the bottom does not prove
|
|
88
|
+
* that much (their pickers are drawn over it), and their numbered candidates
|
|
89
|
+
* stay with their own dialog rules — the Auto-Yes gate, which both enforce, and
|
|
90
|
+
* opencode-v2's `requireVouchedPrompt`.
|
|
91
|
+
*
|
|
92
|
+
* The one rule both the status chain (`run-detection.ts`) and the Auto-Yes
|
|
93
|
+
* path (`response-checker.ts`'s `detectPromptOnCleanFrame`) apply.
|
|
94
|
+
*/
|
|
95
|
+
function isQuotedNumberedPrompt(region, prompt) {
|
|
96
|
+
return (prompt.isPrompt &&
|
|
97
|
+
prompt.promptData?.type === 'multiple_choice' &&
|
|
98
|
+
region.composerAtBottom &&
|
|
99
|
+
region.composerHidesDialogs);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Should a tool's own dialog reading be discarded because the input box is the
|
|
103
|
+
* bottom of the pane? (Issue #3183)
|
|
104
|
+
*
|
|
105
|
+
* Numbered dialogs always are: every tool measured removes its input box while
|
|
106
|
+
* one is up (design doc §7). Arrow-key surfaces are only for tools whose every
|
|
107
|
+
* screen replaces the input box ({@link LiveRegion.composerHidesDialogs}):
|
|
108
|
+
* copilot and opencode draw their pickers OVER a live composer, so there a
|
|
109
|
+
* composer at the bottom says nothing about a `keys` overlay.
|
|
110
|
+
*/
|
|
111
|
+
function vetoesDialog(region, verdict) {
|
|
112
|
+
if (verdict === null || !region.composerAtBottom)
|
|
113
|
+
return false;
|
|
114
|
+
return verdict.answerMode === 'numbered' || region.composerHidesDialogs;
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Shared parts the per-tool declarations are built from.
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
/**
|
|
120
|
+
* A composer fenced by rules and pinned to the bottom (claude, Command Code,
|
|
121
|
+
* copilot): the tool's own structural finder, which returns the index of the
|
|
122
|
+
* block's first row or -1. The block runs to the last content row (the status
|
|
123
|
+
* bar under the fence is part of it), so it is the bottom by construction.
|
|
124
|
+
*/
|
|
125
|
+
function fencedComposer(find) {
|
|
126
|
+
return {
|
|
127
|
+
locate({ contentLines }) {
|
|
128
|
+
const start = find(contentLines);
|
|
129
|
+
if (start < 0)
|
|
130
|
+
return null;
|
|
131
|
+
return { start, end: lastContentRow(contentLines), atBottom: true };
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The bottom-most row `isComposerRow` accepts (agy's bare `>`, codex's `›`).
|
|
137
|
+
* `atBottom` decides whether the rows below it still hold something live.
|
|
138
|
+
*/
|
|
139
|
+
function bottomMostComposerRow(options) {
|
|
140
|
+
return {
|
|
141
|
+
locate(rows) {
|
|
142
|
+
const { contentLines } = rows;
|
|
143
|
+
for (let i = contentLines.length - 1; i >= 0; i--) {
|
|
144
|
+
if (options.isComposerRow(contentLines[i])) {
|
|
145
|
+
return { start: i, end: i, atBottom: options.atBottom(rows, i) };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/** A dialog top found by a tool's own function over `contentLines` (-1 when absent). */
|
|
153
|
+
function dialogTopFrom(find) {
|
|
154
|
+
return {
|
|
155
|
+
locate({ contentLines }) {
|
|
156
|
+
const start = find(contentLines);
|
|
157
|
+
return start < 0 ? null : { start };
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/** A numbered option row, cursor glyph optional (`❯ 1. Yes`, ` 2. No`, `› 3. …`). */
|
|
162
|
+
const OPTION_ONE_ROW_PATTERN = /^\s*(?:[❯›>●]\s*)?1[.)]\s+\S/;
|
|
163
|
+
/**
|
|
164
|
+
* The top of a dialog drawn as: rule, title, …, `1.` option, …, footer
|
|
165
|
+
* (claude, Command Code). From the bottom-most footer, up to the first option,
|
|
166
|
+
* up to the nearest rule. Searching from the OPTION rather than the footer is
|
|
167
|
+
* what keeps an AskUserQuestion picker's second, inner rule (between its
|
|
168
|
+
* options and its footer) from being taken for the top.
|
|
169
|
+
*/
|
|
170
|
+
function ruleAboveOptionRun(options) {
|
|
171
|
+
return dialogTopFrom(lines => {
|
|
172
|
+
let footer = -1;
|
|
173
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
174
|
+
if (options.footer(lines[i])) {
|
|
175
|
+
footer = i;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (footer < 0)
|
|
180
|
+
return -1;
|
|
181
|
+
const floor = Math.max(0, footer - options.maxRows);
|
|
182
|
+
let optionOne = -1;
|
|
183
|
+
for (let i = footer - 1; i >= floor; i--) {
|
|
184
|
+
if (OPTION_ONE_ROW_PATTERN.test(lines[i])) {
|
|
185
|
+
optionOne = i;
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (optionOne < 0)
|
|
190
|
+
return -1;
|
|
191
|
+
for (let i = optionOne - 1; i >= floor; i--) {
|
|
192
|
+
if (options.rule.test(lines[i].trimEnd()))
|
|
193
|
+
return i;
|
|
194
|
+
}
|
|
195
|
+
return -1;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/** The last non-blank row's index, or -1. */
|
|
199
|
+
function lastContentRow(lines) {
|
|
200
|
+
let i = lines.length - 1;
|
|
201
|
+
while (i >= 0 && lines[i].trim() === '')
|
|
202
|
+
i--;
|
|
203
|
+
return i;
|
|
204
|
+
}
|
|
@@ -15,6 +15,7 @@ const status_reason_1 = require("../../status-reason");
|
|
|
15
15
|
const opencode_modal_overlay_1 = require("../../opencode-modal-overlay");
|
|
16
16
|
const prompt_1 = require("./prompt");
|
|
17
17
|
const frame_1 = require("../frame");
|
|
18
|
+
const live_region_1 = require("./live-region");
|
|
18
19
|
const run_detection_1 = require("../run-detection");
|
|
19
20
|
const verified_against_1 = require("../verified-against");
|
|
20
21
|
const thinking_constants_1 = require("../../../../config/thinking-constants");
|
|
@@ -81,6 +82,8 @@ function readIdleEvidence(frame) {
|
|
|
81
82
|
exports.opencodeStatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
82
83
|
tool: 'opencode',
|
|
83
84
|
verifiedAgainst: exports.VERIFIED_AGAINST,
|
|
85
|
+
// Issue #3183: where the live part of the frame begins (`./live-region.ts`).
|
|
86
|
+
liveRegion: live_region_1.OPENCODE_LIVE_REGION,
|
|
84
87
|
afterThinking(frame) {
|
|
85
88
|
// 2.5. OpenCode status detection (Issue #379)
|
|
86
89
|
// OpenCode TUI layout: content area (top) | empty padding (~150 lines) | footer status bar (~6 lines at bottom).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* opencode (v1)'s live region (Issue #3183; design doc §7 "opencode").
|
|
4
|
+
*
|
|
5
|
+
* - **composer** — the gutter block above `╹▀▀…` and the `ctrl+p` footer.
|
|
6
|
+
* Measured: `opencode-agent-health-3021/quoted-dialog-reply-done.txt`
|
|
7
|
+
* L192-L199 (1.18.33).
|
|
8
|
+
* - **dialog top** — the `┃ △ Permission required` row. Measured:
|
|
9
|
+
* `opencode-live-1893/permission-bash.txt` L192 / L198 (1.18.21).
|
|
10
|
+
*
|
|
11
|
+
* `composerHidesDialogs: false`: opencode draws its pickers and the command
|
|
12
|
+
* palette over a live composer, so a composer at the bottom vetoes only the
|
|
13
|
+
* numbered readings.
|
|
14
|
+
*
|
|
15
|
+
* @module lib/detection/tools/opencode/live-region
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.OPENCODE_LIVE_REGION = void 0;
|
|
19
|
+
const opencode_gutter_live_region_1 = require("../opencode-gutter-live-region");
|
|
20
|
+
exports.OPENCODE_LIVE_REGION = {
|
|
21
|
+
composer: opencode_gutter_live_region_1.OPENCODE_GUTTER_COMPOSER,
|
|
22
|
+
dialogTop: (0, opencode_gutter_live_region_1.opencodeGutterDialogTop)(/△ Permission required/),
|
|
23
|
+
composerHidesDialogs: false,
|
|
24
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The live-region parts the two opencode generations share (Issue #3183;
|
|
4
|
+
* design doc §7 "opencode" / "opencode-v2").
|
|
5
|
+
*
|
|
6
|
+
* Both draw the composer as a run of `┃` gutter rows ending in the model bar,
|
|
7
|
+
* then a `╹▀▀…` rule, then a footer carrying `ctrl+p` (or v1's `ctrl+t`). Both
|
|
8
|
+
* REMOVE that footer and rule while an approval strip or a question form is up
|
|
9
|
+
* (`opencode-live-1893/permission-bash.txt`, `opencode-v2-dialogs-2984/
|
|
10
|
+
* permission.txt` / `question.txt` end on a `┃` row), so finding them is
|
|
11
|
+
* finding the composer.
|
|
12
|
+
*
|
|
13
|
+
* The user's own turns are drawn on the same gutter
|
|
14
|
+
* (`opencode-agent-health-3021/quoted-dialog-reply-done.txt` L17-L24 holds a
|
|
15
|
+
* quoted `Allow once Allow always Reject` strip inside one), which is why the
|
|
16
|
+
* composer is the gutter run directly above the rule and nothing higher.
|
|
17
|
+
*
|
|
18
|
+
* @module lib/detection/tools/opencode-gutter-live-region
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.OPENCODE_GUTTER_COMPOSER = void 0;
|
|
22
|
+
exports.opencodeGutterDialogTop = opencodeGutterDialogTop;
|
|
23
|
+
const live_region_1 = require("./live-region");
|
|
24
|
+
/** How far above the last row the keybinding footer may sit (v1 1.18.33 wraps it over 3 rows). */
|
|
25
|
+
const FOOTER_MAX_ROWS = 4;
|
|
26
|
+
/** How far above the footer the `╹▀` rule may sit. */
|
|
27
|
+
const RULE_MAX_ROWS = 3;
|
|
28
|
+
/** How far above the bottom a dialog's title may sit. */
|
|
29
|
+
const DIALOG_MAX_ROWS = 60;
|
|
30
|
+
const FOOTER_PATTERN = /ctrl\+[tp]\b/;
|
|
31
|
+
const RULE_PATTERN = /^\s*╹▀+/;
|
|
32
|
+
const GUTTER_PATTERN = /^\s*[┃│]/;
|
|
33
|
+
exports.OPENCODE_GUTTER_COMPOSER = {
|
|
34
|
+
locate({ contentLines }) {
|
|
35
|
+
const last = (0, live_region_1.lastContentRow)(contentLines);
|
|
36
|
+
let footer = -1;
|
|
37
|
+
for (let i = last; i >= Math.max(0, last - FOOTER_MAX_ROWS); i--) {
|
|
38
|
+
if (FOOTER_PATTERN.test(contentLines[i])) {
|
|
39
|
+
footer = i;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (footer < 0)
|
|
44
|
+
return null;
|
|
45
|
+
let rule = -1;
|
|
46
|
+
for (let i = footer - 1; i >= Math.max(0, footer - RULE_MAX_ROWS); i--) {
|
|
47
|
+
if (RULE_PATTERN.test(contentLines[i])) {
|
|
48
|
+
rule = i;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (rule < 0)
|
|
53
|
+
return null;
|
|
54
|
+
let start = rule;
|
|
55
|
+
while (start - 1 >= 0 && GUTTER_PATTERN.test(contentLines[start - 1]))
|
|
56
|
+
start--;
|
|
57
|
+
return { start, end: last, atBottom: true };
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
/** The bottom-most gutter row `title` matches, within the last rows of the pane. */
|
|
61
|
+
function opencodeGutterDialogTop(title) {
|
|
62
|
+
return {
|
|
63
|
+
locate({ contentLines }) {
|
|
64
|
+
const last = (0, live_region_1.lastContentRow)(contentLines);
|
|
65
|
+
for (let i = last; i >= Math.max(0, last - DIALOG_MAX_ROWS); i--) {
|
|
66
|
+
if (GUTTER_PATTERN.test(contentLines[i]) && title.test(contentLines[i]))
|
|
67
|
+
return { start: i };
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -48,6 +48,7 @@ exports.opencodeV2StatusDetector = exports.OPENCODE_V2_PERMISSION_OPTIONS = expo
|
|
|
48
48
|
exports.endsWithTurnComplete = endsWithTurnComplete;
|
|
49
49
|
const cli_patterns_1 = require("../../cli-patterns");
|
|
50
50
|
const status_reason_1 = require("../../status-reason");
|
|
51
|
+
const live_region_1 = require("./live-region");
|
|
51
52
|
const run_detection_1 = require("../run-detection");
|
|
52
53
|
const verified_against_1 = require("../verified-against");
|
|
53
54
|
exports.VERIFIED_AGAINST = verified_against_1.OPENCODE_V2_VERIFIED_AGAINST;
|
|
@@ -141,6 +142,8 @@ function endsWithTurnComplete(frame) {
|
|
|
141
142
|
exports.opencodeV2StatusDetector = (0, run_detection_1.createToolStatusDetector)({
|
|
142
143
|
tool: 'opencode-v2',
|
|
143
144
|
verifiedAgainst: exports.VERIFIED_AGAINST,
|
|
145
|
+
// Issue #3183: where the live part of the frame begins (`./live-region.ts`).
|
|
146
|
+
liveRegion: live_region_1.OPENCODE_V2_LIVE_REGION,
|
|
144
147
|
// Issue #2991: every v2 dialog is recognised by `beforePrompt` below, so a
|
|
145
148
|
// numbered list that reaches the generic parser is text in a reply (the UAT
|
|
146
149
|
// frame: `❯ 1. Yes / 2. No` quoted in the answer). Unvouched by
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* opencode-v2's live region (Issue #3183; design doc §7 "opencode-v2").
|
|
4
|
+
*
|
|
5
|
+
* - **composer** — the gutter block above `╹▀▀…` and the `ctrl+p commands`
|
|
6
|
+
* footer. Measured: `opencode-v2-dialogs-2984/quoted-dialog-reply.txt`
|
|
7
|
+
* L194-L199 (2.0.18), under the quotation at L27-L29.
|
|
8
|
+
* - **dialog top** — the `┃ △ Permission required` row or the question form's
|
|
9
|
+
* `┃ Questions` row. Measured: `opencode-v2-dialogs-2984/permission.txt`
|
|
10
|
+
* L186, `question.txt` L190.
|
|
11
|
+
*
|
|
12
|
+
* `composerHidesDialogs: false`, as for v1: v2's dialog-title overlays
|
|
13
|
+
* (`commands.txt`) are drawn over a live composer.
|
|
14
|
+
*
|
|
15
|
+
* @module lib/detection/tools/opencode-v2/live-region
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.OPENCODE_V2_LIVE_REGION = void 0;
|
|
19
|
+
const opencode_gutter_live_region_1 = require("../opencode-gutter-live-region");
|
|
20
|
+
exports.OPENCODE_V2_LIVE_REGION = {
|
|
21
|
+
composer: opencode_gutter_live_region_1.OPENCODE_GUTTER_COMPOSER,
|
|
22
|
+
dialogTop: (0, opencode_gutter_live_region_1.opencodeGutterDialogTop)(/△ Permission required|┃\s*Questions\s*$/),
|
|
23
|
+
composerHidesDialogs: false,
|
|
24
|
+
};
|
|
@@ -32,6 +32,8 @@ exports.runToolDetection = runToolDetection;
|
|
|
32
32
|
exports.createToolStatusDetector = createToolStatusDetector;
|
|
33
33
|
const cli_patterns_1 = require("../cli-patterns");
|
|
34
34
|
const prompt_detector_1 = require("../prompt-detector");
|
|
35
|
+
const frame_1 = require("./frame");
|
|
36
|
+
const live_region_1 = require("./live-region");
|
|
35
37
|
const status_reason_1 = require("../status-reason");
|
|
36
38
|
const detection_evidence_config_1 = require("../../../config/detection-evidence-config");
|
|
37
39
|
const idle_evidence_observation_1 = require("../idle-evidence-observation");
|
|
@@ -77,7 +79,10 @@ function resolveIdleEvidence(spec, frame) {
|
|
|
77
79
|
return mode === 'observe' ? 'positive' : evidence;
|
|
78
80
|
}
|
|
79
81
|
/** Run the whole chain for one tool over one frame. */
|
|
80
|
-
function runToolDetection(spec,
|
|
82
|
+
function runToolDetection(spec, input, context = {}) {
|
|
83
|
+
// Issue #3183: every branch below reads the tool's own live region, whoever
|
|
84
|
+
// built the frame.
|
|
85
|
+
const frame = (0, frame_1.withLiveRegion)(input, spec.tool);
|
|
81
86
|
// 0.x — the tool's own pre-prompt branches. A picker, a pager or a status bar
|
|
82
87
|
// whose body the generic parser would misread as a numbered dialog.
|
|
83
88
|
const early = spec.beforePrompt?.(frame) ?? null;
|
|
@@ -93,7 +98,14 @@ function runToolDetection(spec, frame, context = {}) {
|
|
|
93
98
|
: (0, cli_patterns_1.stripBoxDrawing)(frame.lastLines);
|
|
94
99
|
let promptDetection = (0, prompt_detector_1.detectPrompt)(promptInput, promptOptions);
|
|
95
100
|
if (promptDetection.isPrompt) {
|
|
96
|
-
if (
|
|
101
|
+
if ((0, live_region_1.isQuotedNumberedPrompt)(frame.liveRegion, promptDetection)) {
|
|
102
|
+
// Issue #3183: the input box is the bottom of the pane, so the numbered
|
|
103
|
+
// list sits in the conversation above it — a reply quoting a dialog
|
|
104
|
+
// (#2845 / #2991) or a dialog left in the scrollback. The same rule the
|
|
105
|
+
// Auto-Yes path applies (`detectPromptOnCleanFrame`), on the same region.
|
|
106
|
+
promptDetection = { ...promptDetection, isPrompt: false, promptData: undefined };
|
|
107
|
+
}
|
|
108
|
+
else if (spec.isStalePrompt?.(frame, promptDetection)) {
|
|
97
109
|
// Issue #1160: an ALREADY-ANSWERED block still inside the scan window.
|
|
98
110
|
// Neutralise it so Auto-Yes and the sidebar never act on a dead prompt,
|
|
99
111
|
// and let the chain continue to the tool's running/idle branches.
|
|
@@ -205,7 +217,17 @@ function createToolStatusDetector(spec) {
|
|
|
205
217
|
// caller which of the two it got, because the Auto-Yes gate must suppress
|
|
206
218
|
// for "this tool has rules and this frame is not a dialog" and must NOT
|
|
207
219
|
// suppress for "nobody has measured this tool yet".
|
|
208
|
-
|
|
220
|
+
//
|
|
221
|
+
// Issue #3183: wrapped so every tool's reading gets the live-region veto in
|
|
222
|
+
// one place — a dialog on a frame whose input box is the bottom of the pane
|
|
223
|
+
// is a quotation, whatever the tool's own rule matched.
|
|
224
|
+
detectDialog: spec.detectDialog
|
|
225
|
+
? (input) => {
|
|
226
|
+
const frame = (0, frame_1.withLiveRegion)(input, spec.tool);
|
|
227
|
+
const verdict = spec.detectDialog(frame);
|
|
228
|
+
return (0, live_region_1.vetoesDialog)(frame.liveRegion, verdict) ? null : verdict;
|
|
229
|
+
}
|
|
230
|
+
: () => null,
|
|
209
231
|
hasDialogRules: spec.detectDialog !== undefined,
|
|
210
232
|
};
|
|
211
233
|
}
|
|
@@ -61,6 +61,7 @@ exports.evaluateDialogPresence = evaluateDialogPresence;
|
|
|
61
61
|
exports.judgePromptResponse = judgePromptResponse;
|
|
62
62
|
exports.assessPromptAnswerability = assessPromptAnswerability;
|
|
63
63
|
const frame_1 = require("../../lib/detection/tools/frame");
|
|
64
|
+
const live_region_1 = require("../../lib/detection/tools/live-region");
|
|
64
65
|
const registry_1 = require("../../lib/detection/tools/registry");
|
|
65
66
|
const prompt_detector_1 = require("../../lib/detection/prompt-detector");
|
|
66
67
|
const cli_patterns_1 = require("../../lib/detection/cli-patterns");
|
|
@@ -203,7 +204,9 @@ const GATED_PROMPT_TYPE = 'multiple_choice';
|
|
|
203
204
|
* `captureAndCleanOutput` produced: ANSI **and** box drawing already removed.
|
|
204
205
|
* Every `detectDialog` implementation is written against that spelling as well
|
|
205
206
|
* as the untouched one, so the same frame reaches the same verdict on both
|
|
206
|
-
* paths.
|
|
207
|
+
* paths. Or (Issue #3183) the `NormalizedFrame` the poller built ONCE from
|
|
208
|
+
* the raw capture for this tick — the same object its prompt reading used, so
|
|
209
|
+
* both read one live region; that is what the poller passes.
|
|
207
210
|
* @param env - Environment to read the kill switch from; injectable for tests
|
|
208
211
|
*/
|
|
209
212
|
function evaluateAutoYesDialogGate(cliToolId, promptType, cleanOutput, env = process.env) {
|
|
@@ -237,7 +240,9 @@ function judgeDialogPresence(cliToolId, promptType, frame, mode) {
|
|
|
237
240
|
if (promptType !== GATED_PROMPT_TYPE || !detector.hasDialogRules || mode === 'legacy') {
|
|
238
241
|
return { present: true, dialog: null, mode, gated: false };
|
|
239
242
|
}
|
|
240
|
-
|
|
243
|
+
// Issue #3183: normalised for the tool, so the detector reads the tool's live
|
|
244
|
+
// region (and its veto) — never a whole-frame default.
|
|
245
|
+
const dialog = detector.detectDialog(typeof frame === 'string' ? (0, frame_1.normalizeFrame)(frame, cliToolId) : frame);
|
|
241
246
|
return { present: dialog !== null, dialog, mode, gated: true };
|
|
242
247
|
}
|
|
243
248
|
/**
|
|
@@ -388,10 +393,17 @@ function assessPromptAnswerability(cliToolId, frame) {
|
|
|
388
393
|
};
|
|
389
394
|
}
|
|
390
395
|
const isCommandCodeQuestion = commandCodeQuestion.kind === 'prompt';
|
|
391
|
-
const
|
|
396
|
+
const candidate = (commandCodeQuestion.kind === 'prompt' ? commandCodeQuestion.prompt : null)
|
|
392
397
|
?? toolDialog
|
|
393
398
|
?? (0, prompt_detector_1.detectPrompt)(cleanOutput, (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId));
|
|
394
|
-
|
|
399
|
+
// Issue #3183: one frame, normalised once from the capture, for the
|
|
400
|
+
// quotation veto and the presence gate alike — the reading the status chain
|
|
401
|
+
// and the Auto-Yes poller apply, so Send is offered exactly when they agree.
|
|
402
|
+
const normalized = (0, frame_1.normalizeFrame)(frame, cliToolId);
|
|
403
|
+
const promptCheck = (0, live_region_1.isQuotedNumberedPrompt)(normalized.liveRegion, candidate)
|
|
404
|
+
? { isPrompt: false, cleanContent: cleanOutput }
|
|
405
|
+
: candidate;
|
|
406
|
+
const presence = evaluateDialogPresence(cliToolId, promptCheck.promptData?.type, normalized);
|
|
395
407
|
return {
|
|
396
408
|
promptCheck,
|
|
397
409
|
isCommandCodeQuestion,
|
|
@@ -18,8 +18,8 @@ const db_1 = require("../../lib/db");
|
|
|
18
18
|
const ws_server_1 = require("../../lib/ws-server");
|
|
19
19
|
const prompt_detector_1 = require("../../lib/detection/prompt-detector");
|
|
20
20
|
const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
|
|
21
|
-
const detect_1 = require("../../lib/detection/tools/antigravity/detect");
|
|
22
21
|
const frame_1 = require("../../lib/detection/tools/frame");
|
|
22
|
+
const live_region_1 = require("../../lib/detection/tools/live-region");
|
|
23
23
|
const dialog_2 = require("../../lib/detection/tools/command-code/dialog");
|
|
24
24
|
const conversation_logger_1 = require("../../lib/conversation-logger");
|
|
25
25
|
const types_1 = require("../../lib/cli-tools/types");
|
|
@@ -234,9 +234,14 @@ function buildPromptExtractionResult(lines, lastCapturedLine, totalLines, buffer
|
|
|
234
234
|
* then handed back as no prompt unless agy asked CommandMate about a tool call
|
|
235
235
|
* for that instance a moment ago. Omitted, the reading is not gated — which is
|
|
236
236
|
* what every caller that only DISPLAYS the frame wants.
|
|
237
|
+
* @param frame - the SAME tick's `normalizeFrame(raw, cliToolId)`, when the
|
|
238
|
+
* caller built one (Issue #3183). The Auto-Yes poller builds it once and hands
|
|
239
|
+
* the same object to the dialog gate, so the quotation veto below and the gate
|
|
240
|
+
* read one live region. Omitted, it is built here from `rawFrame` (or, failing
|
|
241
|
+
* that, `cleanOutput`).
|
|
237
242
|
* @returns PromptDetectionResult with isPrompt, promptData, and cleanContent
|
|
238
243
|
*/
|
|
239
|
-
function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawFrame, receiptScope) {
|
|
244
|
+
function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawFrame, receiptScope, frame) {
|
|
240
245
|
// Issue #2364: agy's `↑/↓ Navigate` dialogs are read by agy's own reader
|
|
241
246
|
// before the generic pass, on the same spelling `tools/antigravity/detect.ts`
|
|
242
247
|
// reads them on. The generic multiple-choice parser takes one row per option
|
|
@@ -287,25 +292,25 @@ function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawF
|
|
|
287
292
|
}
|
|
288
293
|
const promptOptions = (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId);
|
|
289
294
|
const result = (0, prompt_detector_1.detectPrompt)(cleanOutput, precomputedLines ? { ...promptOptions, precomputedLines } : promptOptions);
|
|
290
|
-
// Issue #
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
// row makes the list a quotation.
|
|
295
|
+
// Issue #3183 (agy-only before, #2851): a numbered list on a frame whose
|
|
296
|
+
// input box is the bottom of the pane is a quotation — a reply quoting a
|
|
297
|
+
// dialog, or one left in the scrollback — and is not a prompt to answer. The
|
|
298
|
+
// status side declines the same candidate with the same rule on the same
|
|
299
|
+
// region (`run-detection.ts`), so `waiting` and an automatic answer cannot
|
|
300
|
+
// disagree about one frame. Every tool, not only agy: #2851 reached Auto-Yes
|
|
301
|
+
// because agy's `>` is not one of the glyphs the generic parser stops at, and
|
|
302
|
+
// opencode's gutter is not either.
|
|
299
303
|
//
|
|
300
|
-
// `rawFrame` when
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
304
|
+
// `rawFrame` when there is no prebuilt frame: the input-box markers are rule
|
|
305
|
+
// rows that the cleaned spelling has blanked. `stripBoxDrawing` is not
|
|
306
|
+
// idempotent, so the cleaned string is never cleaned again here.
|
|
307
|
+
if (result.isPrompt) {
|
|
308
|
+
const liveRegion = frame !== undefined
|
|
309
|
+
? (0, frame_1.liveRegionOf)(frame, cliToolId)
|
|
310
|
+
: (0, frame_1.normalizeFrame)(rawFrame ?? cleanOutput, cliToolId).liveRegion;
|
|
311
|
+
if ((0, live_region_1.isQuotedNumberedPrompt)(liveRegion, result)) {
|
|
312
|
+
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
313
|
+
}
|
|
309
314
|
}
|
|
310
315
|
// Issue #2849: the same withholding on this exit. agy's reader answering `null`
|
|
311
316
|
// does not mean the frame is no dialog — the generic pass above reads shapes
|
|
@@ -294,7 +294,7 @@ async function assertAnswerModeAcceptsNumber(params) {
|
|
|
294
294
|
const frame = await readGuardFrame(params);
|
|
295
295
|
if (frame === null)
|
|
296
296
|
return null;
|
|
297
|
-
const dialog = detector.detectDialog((0, frame_1.normalizeFrame)(frame));
|
|
297
|
+
const dialog = detector.detectDialog((0, frame_1.normalizeFrame)(frame, params.cliToolId));
|
|
298
298
|
if (dialog === null)
|
|
299
299
|
return null;
|
|
300
300
|
if (dialog.answerMode === TEXT_ANSWERABLE_ANSWER_MODE)
|
|
@@ -110,6 +110,9 @@ function emitTerminalSnapshot(worktreeId, cliToolId, payload, instanceId) {
|
|
|
110
110
|
// `JSON.stringify` (in `broadcast`) already drops from the wire on its own.
|
|
111
111
|
// Defaulting it would turn "not judged" into a judgement.
|
|
112
112
|
promptAnswerable: payload.promptAnswerable,
|
|
113
|
+
// Issue #3184: derived from `promptData` by the builder; `?? null` like
|
|
114
|
+
// `promptData` itself, since both say "no prompt" the same way.
|
|
115
|
+
promptView: payload.promptView ?? null,
|
|
113
116
|
isSelectionListActive: payload.isSelectionListActive ?? false,
|
|
114
117
|
isPagerActive: payload.isPagerActive ?? false,
|
|
115
118
|
isDismissablePanelActive: payload.isDismissablePanelActive ?? false,
|
|
@@ -222,6 +222,8 @@ function findWorkerReply(db, worker, since) {
|
|
|
222
222
|
/** The options of B's open dialog, in the shape the notice lists them. */
|
|
223
223
|
function promptOptionsOf(message) {
|
|
224
224
|
const data = message.promptData;
|
|
225
|
+
// #3184: type narrowing only — the stored row's screen `options` are listed;
|
|
226
|
+
// a stored degraded record never carries a decision id, so it has none.
|
|
225
227
|
if (!(0, models_1.isAnswerablePromptData)(data))
|
|
226
228
|
return [];
|
|
227
229
|
if (data.type === 'yes_no') {
|
|
@@ -383,6 +385,7 @@ function notifyRelayPromptWaiting(worker) {
|
|
|
383
385
|
return;
|
|
384
386
|
const locale = (0, model_change_push_notifier_1.resolveReadersLocale)(db);
|
|
385
387
|
const options = promptOptionsOf(prompt);
|
|
388
|
+
// #3184: type narrowing only, to read `question` off the closed union.
|
|
386
389
|
const question = (0, models_1.isAnswerablePromptData)(prompt.promptData)
|
|
387
390
|
? prompt.promptData.question
|
|
388
391
|
: (prompt.promptData?.question ?? prompt.content);
|
|
@@ -75,6 +75,8 @@ exports.areRelayTriggersActive = areRelayTriggersActive;
|
|
|
75
75
|
const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
|
|
76
76
|
const relay_policy_1 = require("../../lib/relay/relay-policy");
|
|
77
77
|
const logger_1 = require("../../lib/logger");
|
|
78
|
+
const prompt_waiting_composition_1 = require("../../lib/session/prompt-waiting-composition");
|
|
79
|
+
const registry_1 = require("../../lib/hooks/sources/registry");
|
|
78
80
|
const logger = (0, logger_1.createLogger)('relay-triggers');
|
|
79
81
|
/**
|
|
80
82
|
* Tell the relays that this instance finished a turn.
|
|
@@ -151,6 +153,13 @@ function startRelayTriggers() {
|
|
|
151
153
|
// another session as a question it might report to a human.
|
|
152
154
|
if (!transition.waiting || transition.kind !== 'prompt')
|
|
153
155
|
return;
|
|
156
|
+
// Issue #3184 (design §6-2): a wait answered over the agent's API is
|
|
157
|
+
// published as `prompt` for the dots and the push body, but the relay is
|
|
158
|
+
// not raised for it — its notice lists the stored row's screen options,
|
|
159
|
+
// and such a wait has none to list. Relaying it is a separate Issue.
|
|
160
|
+
if ((0, prompt_waiting_composition_1.isApiAnswerableWaitNow)(transition.worktreeId, transition.cliToolId, transition.instanceId, (0, registry_1.getAgentEventSource)(transition.cliToolId).capabilities.eventIdentity)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
154
163
|
onRelayPromptWaiting(transition.worktreeId, transition.cliToolId, transition.instanceId);
|
|
155
164
|
});
|
|
156
165
|
const timer = setInterval(() => void runRelayMaintenance(), relay_policy_1.RELAY_PUMP_INTERVAL_MS);
|
|
@@ -22,6 +22,7 @@ exports.stopResourceCleanup = stopResourceCleanup;
|
|
|
22
22
|
const child_process_1 = require("child_process");
|
|
23
23
|
const fs_1 = require("fs");
|
|
24
24
|
const auto_yes_manager_1 = require("./polling/auto-yes-manager");
|
|
25
|
+
const auto_yes_lifecycle_1 = require("./auto-yes-lifecycle");
|
|
25
26
|
const path_validator_1 = require("./security/path-validator");
|
|
26
27
|
const schedule_manager_1 = require("./schedule-manager");
|
|
27
28
|
const timer_manager_1 = require("./timer-manager");
|
|
@@ -174,18 +175,19 @@ function cleanupOrphanedMapEntries() {
|
|
|
174
175
|
// If DB query returned nothing, skip cleanup to avoid false positives
|
|
175
176
|
return result;
|
|
176
177
|
}
|
|
177
|
-
// Cleanup autoYesStates (Issue #525: composite keys)
|
|
178
|
+
// Cleanup autoYesStates (Issue #525: composite keys). Issue #3184: through the
|
|
179
|
+
// `orphan-swept` row of the Auto-Yes lifecycle table.
|
|
178
180
|
const autoYesStateKeys = (0, auto_yes_manager_1.getAutoYesStateCompositeKeys)();
|
|
179
181
|
for (const compositeKey of autoYesStateKeys) {
|
|
180
182
|
const worktreeId = (0, auto_yes_manager_1.extractWorktreeId)(compositeKey);
|
|
181
183
|
// [SEC4-MF-001] Validate extracted worktreeId
|
|
182
184
|
if (!(0, path_validator_1.isValidWorktreeId)(worktreeId)) {
|
|
183
|
-
(0,
|
|
185
|
+
(0, auto_yes_lifecycle_1.applyAutoYesStateRule)('orphan-swept', { scope: 'key', compositeKey });
|
|
184
186
|
result.deletedAutoYesStateIds.push(compositeKey);
|
|
185
187
|
continue;
|
|
186
188
|
}
|
|
187
189
|
if (!validWorktreeIds.has(worktreeId)) {
|
|
188
|
-
(0,
|
|
190
|
+
(0, auto_yes_lifecycle_1.applyAutoYesStateRule)('orphan-swept', { scope: 'key', compositeKey });
|
|
189
191
|
result.deletedAutoYesStateIds.push(compositeKey);
|
|
190
192
|
}
|
|
191
193
|
}
|
|
@@ -194,7 +196,7 @@ function cleanupOrphanedMapEntries() {
|
|
|
194
196
|
for (const compositeKey of autoYesPollerKeys) {
|
|
195
197
|
const worktreeId = (0, auto_yes_manager_1.extractWorktreeId)(compositeKey);
|
|
196
198
|
if (!(0, path_validator_1.isValidWorktreeId)(worktreeId) || !validWorktreeIds.has(worktreeId)) {
|
|
197
|
-
(0,
|
|
199
|
+
(0, auto_yes_lifecycle_1.stopAutoYesPollersFor)('orphan-swept', { scope: 'key', compositeKey });
|
|
198
200
|
result.deletedAutoYesPollerIds.push(compositeKey);
|
|
199
201
|
}
|
|
200
202
|
}
|