commandmate 0.47.2 → 0.49.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 +180 -180
- package/.next/app-path-routes-manifest.json +30 -30
- 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/release-notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route.js +3 -3
- 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.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.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 -1
- 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 -1
- 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]/prompt-response/strict/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/strict/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/strict/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
- 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.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.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 +1 -1
- 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_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.js +2 -2
- package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +12 -12
- 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 +30 -30
- package/.next/server/chunks/1191.js +11 -4
- package/.next/server/chunks/1501.js +1 -1
- package/.next/server/chunks/1601.js +2 -2
- package/.next/server/chunks/1656.js +2 -2
- package/.next/server/chunks/1945.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2069.js +1 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2422.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2534.js +1 -1
- package/.next/server/chunks/255.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3505.js +2 -2
- package/.next/server/chunks/4243.js +1 -1
- package/.next/server/chunks/4248.js +1 -1
- package/.next/server/chunks/4280.js +1 -0
- package/.next/server/chunks/5209.js +1 -1
- package/.next/server/chunks/6119.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6486.js +9 -8
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/720.js +103 -0
- package/.next/server/chunks/7604.js +2 -0
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8581.js +8 -8
- package/.next/server/chunks/8728.js +3 -3
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8807.js +19 -18
- package/.next/server/chunks/8918.js +2 -104
- package/.next/server/chunks/936.js +1 -1
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9540.js +1 -1
- package/.next/server/chunks/9627.js +5 -5
- package/.next/server/chunks/9731.js +2 -2
- 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/1128-914c559913546bbc.js +1 -0
- package/.next/static/chunks/{2407-a6533805a86d05bd.js → 2407-ab92ae9837c39dce.js} +1 -1
- package/.next/static/chunks/{2863-6a07ec82fb52f4dd.js → 2863-7173dc305dffc4f6.js} +1 -1
- package/.next/static/chunks/6288-6fadbba6e84393b2.js +1 -0
- package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +1 -0
- package/.next/static/chunks/8407-35bbfc84793d7004.js +1 -0
- package/.next/static/chunks/9079-987939d231704218.js +1 -0
- package/.next/static/chunks/app/{layout-538d8d2746ad1588.js → layout-aa8e66164a4367af.js} +1 -1
- package/.next/static/chunks/app/sessions/page-cfd645305e25fd33.js +1 -0
- package/.next/static/chunks/app/skills/[skillId]/{page-52ba58712faf3378.js → page-cb6e74fd9a6a571d.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-704086656fb45699.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-a8d7886703ffc7b4.js +1 -0
- package/.next/static/css/{743f79ff19ab91e9.css → db8959555c3d9c96.css} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/auto-yes.d.ts +24 -0
- package/dist/cli/commands/auto-yes.d.ts.map +1 -1
- package/dist/cli/commands/auto-yes.js +76 -8
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +5 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +10 -1
- package/dist/cli/commands/prompt.d.ts.map +1 -1
- package/dist/cli/commands/prompt.js +5 -3
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +19 -6
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +8 -1
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +101 -13
- package/dist/cli/config/duration-constants.d.ts +16 -13
- package/dist/cli/config/duration-constants.d.ts.map +1 -1
- package/dist/cli/config/duration-constants.js +21 -21
- package/dist/cli/docs/agent-operations.d.ts +2 -2
- package/dist/cli/docs/agent-operations.d.ts.map +1 -1
- package/dist/cli/docs/agent-operations.js +29 -1
- package/dist/cli/types/api-responses.d.ts +145 -3
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/types/index.d.ts +4 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/cli/utils/resource-resolvers.d.ts +0 -18
- package/dist/cli/utils/resource-resolvers.d.ts.map +1 -1
- package/dist/cli/utils/resource-resolvers.js +1 -51
- package/dist/cli/utils/verify-runner.d.ts +24 -1
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +54 -1
- package/dist/config/auto-yes-duration.d.ts +56 -0
- package/dist/config/auto-yes-duration.d.ts.map +1 -0
- package/dist/config/auto-yes-duration.js +76 -0
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +54 -2
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.js +33 -2
- package/dist/lib/prompt-observation/types.d.ts +13 -0
- package/dist/lib/prompt-observation/types.d.ts.map +1 -1
- package/dist/server/locales/en/worktree.json +2 -1
- package/dist/server/locales/ja/worktree.json +2 -1
- package/dist/server/src/config/auto-yes-config.js +14 -19
- package/dist/server/src/config/auto-yes-duration.js +76 -0
- package/dist/server/src/lib/auto-yes-poller-answer-target.js +38 -0
- package/dist/server/src/lib/auto-yes-poller-keys.js +35 -0
- package/dist/server/src/lib/auto-yes-poller-session-presence.js +26 -0
- package/dist/server/src/lib/auto-yes-poller-tick.js +233 -0
- package/dist/server/src/lib/auto-yes-poller.js +337 -376
- package/dist/server/src/lib/auto-yes-state.js +59 -4
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +235 -19
- package/dist/server/src/lib/db/chat-db.js +5 -1
- package/dist/server/src/lib/db/verification-db.js +23 -2
- package/dist/server/src/lib/detection/composer-text.js +215 -11
- package/dist/server/src/lib/detection/option-recommendation.js +120 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice-approval-context.js +290 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice-chrome.js +193 -0
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +402 -539
- package/dist/server/src/lib/detection/prompt-detector.js +92 -21
- package/dist/server/src/lib/detection/prompt-screen-key.js +60 -0
- package/dist/server/src/lib/detection/tools/antigravity/dialog.js +158 -35
- package/dist/server/src/lib/detection/tools/claude/detect.js +111 -10
- package/dist/server/src/lib/detection/tools/command-code/dialog.js +67 -0
- package/dist/server/src/lib/detection/tools/dialog-block.js +16 -0
- package/dist/server/src/lib/detection/upstream-faults.js +19 -2
- package/dist/server/src/lib/detection/waiting-screen-reading.js +98 -0
- package/dist/server/src/lib/hooks/permission-decision-service.js +7 -0
- package/dist/server/src/lib/hooks/structured-decision-response.js +1 -1
- package/dist/server/src/lib/polling/auto-yes-confirm-page.js +2 -2
- package/dist/server/src/lib/polling/auto-yes-confirmation-ledger-types.js +3 -0
- package/dist/server/src/lib/polling/auto-yes-confirmation-ledger.js +34 -3
- package/dist/server/src/lib/polling/auto-yes-decision-state.js +195 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +139 -10
- package/dist/server/src/lib/polling/auto-yes-enter-fallback.js +14 -0
- package/dist/server/src/lib/polling/auto-yes-manual-answer.js +124 -0
- package/dist/server/src/lib/polling/auto-yes-option-effect.js +157 -0
- package/dist/server/src/lib/polling/auto-yes-policy.js +11 -5
- package/dist/server/src/lib/polling/auto-yes-poller-capture.js +15 -2
- package/dist/server/src/lib/polling/auto-yes-poller-generation.js +42 -1
- package/dist/server/src/lib/polling/auto-yes-poller-receipt-log.js +42 -5
- package/dist/server/src/lib/polling/auto-yes-poller-state.js +147 -49
- package/dist/server/src/lib/polling/auto-yes-poller-steps.js +172 -2
- package/dist/server/src/lib/polling/auto-yes-prompt-suppression.js +2 -2
- package/dist/server/src/lib/polling/auto-yes-question-choice.js +57 -0
- package/dist/server/src/lib/polling/auto-yes-resolver.js +96 -21
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +33 -2
- package/dist/server/src/lib/polling/auto-yes-suppression-state.js +25 -1
- package/dist/server/src/lib/polling/prompt-screen-reading.js +232 -0
- package/dist/server/src/lib/polling/response-checker-dialog-gate.js +39 -0
- package/dist/server/src/lib/polling/response-checker.js +145 -58
- package/dist/server/src/lib/prompt-answer-sender.js +104 -10
- package/dist/server/src/lib/push/notification-dedup.js +15 -2
- package/dist/server/src/lib/push/prompt-card-state.js +140 -19
- package/dist/server/src/lib/push/prompt-push-gate.js +158 -12
- package/dist/server/src/lib/push/push-sender.js +23 -3
- package/dist/server/src/lib/push/resolution-push-notifier.js +14 -0
- package/dist/server/src/lib/push/waiting-push-notifier.js +139 -17
- package/dist/server/src/lib/realtime/terminal-broadcast.js +16 -0
- package/dist/server/src/lib/session/agent-event-state.js +25 -5
- package/dist/server/src/lib/session/agent-event-turn.js +140 -46
- package/dist/server/src/lib/session/cli-session.js +21 -2
- package/dist/server/src/lib/session/composer-clear.js +56 -4
- package/dist/server/src/lib/session/current-output-builder.js +66 -12
- package/dist/server/src/lib/session/send-attempt-state.js +24 -7
- package/dist/server/src/lib/session/waiting-episode-binding-observation.js +289 -0
- package/dist/server/src/lib/session/waiting-episode-binding-resolve.js +38 -0
- package/dist/server/src/lib/session/waiting-episode-binding.js +276 -0
- package/dist/server/src/lib/session/waiting-episode-state-ops.js +152 -0
- package/dist/server/src/lib/session/waiting-episode-state-store.js +202 -0
- package/dist/server/src/lib/session/waiting-episode-state-types.js +6 -0
- package/dist/server/src/lib/session/waiting-episode-state.js +68 -91
- package/dist/server/src/lib/session/waiting-episode-verdict.js +174 -0
- package/dist/server/src/lib/tmux/tmux-capture-cache.js +76 -11
- package/dist/server/src/lib/tmux/tmux.js +79 -9
- package/dist/server/src/lib/verification/gate-runner.js +172 -16
- package/dist/server/src/lib/verification/machine-lock.js +5 -0
- package/dist/server/src/lib/ws-server.js +18 -3
- package/dist/server/src/types/auto-yes-answer-mode.js +38 -0
- package/dist/server/src/types/auto-yes-decision.js +61 -0
- package/dist/server/src/types/auto-yes.js +6 -0
- package/dist/server/src/types/prompt-reading.js +32 -0
- package/dist/types/auto-yes-answer-mode.d.ts +35 -0
- package/dist/types/auto-yes-answer-mode.d.ts.map +1 -0
- package/dist/types/auto-yes-answer-mode.js +38 -0
- package/docs/en/user-guide/webapp-guide.md +47 -13
- package/package.json +1 -1
- package/public/sw.js +76 -4
- package/release-notes/0.48.0.json +57 -0
- package/release-notes/0.49.0.json +45 -0
- package/.next/server/chunks/1559.js +0 -2
- package/.next/server/chunks/2460.js +0 -1
- package/.next/server/chunks/5595.js +0 -1
- package/.next/server/chunks/610.js +0 -1
- package/.next/server/chunks/6722.js +0 -1
- package/.next/static/chunks/5371-a549a0d2c2044d41.js +0 -1
- package/.next/static/chunks/602-1c1488959215e140.js +0 -1
- package/.next/static/chunks/6288-09feba367cc2c65e.js +0 -1
- package/.next/static/chunks/8407-155f84e5ba05f1d5.js +0 -1
- package/.next/static/chunks/9079-24f9fa549ed298f1.js +0 -1
- package/.next/static/chunks/app/sessions/page-e02f1adb1d1c1ccc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9cf1ecc59e36a004.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-46aced20b2b1c010.js +0 -1
- /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_buildManifest.js +0 -0
- /package/.next/static/{etorRtpxbQqqOzdUeXdw2 → 3_JtAZaKMJEDFIIfkHv4n}/_ssgManifest.js +0 -0
|
@@ -6,10 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.isWithheldForWantOfReceipt = isWithheldForWantOfReceipt;
|
|
9
|
+
exports.isAntigravityGenericReadingOnScreen = isAntigravityGenericReadingOnScreen;
|
|
9
10
|
exports.isNumberedDialogVouched = isNumberedDialogVouched;
|
|
10
11
|
const logger_1 = require("../../lib/logger");
|
|
11
12
|
const logger = (0, logger_1.createLogger)('response-poller');
|
|
12
13
|
const antigravity_receipt_episodes_1 = require("./antigravity-receipt-episodes");
|
|
14
|
+
const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
|
|
15
|
+
const auto_yes_option_effect_1 = require("./auto-yes-option-effect");
|
|
13
16
|
// Issue #2457: the same rollout table, `hasDialogRules` cross-check and
|
|
14
17
|
// `detectDialog` seam Auto-Yes reads, reached through the presence helper rather
|
|
15
18
|
// than through `evaluateAutoYesDialogGate` — see `isNumberedDialogVouched`.
|
|
@@ -44,6 +47,42 @@ function isWithheldForWantOfReceipt(scope) {
|
|
|
44
47
|
});
|
|
45
48
|
return true;
|
|
46
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Does the screen itself show that the generic parser's agy reading is one
|
|
52
|
+
* CommandMate may answer? (Issue #3881, the second half: finding 8)
|
|
53
|
+
*
|
|
54
|
+
* Asked by the answering entry (`detectPromptOnCleanFrame` with a receipt
|
|
55
|
+
* scope) only for a reading agy's own reader did not take and
|
|
56
|
+
* `isAntigravityUnansweredNumberedScreen` let through — in practice a reply's
|
|
57
|
+
* plain `1. … N.` list (#1928's legacy reading). Before this, such a list was
|
|
58
|
+
* answered whenever agy's hook had recorded a tool call a moment earlier
|
|
59
|
+
* (#2849). The receipt says a tool call happened; it says nothing about
|
|
60
|
+
* whether THIS list is that call's approval UI, so on its own it is not
|
|
61
|
+
* evidence. The screen must show some:
|
|
62
|
+
*
|
|
63
|
+
* - agy's `/feedback` menu (its own footer under the options), the generic
|
|
64
|
+
* reading #2364 left in place;
|
|
65
|
+
* - option rows agy's measured permission wording reads as (`Yes`, `Yes, run
|
|
66
|
+
* command`, `Yes, and always allow …` — `auto-yes-option-effect`).
|
|
67
|
+
*
|
|
68
|
+
* The heading (`Requesting permission for:` / `Do you want to proceed?`), the
|
|
69
|
+
* `>` cursor and the `↑/↓ Navigate` footer are the other evidence, and a frame
|
|
70
|
+
* that shows them reaches no generic reading: agy's reader answers it, or
|
|
71
|
+
* `isAntigravityUnansweredNumberedScreen` declines it (#3808, #3818).
|
|
72
|
+
*
|
|
73
|
+
* A yes/no reading is not a numbered list and is left as it was.
|
|
74
|
+
*
|
|
75
|
+
* @param cleanOutput - The frame the reading came off (ANSI and box drawing stripped)
|
|
76
|
+
* @param reading - The generic parser's reading of it
|
|
77
|
+
*/
|
|
78
|
+
function isAntigravityGenericReadingOnScreen(cleanOutput, reading) {
|
|
79
|
+
const promptData = reading.promptData;
|
|
80
|
+
if (promptData?.type !== 'multiple_choice')
|
|
81
|
+
return true;
|
|
82
|
+
if ((0, dialog_1.isAntigravityFeedbackMenuScreen)(cleanOutput))
|
|
83
|
+
return true;
|
|
84
|
+
return (0, auto_yes_option_effect_1.selectAllowOnceOption)(promptData.options, 'antigravity').kind !== 'not-a-permission-dialog';
|
|
85
|
+
}
|
|
47
86
|
/**
|
|
48
87
|
* Is the generic parser's numbered-list candidate a dialog the tool vouches for?
|
|
49
88
|
* (Issue #2457)
|
|
@@ -63,23 +63,15 @@ const prompt_push_gate_1 = require("../../lib/push/prompt-push-gate");
|
|
|
63
63
|
// Issue #2000: deep path for the same reason as the two imports above.
|
|
64
64
|
const failure_push_notifier_1 = require("../../lib/push/failure-push-notifier");
|
|
65
65
|
const upstream_faults_1 = require("../../lib/detection/upstream-faults");
|
|
66
|
+
const realtime_snippet_1 = require("../../lib/realtime-snippet");
|
|
66
67
|
const waiting_push_notifier_1 = require("../../lib/push/waiting-push-notifier");
|
|
68
|
+
const waiting_episode_binding_1 = require("../../lib/session/waiting-episode-binding");
|
|
67
69
|
const waiting_episode_state_1 = require("../../lib/session/waiting-episode-state");
|
|
70
|
+
const waiting_screen_reading_1 = require("../../lib/detection/waiting-screen-reading");
|
|
71
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
72
|
+
const auto_yes_poller_state_1 = require("./auto-yes-poller-state");
|
|
68
73
|
const task_transition_service_1 = require("../../lib/tasks/task-transition-service");
|
|
69
74
|
const response_checker_blank_response_1 = require("./response-checker-blank-response");
|
|
70
|
-
/**
|
|
71
|
-
* How many rows from the bottom of a capture the upstream-fault check reads
|
|
72
|
-
* (Issue #2000).
|
|
73
|
-
*
|
|
74
|
-
* The same 100 as `current-output-builder`'s `realtimeSnippet`, and for the
|
|
75
|
-
* reason #1839 gives there: the wider capture keeps a banner from an hour ago
|
|
76
|
-
* in scope, and "is this happening now" is the only question worth ringing a
|
|
77
|
-
* phone about. Keeping the two windows equal also means the notification and
|
|
78
|
-
* the `upstreamFault` field an operator reads in `capture --json` are judging
|
|
79
|
-
* the same rows — a fault that rang but is invisible in the payload next to it
|
|
80
|
-
* is unverifiable.
|
|
81
|
-
*/
|
|
82
|
-
const UPSTREAM_FAULT_SCAN_ROWS = 100;
|
|
83
75
|
/**
|
|
84
76
|
* Raise a push notification when this frame shows a NEW upstream fault
|
|
85
77
|
* (Issue #2000).
|
|
@@ -96,8 +88,17 @@ const UPSTREAM_FAULT_SCAN_ROWS = 100;
|
|
|
96
88
|
* anything, so the level can be handed over on every poll.
|
|
97
89
|
*/
|
|
98
90
|
function observeUpstreamFaultForPush(worktreeId, cliToolId, instanceId, output) {
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
// The rows `current-output-builder` publishes as `realtimeSnippet` and judges
|
|
92
|
+
// `upstreamFault` on (#1839), cut by the same function rather than a copy of
|
|
93
|
+
// its window. The reason is #1839's: the wider capture keeps a banner from an
|
|
94
|
+
// hour ago in scope, and "is this happening now" is the only question worth
|
|
95
|
+
// ringing a phone about. Sharing the cut also means the notification and the
|
|
96
|
+
// `upstreamFault` an operator reads in `capture --json` judge the same rows —
|
|
97
|
+
// a fault that rang but is invisible in the payload next to it is
|
|
98
|
+
// unverifiable. Issue #3936: the plain last 100 rows (#2000) drifted from the
|
|
99
|
+
// snippet when #2768 anchored it to the last row with content, so an inline
|
|
100
|
+
// codex pane showed `model-capacity` in the capture and never rang.
|
|
101
|
+
const match = (0, upstream_faults_1.matchUpstreamFault)((0, realtime_snippet_1.buildRealtimeSnippet)(output));
|
|
101
102
|
// Fire-and-forget, like every other push call in this file: the poller must
|
|
102
103
|
// not slow down or break because a notification could not be delivered.
|
|
103
104
|
void (0, failure_push_notifier_1.notifyUpstreamFaultPush)({
|
|
@@ -154,6 +155,7 @@ function broadcastPromptSweptToAnswered(worktreeId) {
|
|
|
154
155
|
// the one that calls `detectPrompt`, and only this file may import
|
|
155
156
|
// `@/lib/tmux/tmux-capture-cache` (.eslintrc.json `no-restricted-imports`).
|
|
156
157
|
const response_checker_extraction_result_1 = require("./response-checker-extraction-result");
|
|
158
|
+
const prompt_screen_reading_1 = require("./prompt-screen-reading");
|
|
157
159
|
var response_checker_extraction_result_2 = require("./response-checker-extraction-result");
|
|
158
160
|
Object.defineProperty(exports, "incompleteResult", { enumerable: true, get: function () { return response_checker_extraction_result_2.incompleteResult; } });
|
|
159
161
|
Object.defineProperty(exports, "buildPromptExtractionResult", { enumerable: true, get: function () { return response_checker_extraction_result_2.buildPromptExtractionResult; } });
|
|
@@ -197,8 +199,10 @@ const response_checker_extraction_steps_1 = require("./response-checker-extracti
|
|
|
197
199
|
* @param receiptScope - whose frame this is, when the caller answers it
|
|
198
200
|
* automatically (Issue #2849). For agy only: a frame that reads as a prompt is
|
|
199
201
|
* then handed back as no prompt unless agy asked CommandMate about a tool call
|
|
200
|
-
* for that instance a moment ago
|
|
201
|
-
*
|
|
202
|
+
* for that instance a moment ago — and (Issue #3881) a generic numbered
|
|
203
|
+
* reading also needs evidence on the screen itself
|
|
204
|
+
* (`isAntigravityGenericReadingOnScreen`). Omitted, the reading is not gated —
|
|
205
|
+
* which is what every caller that only DISPLAYS the frame wants.
|
|
202
206
|
* @param frame - the SAME tick's `normalizeFrame(raw, cliToolId)`, when the
|
|
203
207
|
* caller built one (Issue #3183). The Auto-Yes poller builds it once and hands
|
|
204
208
|
* the same object to the dialog gate, so the quotation veto below and the gate
|
|
@@ -235,7 +239,13 @@ function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawF
|
|
|
235
239
|
// reads `> 1. Google OAuth` as an answerable option. Judged without the
|
|
236
240
|
// footer, so a missing footer cannot reopen the generic path. The status
|
|
237
241
|
// verdict publishes the same frame as unclassified (`tools/antigravity/detect.ts`).
|
|
238
|
-
|
|
242
|
+
//
|
|
243
|
+
// Issue #3818: and by default — a numbered agy screen keeps the generic
|
|
244
|
+
// reading only as `/feedback` or as a reply's plain `1. … N.` list, so a
|
|
245
|
+
// run with a number missing or its `>` row off the pane is no prompt either.
|
|
246
|
+
// The status verdict keeps #3808's narrower rule: these frames still read
|
|
247
|
+
// as someone waiting there, they are only not answered from here.
|
|
248
|
+
if ((0, dialog_1.isAntigravityUnansweredNumberedScreen)(cleanOutput)) {
|
|
239
249
|
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
240
250
|
}
|
|
241
251
|
}
|
|
@@ -293,6 +303,14 @@ function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawF
|
|
|
293
303
|
if (cliToolId === 'antigravity' && result.isPrompt && (0, response_checker_dialog_gate_1.isWithheldForWantOfReceipt)(receiptScope)) {
|
|
294
304
|
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
295
305
|
}
|
|
306
|
+
// Issue #3881 (finding 8): and with a receipt, the receipt alone does not
|
|
307
|
+
// vouch for a generic reading — a reply's plain numbered list is answered
|
|
308
|
+
// only when the screen itself shows a known menu or agy's permission rows.
|
|
309
|
+
// Only for the caller that answers (a receipt scope); a display keeps it.
|
|
310
|
+
if (cliToolId === 'antigravity' && result.isPrompt && receiptScope !== undefined
|
|
311
|
+
&& !(0, response_checker_dialog_gate_1.isAntigravityGenericReadingOnScreen)(cleanOutput, result)) {
|
|
312
|
+
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
313
|
+
}
|
|
296
314
|
return result;
|
|
297
315
|
}
|
|
298
316
|
/**
|
|
@@ -615,6 +633,24 @@ function extractCompletedTurn(ctx, output, lastCapturedLine, owns) {
|
|
|
615
633
|
}
|
|
616
634
|
return { result, isFullScreenTui, lineCountIsCursor };
|
|
617
635
|
}
|
|
636
|
+
/**
|
|
637
|
+
* The episode a committed prompt observation left this wait in (Issue #3798):
|
|
638
|
+
* the one kept or rebound, the one the commit just opened or put in place, or
|
|
639
|
+
* null when the commit changed nothing.
|
|
640
|
+
*/
|
|
641
|
+
function committedEpisodeId(plan, committed) {
|
|
642
|
+
const obs = plan.observation;
|
|
643
|
+
switch (committed) {
|
|
644
|
+
case 'kept':
|
|
645
|
+
case 'rebound':
|
|
646
|
+
return plan.episodeId;
|
|
647
|
+
case 'opened':
|
|
648
|
+
case 'replaced':
|
|
649
|
+
return (0, waiting_episode_state_1.getWaitingEpisodeRecord)(obs.worktreeId, obs.cliToolId, obs.instanceId)?.episodeId ?? null;
|
|
650
|
+
default:
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
618
654
|
/**
|
|
619
655
|
* Save a live prompt as a prompt message, and raise what follows from it: the
|
|
620
656
|
* task event, the push notification and the waiting episode.
|
|
@@ -627,9 +663,11 @@ function extractCompletedTurn(ctx, output, lastCapturedLine, owns) {
|
|
|
627
663
|
* @param promptDetection - The detection that passed the #2457 gate
|
|
628
664
|
* @param result - The complete extraction this tick made
|
|
629
665
|
* @param isFullScreenTui - True for opencode and copilot, which keep polling after a prompt
|
|
666
|
+
* @param frameTime - When the frame this prompt was read on was fetched (Issue #3798)
|
|
667
|
+
* @param frame - The capture the prompt was read on, for the stored reading (Issue #3881)
|
|
630
668
|
* @returns What `checkForResponse` returns for this tick
|
|
631
669
|
*/
|
|
632
|
-
function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
670
|
+
function savePromptMessage(ctx, promptDetection, result, isFullScreenTui, frameTime, frame) {
|
|
633
671
|
const { db, worktree, worktreeId, cliToolId, instanceId, resolvedInstanceId, pollerKey } = ctx;
|
|
634
672
|
// Issue #3701: the question #3663 / #3684 ask, for the prompt a tick retired
|
|
635
673
|
// during the capture's `await` then finds on the pane — no row, broadcast,
|
|
@@ -646,6 +684,34 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
646
684
|
});
|
|
647
685
|
return false;
|
|
648
686
|
}
|
|
687
|
+
// Issue #3798 (design 規則 8): what this prompt does to the waiting episode,
|
|
688
|
+
// decided BEFORE the dedup below registers its hash. A frame fetched before
|
|
689
|
+
// the close of the very confirmation it shows — an answer and a stop landed
|
|
690
|
+
// during the capture — is not a new wait: nothing is saved, registered or
|
|
691
|
+
// pushed, and the next tick's frame decides. Planned against the state as it
|
|
692
|
+
// is now (`freshPrompt`), not as the tick found it. With the Auto-Yes
|
|
693
|
+
// poller's last answer (PR 3): another confirmation in the wait it answered
|
|
694
|
+
// is a new wait (R1-7), with a hold of its own rather than the spent one.
|
|
695
|
+
const plan = (0, waiting_episode_binding_1.planWaitingObservation)({
|
|
696
|
+
worktreeId,
|
|
697
|
+
cliToolId,
|
|
698
|
+
instanceId,
|
|
699
|
+
observer: 'response-checker',
|
|
700
|
+
start: ctx.observationStart,
|
|
701
|
+
reading: (0, waiting_screen_reading_1.promptWaitingReading)(promptDetection.promptData ?? null),
|
|
702
|
+
...frameTime,
|
|
703
|
+
freshPrompt: true,
|
|
704
|
+
lastAnswer: (0, auto_yes_poller_state_1.getAutoYesLastAnswer)((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId)),
|
|
705
|
+
});
|
|
706
|
+
if (plan.action === 'ignored') {
|
|
707
|
+
logger.info('prompt-observation-stale', {
|
|
708
|
+
worktreeId,
|
|
709
|
+
cliToolId,
|
|
710
|
+
instanceId: resolvedInstanceId,
|
|
711
|
+
because: plan.ignoredBecause,
|
|
712
|
+
});
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
649
715
|
// Issue #565: Content hash-based duplicate prompt prevention
|
|
650
716
|
const promptContent = promptDetection.rawContent || promptDetection.cleanContent;
|
|
651
717
|
const normalizedForDedup = (0, prompt_dedup_1.normalizePromptForDedup)(promptContent, cliToolId);
|
|
@@ -670,6 +736,9 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
670
736
|
}
|
|
671
737
|
return false;
|
|
672
738
|
}
|
|
739
|
+
// Issue #3881 (review P2-1): whether the frame's first row is the pane's —
|
|
740
|
+
// the capture was taken with `CACHE_MAX_CAPTURE_LINES` (`checkForResponse`).
|
|
741
|
+
const captureTop = (0, prompt_screen_reading_1.captureTopOf)(frame, tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES, cliToolId);
|
|
673
742
|
// Issue #571: Clean TUI decorations from Copilot prompt content before saving
|
|
674
743
|
let promptSaveContent = promptContent;
|
|
675
744
|
if (cliToolId === 'copilot') {
|
|
@@ -683,7 +752,13 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
683
752
|
role: 'assistant',
|
|
684
753
|
content: promptSaveContent,
|
|
685
754
|
messageType: 'prompt',
|
|
686
|
-
|
|
755
|
+
// Issue #3881: with what the frame was read as — the kind, the live rows,
|
|
756
|
+
// the target's completeness — so the chat transcript and every later
|
|
757
|
+
// reader take it as stated instead of deciding it again from the strings.
|
|
758
|
+
// Review P2-1: the capture window says whether the frame's top is the
|
|
759
|
+
// pane's (`captureTop`, and `top-unknown` on a target that reached a cut top),
|
|
760
|
+
// as the Auto-Yes poller reads its own frame.
|
|
761
|
+
promptData: (0, prompt_screen_reading_1.promptDataForStorage)(cliToolId, frame, (0, prompt_screen_reading_1.withCaptureTopCompleteness)(promptDetection, captureTop), captureTop),
|
|
687
762
|
timestamp: new Date(),
|
|
688
763
|
cliToolId,
|
|
689
764
|
instanceId: resolvedInstanceId,
|
|
@@ -701,19 +776,19 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
701
776
|
// Fire-and-forget — push is advisory and must never block/break the poller.
|
|
702
777
|
//
|
|
703
778
|
// Issue #1790: the wait is now named by #1786's episode rather than by the
|
|
704
|
-
// prompt text.
|
|
705
|
-
//
|
|
706
|
-
//
|
|
707
|
-
//
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
//
|
|
711
|
-
//
|
|
712
|
-
//
|
|
713
|
-
//
|
|
714
|
-
//
|
|
715
|
-
|
|
716
|
-
const promptWaitingSince =
|
|
779
|
+
// prompt text. Issue #3798: and by the episode's id, which the store gives
|
|
780
|
+
// a wait only when it opens or replaces one. So the observation is committed
|
|
781
|
+
// first and the notification raised with the id the commit settled on —
|
|
782
|
+
// the kept or rebound wait's, or the one just opened — inside
|
|
783
|
+
// `fanOutAfterCommit`, which holds the edge listener's own gate back until
|
|
784
|
+
// this fan-out is done: the notification that quotes the prompt's question
|
|
785
|
+
// still records the episode in the dedup first, and the listener (and
|
|
786
|
+
// #1788's WebSocket frame) agree with it about *which* wait this is — the
|
|
787
|
+
// same id to the gate's hold and suppression record, the dedup and the
|
|
788
|
+
// card's order. A commit that changed nothing (the episode moved since the
|
|
789
|
+
// plan) names no id, and the plan's `since` decides as before.
|
|
790
|
+
// No `await` from the plan to the commit.
|
|
791
|
+
const promptWaitingSince = plan.since ?? plan.at;
|
|
717
792
|
// Issue #1999: Auto-Yes is a declaration that this session's prompts are
|
|
718
793
|
// answered without a human, so notifying for one is telling the reader the
|
|
719
794
|
// opposite of the truth. Only the notification is gated — the episode
|
|
@@ -721,30 +796,27 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
721
796
|
// reminder all see the wait exactly as they did before. The gate runs
|
|
722
797
|
// before the call rather than inside it because `shouldSendWaitingPush`
|
|
723
798
|
// records the episode the moment it decides to send.
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
instanceId,
|
|
728
|
-
waitingSince: promptWaitingSince,
|
|
729
|
-
})) {
|
|
730
|
-
void (0, push_1.notifyPushSubscribers)({
|
|
799
|
+
(0, waiting_push_notifier_1.fanOutAfterCommit)({ worktreeId, cliToolId, instanceId }, () => (0, waiting_episode_binding_1.commitWaitingObservation)(plan), (committed) => {
|
|
800
|
+
const waitingEpisodeId = committedEpisodeId(plan, committed);
|
|
801
|
+
if (!(0, prompt_push_gate_1.isPromptPushSuppressed)({
|
|
731
802
|
worktreeId,
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
agentName: resolvedInstanceId,
|
|
735
|
-
instanceId: resolvedInstanceId,
|
|
736
|
-
waitingKind: 'prompt',
|
|
803
|
+
cliToolId,
|
|
804
|
+
instanceId,
|
|
737
805
|
waitingSince: promptWaitingSince,
|
|
738
|
-
|
|
739
|
-
})
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
806
|
+
waitingEpisodeId,
|
|
807
|
+
})) {
|
|
808
|
+
void (0, push_1.notifyPushSubscribers)({
|
|
809
|
+
worktreeId,
|
|
810
|
+
worktreeName: worktree.name,
|
|
811
|
+
kind: 'prompt',
|
|
812
|
+
agentName: resolvedInstanceId,
|
|
813
|
+
instanceId: resolvedInstanceId,
|
|
814
|
+
waitingKind: 'prompt',
|
|
815
|
+
waitingSince: promptWaitingSince,
|
|
816
|
+
waitingEpisodeId,
|
|
817
|
+
excerpt: promptDetection.promptData?.question ?? promptSaveContent,
|
|
818
|
+
}).catch(() => { });
|
|
819
|
+
}
|
|
748
820
|
});
|
|
749
821
|
if (!isFullScreenTui) {
|
|
750
822
|
(0, response_poller_core_1.stopPolling)(worktreeId, cliToolId, instanceId);
|
|
@@ -1203,7 +1275,18 @@ async function recordCompletedResponse(ctx, turn, claudeMetadata, cleanedRespons
|
|
|
1203
1275
|
// API, and every later prompt would be folded into that stale episode and
|
|
1204
1276
|
// silently deduped. Nothing to close is a no-op, and no notification is
|
|
1205
1277
|
// raised for a closing edge.
|
|
1206
|
-
|
|
1278
|
+
//
|
|
1279
|
+
// Issue #3798: only the episode this tick started against — one that opened
|
|
1280
|
+
// or moved while the reader and the log ran is not this reply's to end.
|
|
1281
|
+
(0, waiting_episode_binding_1.observeWaiting)({
|
|
1282
|
+
worktreeId,
|
|
1283
|
+
cliToolId,
|
|
1284
|
+
instanceId,
|
|
1285
|
+
observer: 'response-checker',
|
|
1286
|
+
start: ctx.observationStart,
|
|
1287
|
+
reading: { kind: 'not-waiting' },
|
|
1288
|
+
frameCapturedAt: 0,
|
|
1289
|
+
});
|
|
1207
1290
|
// Web Push fan-out (Issue #1125): session completed (running → idle).
|
|
1208
1291
|
// Fire-and-forget — push is advisory and must never block/break the poller.
|
|
1209
1292
|
void (0, push_1.notifyPushSubscribers)({
|
|
@@ -1256,6 +1339,8 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1256
1339
|
instanceId,
|
|
1257
1340
|
resolvedInstanceId,
|
|
1258
1341
|
pollerKey,
|
|
1342
|
+
// Issue #3798: before the tick's first `await`.
|
|
1343
|
+
observationStart: (0, waiting_episode_binding_1.startWaitingObservation)(worktreeId, cliToolId, instanceId),
|
|
1259
1344
|
};
|
|
1260
1345
|
// Check if CLI tool session is running
|
|
1261
1346
|
const running = await (0, cli_session_1.isSessionRunning)(worktreeId, cliToolId, instanceId);
|
|
@@ -1320,7 +1405,9 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1320
1405
|
// Capture current output. The requested width IS the capture window, so it is
|
|
1321
1406
|
// taken from the same constant extractResponse() measures saturation against
|
|
1322
1407
|
// (Issue #1670) — a literal here would silently decouple the two.
|
|
1323
|
-
|
|
1408
|
+
// Issue #3798: dated by where that frame came from — from the cache, it may
|
|
1409
|
+
// be older than this tick.
|
|
1410
|
+
const { frame: output, frameTime } = await (0, waiting_episode_binding_1.captureObservedFrame)(() => (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES, instanceId));
|
|
1324
1411
|
// Issue #3705: there is no `await` from here to the transcript reader
|
|
1325
1412
|
// inside the save path, so this one answer covers every write in between —
|
|
1326
1413
|
// the fault notifier, the TUI accumulator, the prompt sweep, the skip
|
|
@@ -1360,7 +1447,7 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1360
1447
|
if (owns)
|
|
1361
1448
|
(0, response_dedup_1.resetDuplicateResponseSkipStreak)(pollerKey);
|
|
1362
1449
|
// Asks for itself (#3701), before the prompt dedup.
|
|
1363
|
-
return savePromptMessage(ctx, promptDetection, result, isFullScreenTui);
|
|
1450
|
+
return savePromptMessage(ctx, promptDetection, result, isFullScreenTui, frameTime, output);
|
|
1364
1451
|
}
|
|
1365
1452
|
// Issue #3538: a finished frame without a live prompt ends the run of
|
|
1366
1453
|
// duplicate prompt ticks, as an unfinished one does in `extractCompletedTurn`.
|
|
@@ -665,7 +665,7 @@ async function recaptureAfterKeys(sessionName) {
|
|
|
665
665
|
* @throws {MultiSelectAnswerRejectedError} whenever the question was not
|
|
666
666
|
* committed; `keysSent` says whether the pane was touched.
|
|
667
667
|
*/
|
|
668
|
-
async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted, stillCurrent) {
|
|
668
|
+
async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted, stillCurrent, touch) {
|
|
669
669
|
const cursor = promptData.options.find((option) => option.isDefault === true);
|
|
670
670
|
if (cursor === undefined) {
|
|
671
671
|
throw new MultiSelectAnswerRejectedError('cursor-unknown', false, wanted);
|
|
@@ -679,7 +679,7 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted,
|
|
|
679
679
|
...current.filter((n) => !wanted.includes(n)),
|
|
680
680
|
].sort((a, b) => a - b);
|
|
681
681
|
if (toggles.length > 0) {
|
|
682
|
-
await sendSpecialKeysWhileCurrent(sessionName, toggles.map(String), stillCurrent);
|
|
682
|
+
await sendSpecialKeysWhileCurrent(sessionName, toggles.map(String), stillCurrent, touch);
|
|
683
683
|
}
|
|
684
684
|
const keysSent = toggles.length > 0;
|
|
685
685
|
// 2. Read the screen back and refuse unless it is the same question with
|
|
@@ -712,7 +712,7 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted,
|
|
|
712
712
|
if (cursorNow === undefined) {
|
|
713
713
|
throw new MultiSelectAnswerRejectedError('cursor-unknown', keysSent, wanted);
|
|
714
714
|
}
|
|
715
|
-
await sendSpecialKeysWhileCurrent(sessionName, [...downKeys(verified.options.length - cursorNow.number + 1), 'Enter'], stillCurrent);
|
|
715
|
+
await sendSpecialKeysWhileCurrent(sessionName, [...downKeys(verified.options.length - cursorNow.number + 1), 'Enter'], stillCurrent, touch);
|
|
716
716
|
// 4. The second stage. `Submit` opens the Review page and the answer is sent
|
|
717
717
|
// from there; `Next` advances to the following question, which IS the
|
|
718
718
|
// commit for this one (its tab turns `✔`).
|
|
@@ -728,7 +728,7 @@ async function sendCommandCodeMultiSelectAnswer(sessionName, promptData, wanted,
|
|
|
728
728
|
if (review.hasUnansweredWarning) {
|
|
729
729
|
throw new MultiSelectAnswerRejectedError('review-unanswered', true, wanted);
|
|
730
730
|
}
|
|
731
|
-
await sendSpecialKeysWhileCurrent(sessionName, ['Enter'], stillCurrent);
|
|
731
|
+
await sendSpecialKeysWhileCurrent(sessionName, ['Enter'], stillCurrent, touch);
|
|
732
732
|
return;
|
|
733
733
|
}
|
|
734
734
|
const next = (0, dialog_1.readCommandCodeQuestionDialog)(afterConfirm);
|
|
@@ -756,6 +756,50 @@ class PromptAnswerAbortedError extends Error {
|
|
|
756
756
|
}
|
|
757
757
|
}
|
|
758
758
|
exports.PromptAnswerAbortedError = PromptAnswerAbortedError;
|
|
759
|
+
/**
|
|
760
|
+
* What the tmux call that failed did (Issue #3880), when the error came from
|
|
761
|
+
* the transport (`TmuxSendError`, by name: test doubles of `./tmux/tmux` need
|
|
762
|
+
* not export the class); null for any other error.
|
|
763
|
+
*/
|
|
764
|
+
function transportDeliveryOf(error) {
|
|
765
|
+
if (!(error instanceof Error) || error.name !== 'TmuxSendError')
|
|
766
|
+
return null;
|
|
767
|
+
const delivery = error.delivery;
|
|
768
|
+
return delivery === 'not-started' || delivery === 'indeterminate' ? delivery : null;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* A failure after a key reached the pane says so (Issue #3839): `keysSent: true`
|
|
772
|
+
* is put on it, as on {@link PromptAnswerAbortedError}, so Auto-Yes does not
|
|
773
|
+
* type the answer again over what is already there. An error that already
|
|
774
|
+
* names `keysSent` (the refusals and the stop above) keeps its own word, and a
|
|
775
|
+
* failure before any key is left as it was.
|
|
776
|
+
*
|
|
777
|
+
* Issue #3880: a transport failure also gets `answerDelivery` ({@link AnswerDelivery};
|
|
778
|
+
* the tmux error's own `delivery` is that one call's).
|
|
779
|
+
* `indeterminate` — the tmux call ended without an exit status, and its key may
|
|
780
|
+
* be on the pane — is NOT `keysSent: true` (no key is known to be there; the
|
|
781
|
+
* ledger counts it `failed`, #3820) but Auto-Yes holds it all the same. A
|
|
782
|
+
* transport refusal before any key is `keysSent: false`: known not sent, free
|
|
783
|
+
* to be sent again.
|
|
784
|
+
*/
|
|
785
|
+
function withKeysSent(error, touch) {
|
|
786
|
+
if (!(error instanceof Error))
|
|
787
|
+
return error;
|
|
788
|
+
const transport = transportDeliveryOf(error);
|
|
789
|
+
if (transport !== null) {
|
|
790
|
+
const answerDelivery = transport === 'indeterminate' ? 'indeterminate' : touch.touched ? 'delivered' : 'not-started';
|
|
791
|
+
Object.assign(error, { answerDelivery });
|
|
792
|
+
}
|
|
793
|
+
if ('keysSent' in error)
|
|
794
|
+
return error;
|
|
795
|
+
if (touch.touched) {
|
|
796
|
+
Object.assign(error, { keysSent: true });
|
|
797
|
+
}
|
|
798
|
+
else if (transport === 'not-started') {
|
|
799
|
+
Object.assign(error, { keysSent: false });
|
|
800
|
+
}
|
|
801
|
+
return error;
|
|
802
|
+
}
|
|
759
803
|
/** Stop here when the caller's `stillCurrent` says no (Issue #3706). */
|
|
760
804
|
function assertStillCurrent(stillCurrent, keysSent) {
|
|
761
805
|
if (stillCurrent && !stillCurrent())
|
|
@@ -766,13 +810,32 @@ function assertStillCurrent(stillCurrent, keysSent) {
|
|
|
766
810
|
* gave one (Issue #3706). Without it the call is exactly the old two-argument
|
|
767
811
|
* one, so manual answers and every other caller send as before.
|
|
768
812
|
*/
|
|
769
|
-
async function sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent) {
|
|
813
|
+
async function sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent, touch) {
|
|
770
814
|
if (!stillCurrent) {
|
|
771
|
-
|
|
815
|
+
try {
|
|
816
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys);
|
|
817
|
+
}
|
|
818
|
+
catch (error) {
|
|
819
|
+
// Issue #3880: without `shouldContinue` the count comes from the error.
|
|
820
|
+
if (touch && keysDeliveredOf(error) > 0)
|
|
821
|
+
touch.touched = true;
|
|
822
|
+
throw error;
|
|
823
|
+
}
|
|
824
|
+
if (touch && keys.length > 0)
|
|
825
|
+
touch.touched = true;
|
|
772
826
|
return;
|
|
773
827
|
}
|
|
828
|
+
// Issue #3839: `shouldContinue` is asked after each key but the last, so the
|
|
829
|
+
// times it was asked are the keys known to have reached the pane when a
|
|
830
|
+
// later one fails.
|
|
831
|
+
let delivered = 0;
|
|
774
832
|
try {
|
|
775
|
-
await (0, tmux_1.sendSpecialKeys)(sessionName, keys, {
|
|
833
|
+
await (0, tmux_1.sendSpecialKeys)(sessionName, keys, {
|
|
834
|
+
shouldContinue: () => {
|
|
835
|
+
delivered++;
|
|
836
|
+
return stillCurrent();
|
|
837
|
+
},
|
|
838
|
+
});
|
|
776
839
|
}
|
|
777
840
|
catch (error) {
|
|
778
841
|
// By name rather than `instanceof`: test doubles of `./tmux/tmux` need not
|
|
@@ -780,8 +843,22 @@ async function sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent) {
|
|
|
780
843
|
if (error instanceof Error && error.name === 'SpecialKeysAbortedError') {
|
|
781
844
|
throw new PromptAnswerAbortedError(true);
|
|
782
845
|
}
|
|
846
|
+
if (touch && Math.max(delivered, keysDeliveredOf(error)) > 0)
|
|
847
|
+
touch.touched = true;
|
|
783
848
|
throw error;
|
|
784
849
|
}
|
|
850
|
+
if (touch && keys.length > 0)
|
|
851
|
+
touch.touched = true;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* The keys a failed `sendSpecialKeys` says tmux took before the one that
|
|
855
|
+
* failed (Issue #3880, `TmuxSendError.keysDelivered`); 0 when it says none.
|
|
856
|
+
*/
|
|
857
|
+
function keysDeliveredOf(error) {
|
|
858
|
+
if (!(error instanceof Error) || error.name !== 'TmuxSendError')
|
|
859
|
+
return 0;
|
|
860
|
+
const count = error.keysDelivered;
|
|
861
|
+
return typeof count === 'number' && Number.isFinite(count) && count > 0 ? count : 0;
|
|
785
862
|
}
|
|
786
863
|
/**
|
|
787
864
|
* Send an answer to a tmux session, using cursor-key navigation for
|
|
@@ -791,8 +868,22 @@ async function sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent) {
|
|
|
791
868
|
* This function unifies the logic previously duplicated in:
|
|
792
869
|
* - src/app/api/worktrees/[id]/prompt-response/route.ts (L114-187)
|
|
793
870
|
* - src/lib/auto-yes-manager.ts (L340-399)
|
|
871
|
+
*
|
|
872
|
+
* A failure after a key of the answer reached the pane carries `keysSent: true`
|
|
873
|
+
* (Issue #3839), and a transport failure its `answerDelivery` (Issue #3880);
|
|
874
|
+
* see {@link withKeysSent}.
|
|
794
875
|
*/
|
|
795
876
|
async function sendPromptAnswer(params) {
|
|
877
|
+
const touch = { touched: false };
|
|
878
|
+
try {
|
|
879
|
+
await sendPromptAnswerKeys(params, touch);
|
|
880
|
+
}
|
|
881
|
+
catch (error) {
|
|
882
|
+
throw withKeysSent(error, touch);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
/** {@link sendPromptAnswer}, noting in `touch` each key that reached the pane. */
|
|
886
|
+
async function sendPromptAnswerKeys(params, touch) {
|
|
796
887
|
const { sessionName, answer, cliToolId, promptData, fallbackPromptType, fallbackDefaultOptionNumber, stillCurrent } = params;
|
|
797
888
|
// Issue #2755: Command Code's checkbox question, before every guard below.
|
|
798
889
|
// Its answer is a SET (`"1,3"`), which none of them can read — `/^\d+$/` is
|
|
@@ -803,7 +894,7 @@ async function sendPromptAnswer(params) {
|
|
|
803
894
|
// a two-stage confirm, not a digit and an Enter.
|
|
804
895
|
const multiSelect = readMultiSelectRequest(params);
|
|
805
896
|
if (multiSelect !== null) {
|
|
806
|
-
await sendCommandCodeMultiSelectAnswer(sessionName, multiSelect.promptData, multiSelect.wanted, stillCurrent);
|
|
897
|
+
await sendCommandCodeMultiSelectAnswer(sessionName, multiSelect.promptData, multiSelect.wanted, stillCurrent, touch);
|
|
807
898
|
(0, tmux_capture_cache_1.invalidateCache)(sessionName);
|
|
808
899
|
return;
|
|
809
900
|
}
|
|
@@ -874,7 +965,7 @@ async function sendPromptAnswer(params) {
|
|
|
874
965
|
keys.push(...buildNavigationKeys(downToNext));
|
|
875
966
|
// 4. Enter to submit
|
|
876
967
|
keys.push('Enter');
|
|
877
|
-
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent);
|
|
968
|
+
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent, touch);
|
|
878
969
|
}
|
|
879
970
|
else {
|
|
880
971
|
// Single-select: navigate and Enter to select
|
|
@@ -892,12 +983,15 @@ async function sendPromptAnswer(params) {
|
|
|
892
983
|
const keys = (isAskUserQuestionPicker && offset === 0)
|
|
893
984
|
? ['Down', 'Up', 'Enter']
|
|
894
985
|
: [...navigationKeys, 'Enter'];
|
|
895
|
-
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent);
|
|
986
|
+
await sendSpecialKeysWhileCurrent(sessionName, keys, stillCurrent, touch);
|
|
896
987
|
}
|
|
897
988
|
}
|
|
898
989
|
else {
|
|
899
990
|
// Standard CLI prompt: send text + Enter (y/n, Approve?, etc.)
|
|
900
991
|
await (0, tmux_1.sendKeys)(sessionName, answer, false);
|
|
992
|
+
// Issue #3839: the text is on the pane; a failed Enter after it says so.
|
|
993
|
+
if (answer !== '')
|
|
994
|
+
touch.touched = true;
|
|
901
995
|
// Issue #616: Resolve submitMode and determine whether to suppress Enter
|
|
902
996
|
const resolvedSubmitMode = resolveSubmitMode(params, dialog);
|
|
903
997
|
if (!shouldSuppressEnter(params, resolvedSubmitMode, dialog)) {
|
|
@@ -60,15 +60,28 @@ const waitingSent = (0, global_state_1.getOrInitGlobal)('__waitingPushDedup', ()
|
|
|
60
60
|
* - the escalation → allowed exactly once per episode;
|
|
61
61
|
* - a new episode (the wait ended and another began) → sent again, even if the
|
|
62
62
|
* prompt text and the elapsed time are identical.
|
|
63
|
+
*
|
|
64
|
+
* Issue #3798: "the same episode" is the mixed rule `prompt-push-gate` holds
|
|
65
|
+
* its hold by — both ids present and equal, or one absent and the `since`s
|
|
66
|
+
* equal. Kept inline rather than imported: this module stays a leaf.
|
|
63
67
|
*/
|
|
64
68
|
function shouldSendWaitingPush(event) {
|
|
65
69
|
const key = `${event.worktreeId}::${event.instanceId}`;
|
|
66
70
|
const escalated = event.escalated === true;
|
|
71
|
+
const episodeId = event.episodeId ?? undefined;
|
|
67
72
|
const prev = waitingSent.get(key);
|
|
68
|
-
|
|
73
|
+
const sameEpisode = prev !== undefined &&
|
|
74
|
+
(prev.episodeId !== undefined && episodeId !== undefined
|
|
75
|
+
? prev.episodeId === episodeId
|
|
76
|
+
: prev.since === event.since);
|
|
77
|
+
if (prev && sameEpisode && (prev.escalated || !escalated)) {
|
|
78
|
+
// An id-less producer recorded this wait first; it is named now.
|
|
79
|
+
if (prev.episodeId === undefined && episodeId !== undefined)
|
|
80
|
+
prev.episodeId = episodeId;
|
|
69
81
|
return false;
|
|
70
82
|
}
|
|
71
|
-
|
|
83
|
+
const recordedId = episodeId ?? (sameEpisode ? prev?.episodeId : undefined);
|
|
84
|
+
waitingSent.set(key, { since: event.since, ...(recordedId !== undefined ? { episodeId: recordedId } : {}), escalated });
|
|
72
85
|
return true;
|
|
73
86
|
}
|
|
74
87
|
/** Clear the episode-scoped state (for tests). */
|