commandmate 0.46.0 → 0.46.1
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 +259 -259
- package/.next/app-path-routes-manifest.json +14 -14
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +9 -9
- package/.next/react-loadable-manifest.json +2 -2
- 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.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 +9 -9
- 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.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.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.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.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.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.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.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.js +9 -9
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_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.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.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/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 +7 -7
- 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 +14 -14
- package/.next/server/chunks/1501.js +2 -2
- package/.next/server/chunks/1559.js +1 -1
- package/.next/server/chunks/2460.js +1 -1
- package/.next/server/chunks/2908.js +1 -1
- package/.next/server/chunks/2984.js +25 -0
- package/.next/server/chunks/5209.js +1 -1
- package/.next/server/chunks/5292.js +2 -2
- package/.next/server/chunks/5845.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/6722.js +1 -1
- package/.next/server/chunks/8581.js +4 -4
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8791.js +1 -1
- package/.next/server/chunks/8918.js +5 -5
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9627.js +2 -1
- package/.next/server/chunks/9731.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-acb644c5487e1720.js → 2407-9703c569370b8a9d.js} +1 -1
- package/.next/static/chunks/{2717.21abf5b6bbd45520.js → 2717.1583400c272dc1d9.js} +1 -1
- package/.next/static/chunks/5371-0dc947683e46e78c.js +1 -0
- package/.next/static/chunks/5794-4eee51ff1e878aa6.js +1 -0
- package/.next/static/chunks/{8407-9a72e6f07c5d5458.js → 8407-155f84e5ba05f1d5.js} +1 -1
- package/.next/static/chunks/app/{layout-ae30ce63569c22be.js → layout-3e357690446cd2da.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-effbf0796881dd5a.js +1 -0
- package/.next/static/chunks/{webpack-c0b821f340afdebf.js → webpack-468b7b33030234b3.js} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +6 -1
- package/dist/cli/types/api-responses.d.ts +8 -6
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts +13 -1
- package/dist/lib/polling/auto-yes-suppression-reason.d.ts.map +1 -1
- package/dist/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/src/lib/assistant-response-saver.js +13 -0
- package/dist/server/src/lib/auto-yes-poller.js +252 -54
- package/dist/server/src/lib/conversation-logger.js +14 -2
- package/dist/server/src/lib/db/chat-db.js +2 -1
- package/dist/server/src/lib/history/user-turn-recorder.js +14 -0
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +28 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/codex/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +7 -0
- package/dist/server/src/lib/hooks/sources/transcript-history.js +34 -0
- package/dist/server/src/lib/log-manager.js +7 -2
- package/dist/server/src/lib/polling/auto-yes-enter-fallback-state.js +22 -3
- package/dist/server/src/lib/polling/auto-yes-poller-state.js +234 -0
- package/dist/server/src/lib/polling/auto-yes-suppression-reason.js +3 -0
- package/dist/server/src/lib/polling/pending-scraped-response.js +119 -3
- package/dist/server/src/lib/polling/poller-owner.js +110 -0
- package/dist/server/src/lib/polling/response-checker.js +202 -39
- package/dist/server/src/lib/polling/response-dedup.js +8 -0
- package/dist/server/src/lib/polling/response-poller-core.js +131 -12
- package/dist/server/src/lib/polling/structured-history-gate.js +20 -1
- package/dist/server/src/lib/prompt-answer-sender.js +59 -12
- package/dist/server/src/lib/realtime/terminal-broadcast.js +14 -0
- package/dist/server/src/lib/session/chat-turn-progress.js +57 -6
- package/dist/server/src/lib/session/current-output-builder.js +19 -0
- package/dist/server/src/lib/session/worktree-session-reconcile.js +83 -10
- package/dist/server/src/lib/timer-manager.js +7 -0
- package/dist/server/src/lib/tmux/tmux.js +24 -2
- package/dist/server/src/lib/verification/env-clean-gate.js +30 -2
- package/package.json +1 -1
- package/release-notes/0.46.1.json +40 -0
- package/.next/server/chunks/5625.js +0 -25
- package/.next/static/chunks/5371-a94ed618148287a0.js +0 -1
- package/.next/static/chunks/5794-947fb4934d8be193.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-2eb1d0fd0a077b7e.js +0 -1
- /package/.next/static/{zI2nQ6WKboSbFbMF4EtrJ → QxDf7lm-JJkWoj-TyWiSB}/_buildManifest.js +0 -0
- /package/.next/static/{zI2nQ6WKboSbFbMF4EtrJ → QxDf7lm-JJkWoj-TyWiSB}/_ssgManifest.js +0 -0
|
@@ -49,6 +49,7 @@ const session_name_1 = require("../../lib/cli-tools/session-name");
|
|
|
49
49
|
const geometry_delegation_1 = require("../../lib/tmux/geometry-delegation");
|
|
50
50
|
const tmux_session_surface_1 = require("../../lib/session/tmux-session-surface");
|
|
51
51
|
const response_poller_core_1 = require("./response-poller-core");
|
|
52
|
+
const poller_owner_1 = require("./poller-owner");
|
|
52
53
|
const push_1 = require("../../lib/push");
|
|
53
54
|
// Issue #1790: imported by deep path, not through `@/lib/push`. Suites that
|
|
54
55
|
// replace the barrel to count notifications (e.g. the #1547 escalation test)
|
|
@@ -449,6 +450,48 @@ function markOrSettleStructuredHistoryRecheck(pollerKey, recorded) {
|
|
|
449
450
|
(0, response_dedup_1.markStructuredHistoryRecheckPending)(pollerKey);
|
|
450
451
|
}
|
|
451
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* Whether this tick may still act for `pollerKey` after the `await` it has just
|
|
455
|
+
* resumed from, logging the refusal when it may not (Issue #3705).
|
|
456
|
+
*
|
|
457
|
+
* #3663, #3684 and #3701 asked {@link mayActForPollerKey} at the writes that had
|
|
458
|
+
* been reported, one at a time. A tick resumes from an `await` with no idea
|
|
459
|
+
* whether its chain was stopped, cut loose past `STALLED_TICK_TIMEOUT` or moved
|
|
460
|
+
* by a worktree-ID migration in the meantime, and every write after that
|
|
461
|
+
* `await` — the prompt sweep, the waiting edge, the completion push, the cursor,
|
|
462
|
+
* the fault notifier, the TUI accumulator, the recheck and skip-streak state —
|
|
463
|
+
* lands under a key it no longer owns, on whatever the successor has put there.
|
|
464
|
+
* So the question is asked after every `await` of the tick, named by the point
|
|
465
|
+
* it resumed from, and the writes below each point run only on a yes.
|
|
466
|
+
*
|
|
467
|
+
* Not asked where a self-stop hands back its verdict (`return await
|
|
468
|
+
* recordCompletedResponse(…)`): `runPollTick` settles the pause from that
|
|
469
|
+
* value, and a stop the tick raised itself must not lose what it recorded.
|
|
470
|
+
*
|
|
471
|
+
* @param ctx - What this tick is keyed by
|
|
472
|
+
* @param after - The `await` the tick has just resumed from, for the log line
|
|
473
|
+
*/
|
|
474
|
+
function mayStillActAfter(ctx, after) {
|
|
475
|
+
if ((0, poller_owner_1.mayActForPollerKey)(ctx.pollerKey))
|
|
476
|
+
return true;
|
|
477
|
+
// One line per retired tick, at the first point that turned it away: a tick
|
|
478
|
+
// refused at the capture is asked again after the reader and the log.
|
|
479
|
+
const owner = (0, poller_owner_1.currentPollerOwner)();
|
|
480
|
+
if (owner === undefined || !refusalLogged.has(owner)) {
|
|
481
|
+
if (owner)
|
|
482
|
+
refusalLogged.add(owner);
|
|
483
|
+
logger.info('retired-tick-refused', {
|
|
484
|
+
worktreeId: ctx.worktreeId,
|
|
485
|
+
cliToolId: ctx.cliToolId,
|
|
486
|
+
instanceId: ctx.resolvedInstanceId,
|
|
487
|
+
generation: owner?.generation,
|
|
488
|
+
after,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
/** The retired chains {@link mayStillActAfter} has already logged (Issue #3705). */
|
|
494
|
+
const refusalLogged = new WeakSet();
|
|
452
495
|
/**
|
|
453
496
|
* Read the frame this tick captured: is there a finished turn on it that the
|
|
454
497
|
* cursor has not already counted?
|
|
@@ -469,17 +512,25 @@ function markOrSettleStructuredHistoryRecheck(pollerKey, recorded) {
|
|
|
469
512
|
* @param ctx - What this tick is keyed by
|
|
470
513
|
* @param output - The capture this tick made
|
|
471
514
|
* @param lastCapturedLine - Its cursor, 0 when there is none
|
|
515
|
+
* @param owns - Whether the tick still owns its key (Issue #3705); false reads
|
|
516
|
+
* the frame and writes nothing
|
|
472
517
|
* @returns What the tick goes on with, or `false` when the tick ends here
|
|
473
518
|
*/
|
|
474
|
-
function extractCompletedTurn(ctx, output, lastCapturedLine) {
|
|
519
|
+
function extractCompletedTurn(ctx, output, lastCapturedLine, owns) {
|
|
475
520
|
const { db, worktreeId, cliToolId, instanceId, resolvedInstanceId, pollerKey } = ctx;
|
|
476
521
|
// Issue #2000: the frame is in hand, so this is the cheapest place to ask
|
|
477
522
|
// whether the model API has stalled the session. Level in, edge out — see
|
|
478
523
|
// the helper.
|
|
479
|
-
|
|
524
|
+
//
|
|
525
|
+
// Issue #3705: every write in this function is the caller's `owns` — asked
|
|
526
|
+
// right after the capture, with no `await` since. A retired tick's frame is
|
|
527
|
+
// read, and none of it lands on the fault episode, the accumulator, the skip
|
|
528
|
+
// streaks or the pending prompts of the key it lost.
|
|
529
|
+
if (owns)
|
|
530
|
+
observeUpstreamFaultForPush(worktreeId, cliToolId, instanceId, output);
|
|
480
531
|
// Layer 2: Accumulate TUI content for full-screen TUI tools, so a turn that
|
|
481
532
|
// outgrows the alternate-screen pane keeps the head that has scrolled away.
|
|
482
|
-
if (cliToolId === 'opencode' || cliToolId === 'copilot') {
|
|
533
|
+
if (owns && (cliToolId === 'opencode' || cliToolId === 'copilot')) {
|
|
483
534
|
// Issue #1911: opencode is accumulated from the CURRENT TURN'S REGION
|
|
484
535
|
// rather than the whole frame. Feeding the raw pane seeded the accumulator
|
|
485
536
|
// with the previous turn's transcript, the echoed prompt and the bottom
|
|
@@ -501,7 +552,7 @@ function extractCompletedTurn(ctx, output, lastCapturedLine) {
|
|
|
501
552
|
//
|
|
502
553
|
// Issue #3552: the same frame ends a run of duplicate response ticks for
|
|
503
554
|
// the same reason — an unfinished frame is not the saved reply.
|
|
504
|
-
if (result) {
|
|
555
|
+
if (owns && result) {
|
|
505
556
|
(0, prompt_dedup_1.resetDuplicatePromptSkipStreak)(pollerKey);
|
|
506
557
|
(0, response_dedup_1.resetDuplicateResponseSkipStreak)(pollerKey);
|
|
507
558
|
}
|
|
@@ -509,7 +560,7 @@ function extractCompletedTurn(ctx, output, lastCapturedLine) {
|
|
|
509
560
|
const { thinkingPattern } = (0, cli_patterns_1.getCliToolPatterns)(cliToolId);
|
|
510
561
|
const cleanOutput = (0, cli_patterns_1.stripAnsi)(output);
|
|
511
562
|
const tailLines = cleanOutput.split('\n').slice(-thinking_constants_1.THINKING_TAIL_LINE_COUNT).join('\n');
|
|
512
|
-
if (thinkingPattern.test(tailLines)) {
|
|
563
|
+
if (owns && thinkingPattern.test(tailLines)) {
|
|
513
564
|
// Intended twin of the sweep in recordCompletedResponse: this one runs when
|
|
514
565
|
// working is visible on an unfinished frame, that one when a response is
|
|
515
566
|
// recorded (Issue #31).
|
|
@@ -570,6 +621,21 @@ function extractCompletedTurn(ctx, output, lastCapturedLine) {
|
|
|
570
621
|
*/
|
|
571
622
|
function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
572
623
|
const { db, worktree, worktreeId, cliToolId, instanceId, resolvedInstanceId, pollerKey } = ctx;
|
|
624
|
+
// Issue #3701: the question #3663 / #3684 ask, for the prompt a tick retired
|
|
625
|
+
// during the capture's `await` then finds on the pane — no row, broadcast,
|
|
626
|
+
// task event, push or waiting episode under the key it lost. Asked BEFORE the
|
|
627
|
+
// dedup below, which registers the hash before the save: a refused tick that
|
|
628
|
+
// registered it would make the successor drop the same prompt as a
|
|
629
|
+
// duplicate. No `await` from here to the end of this function.
|
|
630
|
+
if (!(0, poller_owner_1.mayActForPollerKey)(pollerKey)) {
|
|
631
|
+
logger.info('prompt-save-refused', {
|
|
632
|
+
worktreeId,
|
|
633
|
+
cliToolId,
|
|
634
|
+
instanceId: resolvedInstanceId,
|
|
635
|
+
generation: (0, poller_owner_1.currentPollerOwner)()?.generation,
|
|
636
|
+
});
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
573
639
|
// Issue #565: Content hash-based duplicate prompt prevention
|
|
574
640
|
const promptContent = promptDetection.rawContent || promptDetection.cleanContent;
|
|
575
641
|
const normalizedForDedup = (0, prompt_dedup_1.normalizePromptForDedup)(promptContent, cliToolId);
|
|
@@ -686,9 +752,10 @@ function savePromptMessage(ctx, promptDetection, result, isFullScreenTui) {
|
|
|
686
752
|
* @param cliToolId - CLI tool identifier
|
|
687
753
|
* @param result - The complete extraction this tick made
|
|
688
754
|
* @param pollerKey - Poller key ("worktreeId:instanceId")
|
|
755
|
+
* @param owns - Whether the tick still owns its key (Issue #3705)
|
|
689
756
|
* @returns The cleaned response
|
|
690
757
|
*/
|
|
691
|
-
function cleanCompletedResponse(cliToolId, result, pollerKey) {
|
|
758
|
+
function cleanCompletedResponse(cliToolId, result, pollerKey, owns) {
|
|
692
759
|
// Clean up responses
|
|
693
760
|
let cleanedResponse = result.response;
|
|
694
761
|
if (cliToolId === 'gemini') {
|
|
@@ -702,7 +769,10 @@ function cleanCompletedResponse(cliToolId, result, pollerKey) {
|
|
|
702
769
|
const sourceContent = accumulatedContent || result.response;
|
|
703
770
|
cleanedResponse = (0, response_cleaner_1.cleanCopilotResponse)(sourceContent);
|
|
704
771
|
cleanedResponse = (0, response_cleaner_1.truncateMessage)(cleanedResponse, copilot_constants_1.COPILOT_MAX_MESSAGE_LENGTH, copilot_constants_1.COPILOT_TRUNCATION_MARKER);
|
|
705
|
-
|
|
772
|
+
// Issue #3705: read, but not cleared, by a tick that lost the key — the
|
|
773
|
+
// successor may already be accumulating its own turn under it.
|
|
774
|
+
if (owns)
|
|
775
|
+
(0, tui_accumulator_1.clearTuiAccumulator)(pollerKey);
|
|
706
776
|
}
|
|
707
777
|
else if (cliToolId === 'opencode') {
|
|
708
778
|
// Issue #1911 defect 3: opencode wrote to the Layer-2 accumulator but never
|
|
@@ -724,7 +794,8 @@ function cleanCompletedResponse(cliToolId, result, pollerKey) {
|
|
|
724
794
|
? accumulatedContent
|
|
725
795
|
: result.response;
|
|
726
796
|
cleanedResponse = (0, response_cleaner_1.cleanOpenCodeResponse)(sourceContent);
|
|
727
|
-
|
|
797
|
+
if (owns)
|
|
798
|
+
(0, tui_accumulator_1.clearTuiAccumulator)(pollerKey);
|
|
728
799
|
}
|
|
729
800
|
return cleanedResponse;
|
|
730
801
|
}
|
|
@@ -744,6 +815,15 @@ function cleanCompletedResponse(cliToolId, result, pollerKey) {
|
|
|
744
815
|
*/
|
|
745
816
|
async function recheckDuplicateResponse(ctx, result, claudeMetadata) {
|
|
746
817
|
const { db, worktree, worktreeId, cliToolId, instanceId, resolvedInstanceId, pollerKey } = ctx;
|
|
818
|
+
// Issue #3705 (review): a retired tick reaches this function too. The dedup
|
|
819
|
+
// answers "duplicate" on a hash match BEFORE it asks about ownership (it only
|
|
820
|
+
// refuses to REGISTER a hash), and the hash it matches may be the successor's
|
|
821
|
+
// — the same reply, saved by the chain that replaced this one while this
|
|
822
|
+
// tick's capture was in flight. Everything below writes under the key (the
|
|
823
|
+
// skip-log claim, the cursor, the recheck claim, then the reader), so the
|
|
824
|
+
// question is asked first, with no `await` between it and those writes.
|
|
825
|
+
if (!mayStillActAfter(ctx, 'capture'))
|
|
826
|
+
return false;
|
|
747
827
|
// Issue #1695: this branch used to drop the response silently — the
|
|
748
828
|
// prompt-side guard above has logged its skip since #565, this one
|
|
749
829
|
// logged nothing at all, so a reply that never reached History left no
|
|
@@ -821,6 +901,11 @@ async function recheckDuplicateResponse(ctx, result, claudeMetadata) {
|
|
|
821
901
|
worktreePath: worktree.path,
|
|
822
902
|
transcriptPathHint: claudeMetadata?.logFilePath ?? null,
|
|
823
903
|
});
|
|
904
|
+
// Issue #3705: the recheck the successor is owed is not settled, and its
|
|
905
|
+
// hold not dropped, by a tick retired while the reader ran. What the reader
|
|
906
|
+
// answered is still the answer (it asks the same question before it writes).
|
|
907
|
+
if (!mayStillActAfter(ctx, 'recheck-reader'))
|
|
908
|
+
return recaptured;
|
|
824
909
|
if (recaptured) {
|
|
825
910
|
(0, response_dedup_1.settleStructuredHistoryRecheck)(pollerKey);
|
|
826
911
|
// Issue #2436: the turn is now the agent's own Markdown, so a
|
|
@@ -868,7 +953,10 @@ function recordOrHoldScrapedResponse(ctx, cleanedResponse, claudeMetadata, decis
|
|
|
868
953
|
// width and gutter-prefixed, so no content check could ever recognise them
|
|
869
954
|
// as the same reply.
|
|
870
955
|
if (holdScrapedHistory) {
|
|
871
|
-
(
|
|
956
|
+
// Issue #3663: refused (false) to a tick whose chain was retired while it
|
|
957
|
+
// awaited the reader — a stop, a stalled-tick restart or a worktree-ID
|
|
958
|
+
// migration. The store logs that, so this tick does not claim a hold.
|
|
959
|
+
const held = (0, pending_scraped_response_1.holdScrapedResponse)(pollerKey, {
|
|
872
960
|
worktreeId,
|
|
873
961
|
cliToolId,
|
|
874
962
|
instanceId: resolvedInstanceId,
|
|
@@ -884,19 +972,37 @@ function recordOrHoldScrapedResponse(ctx, cleanedResponse, claudeMetadata, decis
|
|
|
884
972
|
transcriptPathHint: claudeMetadata?.logFilePath ?? null,
|
|
885
973
|
expiresAt: Date.now() + pending_scraped_response_1.PENDING_SCRAPE_HOLD_MS,
|
|
886
974
|
});
|
|
887
|
-
|
|
975
|
+
if (held) {
|
|
976
|
+
logger.info('structured-history-scrape-held', {
|
|
977
|
+
worktreeId,
|
|
978
|
+
cliToolId,
|
|
979
|
+
instanceId: resolvedInstanceId,
|
|
980
|
+
scrapedLength: cleanedResponse.length,
|
|
981
|
+
holdMs: pending_scraped_response_1.PENDING_SCRAPE_HOLD_MS,
|
|
982
|
+
});
|
|
983
|
+
// The completion edge is announced HERE and not at the flush, because the
|
|
984
|
+
// turn finished now. A relay waiting on this session gets #2401's grace
|
|
985
|
+
// window to find a turn-keyed row, which is exactly the row the hold is
|
|
986
|
+
// waiting for; delaying the announcement by the hold would delay every
|
|
987
|
+
// delivery by it too. Issue #3684: only for a hold that was taken — a
|
|
988
|
+
// refused one is a retired tick, which announces nothing under the key
|
|
989
|
+
// it lost, as in the immediate-save branch below.
|
|
990
|
+
(0, relay_triggers_1.onRelayTurnCompleted)(worktreeId, cliToolId, resolvedInstanceId, false);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
else if (!suppressScrapedHistory && !(0, poller_owner_1.mayActForPollerKey)(pollerKey)) {
|
|
994
|
+
// Issue #3684: the same question the hold asks (#3663), for the reply saved
|
|
995
|
+
// at once — a tick retired while it awaited the reader or the log writes no
|
|
996
|
+
// row, broadcast or relay edge under the key it lost. No `await` between
|
|
997
|
+
// this check and the three below. Issue #3705: the caller now asks the
|
|
998
|
+
// same question for the rest of the tick's writes and the Markdown log for
|
|
999
|
+
// its own, so a retired tick reaches this branch only to be refused here.
|
|
1000
|
+
logger.info('scraped-response-save-refused', {
|
|
888
1001
|
worktreeId,
|
|
889
1002
|
cliToolId,
|
|
890
1003
|
instanceId: resolvedInstanceId,
|
|
891
|
-
|
|
892
|
-
holdMs: pending_scraped_response_1.PENDING_SCRAPE_HOLD_MS,
|
|
1004
|
+
generation: (0, poller_owner_1.currentPollerOwner)()?.generation,
|
|
893
1005
|
});
|
|
894
|
-
// The completion edge is announced HERE and not at the flush, because the
|
|
895
|
-
// turn finished now. A relay waiting on this session gets #2401's grace
|
|
896
|
-
// window to find a turn-keyed row, which is exactly the row the hold is
|
|
897
|
-
// waiting for; delaying the announcement by the hold would delay every
|
|
898
|
-
// delivery by it too.
|
|
899
|
-
(0, relay_triggers_1.onRelayTurnCompleted)(worktreeId, cliToolId, resolvedInstanceId, false);
|
|
900
1006
|
}
|
|
901
1007
|
else if (!suppressScrapedHistory) {
|
|
902
1008
|
// Create new CLI tool message in database
|
|
@@ -999,7 +1105,13 @@ async function recordCompletedResponse(ctx, turn, claudeMetadata, cleanedRespons
|
|
|
999
1105
|
// a return — so unless the fact is written down now, the ask never happens
|
|
1000
1106
|
// again. A `true` settles it: the turn is recorded and there is nothing left
|
|
1001
1107
|
// to re-ask about.
|
|
1002
|
-
|
|
1108
|
+
//
|
|
1109
|
+
// Issue #3705: by a tick that still owns the key. A retired one goes on to
|
|
1110
|
+
// the scrape decision below only so that the store's and the save branch's
|
|
1111
|
+
// own refusals (#3663, #3684) speak for it; nothing else it would write does.
|
|
1112
|
+
if (mayStillActAfter(ctx, 'reader')) {
|
|
1113
|
+
markOrSettleStructuredHistoryRecheck(pollerKey, structuredHistoryLive);
|
|
1114
|
+
}
|
|
1003
1115
|
// Issue #2317 Phase D: the scrape is dropped while the geometry is
|
|
1004
1116
|
// delegated, and the transcript capture above is what makes that safe.
|
|
1005
1117
|
//
|
|
@@ -1030,8 +1142,29 @@ async function recordCompletedResponse(ctx, turn, claudeMetadata, cleanedRespons
|
|
|
1030
1142
|
// out. Only the two writes that RECORD THE REPLY wait.
|
|
1031
1143
|
const holdScrapedHistory = !suppressScrapedHistory && captureReport.outcome === 'not_yet_closed';
|
|
1032
1144
|
// Create Markdown log file for the conversation pair
|
|
1145
|
+
//
|
|
1146
|
+
// Issue #3705: keyed, so the log asks before its own write (after its own
|
|
1147
|
+
// awaits) whether this tick still owns the key. A held reply confirmed by a
|
|
1148
|
+
// stop is logged by the store with no key (`pending-scraped-response`), and
|
|
1149
|
+
// that log is kept.
|
|
1033
1150
|
if (cleanedResponse && !suppressScrapedHistory && !holdScrapedHistory) {
|
|
1034
|
-
await (0, conversation_logger_1.recordClaudeConversation)(db, worktreeId, cleanedResponse, cliToolId);
|
|
1151
|
+
await (0, conversation_logger_1.recordClaudeConversation)(db, worktreeId, cleanedResponse, cliToolId, { pollerKey });
|
|
1152
|
+
}
|
|
1153
|
+
// Issue #3705: everything from here to the end of the function runs without
|
|
1154
|
+
// an `await`, so this is the tick's last chance to find out that it was
|
|
1155
|
+
// retired while the reader or the log ran. A retired tick sweeps no prompt to
|
|
1156
|
+
// "answered", closes no waiting episode, sends no completion push and moves
|
|
1157
|
+
// no cursor under the key it lost — the successor's, possibly. The scrape
|
|
1158
|
+
// decision still runs: every branch of it asks the same question itself
|
|
1159
|
+
// (#3663 the hold, #3684 the immediate save, the store the discard), and its
|
|
1160
|
+
// refusal lines are what the earlier suites read.
|
|
1161
|
+
if (!mayStillActAfter(ctx, 'conversation-log')) {
|
|
1162
|
+
recordOrHoldScrapedResponse(ctx, cleanedResponse, claudeMetadata, {
|
|
1163
|
+
structuredHistoryLive,
|
|
1164
|
+
suppressScrapedHistory,
|
|
1165
|
+
holdScrapedHistory,
|
|
1166
|
+
});
|
|
1167
|
+
return false;
|
|
1035
1168
|
}
|
|
1036
1169
|
// Mark any pending prompts as answered. Intended twin of the sweep in
|
|
1037
1170
|
// extractCompletedTurn (working visible on an unfinished frame); this one runs
|
|
@@ -1103,8 +1236,23 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1103
1236
|
(0, response_poller_core_1.stopPolling)(worktreeId, cliToolId, instanceId);
|
|
1104
1237
|
return false;
|
|
1105
1238
|
}
|
|
1239
|
+
const pollerKey = (0, response_poller_core_1.getPollerKey)(worktreeId, cliToolId, instanceId);
|
|
1240
|
+
// Issue #3213: what the steps split out of this function are keyed by.
|
|
1241
|
+
const ctx = {
|
|
1242
|
+
db,
|
|
1243
|
+
worktree,
|
|
1244
|
+
worktreeId,
|
|
1245
|
+
cliToolId,
|
|
1246
|
+
instanceId,
|
|
1247
|
+
resolvedInstanceId,
|
|
1248
|
+
pollerKey,
|
|
1249
|
+
};
|
|
1106
1250
|
// Check if CLI tool session is running
|
|
1107
1251
|
const running = await (0, cli_session_1.isSessionRunning)(worktreeId, cliToolId, instanceId);
|
|
1252
|
+
// Issue #3705: the first of the tick's awaits. Every one of them is followed
|
|
1253
|
+
// by the same question; see `mayStillActAfter`.
|
|
1254
|
+
if (!mayStillActAfter(ctx, 'session-check'))
|
|
1255
|
+
return false;
|
|
1108
1256
|
if (!running) {
|
|
1109
1257
|
logger.info('session-not-running');
|
|
1110
1258
|
// `stopPolling` is what confirms a held scrape here; see
|
|
@@ -1116,23 +1264,14 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1116
1264
|
(0, response_poller_core_1.stopPolling)(worktreeId, cliToolId, instanceId);
|
|
1117
1265
|
return false;
|
|
1118
1266
|
}
|
|
1119
|
-
const pollerKey = (0, response_poller_core_1.getPollerKey)(worktreeId, cliToolId, instanceId);
|
|
1120
|
-
// Issue #3213: what the steps split out of this function are keyed by.
|
|
1121
|
-
const ctx = {
|
|
1122
|
-
db,
|
|
1123
|
-
worktree,
|
|
1124
|
-
worktreeId,
|
|
1125
|
-
cliToolId,
|
|
1126
|
-
instanceId,
|
|
1127
|
-
resolvedInstanceId,
|
|
1128
|
-
pollerKey,
|
|
1129
|
-
};
|
|
1130
1267
|
// Issue #2436: a scrape held by an earlier tick, whose transcript has now
|
|
1131
1268
|
// had its whole budget to close. Ahead of everything below because most
|
|
1132
1269
|
// ticks of a finished turn never reach the save path — a static frame is a
|
|
1133
1270
|
// duplicate for an alternate-screen tool and yields no new lines for a
|
|
1134
1271
|
// scrollback one, and both of those return early.
|
|
1135
1272
|
await (0, pending_scraped_response_1.settleExpiredPendingScrapedResponse)(pollerKey);
|
|
1273
|
+
if (!mayStillActAfter(ctx, 'pending-scrape-settle'))
|
|
1274
|
+
return false;
|
|
1136
1275
|
// Issue #2317 Phase D: is a human reading this pane at their own terminal
|
|
1137
1276
|
// size right now, and did they just stop?
|
|
1138
1277
|
//
|
|
@@ -1144,6 +1283,8 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1144
1283
|
const delegation = (0, tmux_session_surface_1.isLiveAttachEligibleSession)(sessionName)
|
|
1145
1284
|
? await (0, geometry_delegation_1.probeGeometryDelegation)(sessionName)
|
|
1146
1285
|
: { delegated: false, released: false };
|
|
1286
|
+
if (!mayStillActAfter(ctx, 'geometry-probe'))
|
|
1287
|
+
return false;
|
|
1147
1288
|
if (delegation.released) {
|
|
1148
1289
|
// The canvas is 1000 rows again, so a cursor recorded against a 44-row
|
|
1149
1290
|
// frame indexes into a pane that no longer exists. Zero is the only value
|
|
@@ -1170,7 +1311,16 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1170
1311
|
// taken from the same constant extractResponse() measures saturation against
|
|
1171
1312
|
// (Issue #1670) — a literal here would silently decouple the two.
|
|
1172
1313
|
const output = await (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, tmux_capture_cache_1.CACHE_MAX_CAPTURE_LINES, instanceId);
|
|
1173
|
-
|
|
1314
|
+
// Issue #3705: there is no `await` from here to the transcript reader
|
|
1315
|
+
// inside the save path, so this one answer covers every write in between —
|
|
1316
|
+
// the fault notifier, the TUI accumulator, the prompt sweep, the skip
|
|
1317
|
+
// streaks, the cursor, the in-progress id. A retired tick still READS the
|
|
1318
|
+
// frame and goes on, because the writes that already ask for themselves
|
|
1319
|
+
// (the prompt row #3701, the response hash #3663, the reader and the
|
|
1320
|
+
// scrape decision) are where its refusal is recorded; it writes none of
|
|
1321
|
+
// the rest.
|
|
1322
|
+
const owns = mayStillActAfter(ctx, 'capture');
|
|
1323
|
+
const turn = extractCompletedTurn(ctx, output, lastCapturedLine, owns);
|
|
1174
1324
|
if (!turn) {
|
|
1175
1325
|
return false;
|
|
1176
1326
|
}
|
|
@@ -1197,29 +1347,38 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1197
1347
|
// Issue #3552: a live prompt is not the saved reply, so a run of
|
|
1198
1348
|
// duplicate response ticks is over; the response hash is kept (a resume
|
|
1199
1349
|
// after the answer must not re-save the reply underneath, #2230).
|
|
1200
|
-
|
|
1350
|
+
if (owns)
|
|
1351
|
+
(0, response_dedup_1.resetDuplicateResponseSkipStreak)(pollerKey);
|
|
1352
|
+
// Asks for itself (#3701), before the prompt dedup.
|
|
1201
1353
|
return savePromptMessage(ctx, promptDetection, result, isFullScreenTui);
|
|
1202
1354
|
}
|
|
1203
1355
|
// Issue #3538: a finished frame without a live prompt ends the run of
|
|
1204
1356
|
// duplicate prompt ticks, as an unfinished one does in `extractCompletedTurn`.
|
|
1205
|
-
|
|
1357
|
+
if (owns)
|
|
1358
|
+
(0, prompt_dedup_1.resetDuplicatePromptSkipStreak)(pollerKey);
|
|
1206
1359
|
// Validate response content is not empty
|
|
1207
1360
|
if (!result.response || result.response.trim() === '') {
|
|
1208
1361
|
// Issue #3552: an empty response is not the saved reply either.
|
|
1209
|
-
|
|
1210
|
-
|
|
1362
|
+
if (owns) {
|
|
1363
|
+
(0, response_dedup_1.resetDuplicateResponseSkipStreak)(pollerKey);
|
|
1364
|
+
(0, db_1.updateSessionState)(db, worktreeId, cliToolId, result.lineCount, resolvedInstanceId);
|
|
1365
|
+
}
|
|
1211
1366
|
return false;
|
|
1212
1367
|
}
|
|
1213
1368
|
// Parse Claude-specific metadata
|
|
1214
1369
|
const claudeMetadata = cliToolId === 'claude'
|
|
1215
1370
|
? (0, claude_output_1.parseClaudeOutput)(result.response)
|
|
1216
1371
|
: undefined;
|
|
1217
|
-
const cleanedResponse = cleanCompletedResponse(cliToolId, result, pollerKey);
|
|
1372
|
+
const cleanedResponse = cleanCompletedResponse(cliToolId, result, pollerKey, owns);
|
|
1218
1373
|
// If cleaned response is empty or just "[No content]", skip saving
|
|
1219
1374
|
if (!cleanedResponse || cleanedResponse.trim() === '' || cleanedResponse === '[No content]') {
|
|
1220
1375
|
// Issue #3552: nor is one that cleans down to nothing.
|
|
1221
|
-
|
|
1222
|
-
|
|
1376
|
+
if (owns) {
|
|
1377
|
+
(0, response_dedup_1.resetDuplicateResponseSkipStreak)(pollerKey);
|
|
1378
|
+
(0, db_1.updateSessionState)(db, worktreeId, cliToolId, result.lineCount, resolvedInstanceId);
|
|
1379
|
+
}
|
|
1380
|
+
// Left as it was (Issue #3705 sets it aside as harmless): nothing sets the
|
|
1381
|
+
// in-progress id to a non-null value or reads it today.
|
|
1223
1382
|
(0, db_1.clearInProgressMessageId)(db, worktreeId, cliToolId, resolvedInstanceId);
|
|
1224
1383
|
return false;
|
|
1225
1384
|
}
|
|
@@ -1234,6 +1393,10 @@ async function checkForResponse(worktreeId, cliToolId, instanceId) {
|
|
|
1234
1393
|
// Without this the disabled cursor would leave nothing suppressing re-saves and
|
|
1235
1394
|
// the poller would append the same finished reply every 2 s.
|
|
1236
1395
|
if (!lineCountIsCursor) {
|
|
1396
|
+
// A retired tick registers no hash here (#3663, `./response-dedup`), but
|
|
1397
|
+
// it can still MATCH one — the successor's, for the same reply. The
|
|
1398
|
+
// recheck below therefore opens on the ownership question itself before
|
|
1399
|
+
// its claim, its cursor and its read (Issue #3705 review).
|
|
1237
1400
|
if ((0, response_dedup_1.isDuplicateResponse)(pollerKey, cleanedResponse)) {
|
|
1238
1401
|
// `await`, so that a rejection still lands in the catch below.
|
|
1239
1402
|
return await recheckDuplicateResponse(ctx, result, claudeMetadata);
|
|
@@ -64,6 +64,7 @@ exports.renameResponseHashCacheKey = renameResponseHashCacheKey;
|
|
|
64
64
|
exports.renameResponseHashCacheKeys = renameResponseHashCacheKeys;
|
|
65
65
|
const crypto_1 = require("crypto");
|
|
66
66
|
const global_state_1 = require("../global-state");
|
|
67
|
+
const poller_owner_1 = require("./poller-owner");
|
|
67
68
|
const responseHashCache = (0, global_state_1.getOrInitGlobal)('__responseHashCache', () => new Map());
|
|
68
69
|
/**
|
|
69
70
|
* In-memory cache: pollerKey -> ticks still to wait before the transcript reader
|
|
@@ -127,6 +128,13 @@ function isDuplicateResponse(pollerKey, content) {
|
|
|
127
128
|
if (responseHashCache.get(pollerKey) === hash) {
|
|
128
129
|
return true;
|
|
129
130
|
}
|
|
131
|
+
// Issue #3663: a tick of a stopped chain no longer owns its key, so it does
|
|
132
|
+
// not register a hash there — the same line the held scrape draws. Left
|
|
133
|
+
// behind, the hash of a reply that tick never saves (its hold is refused)
|
|
134
|
+
// would be inherited by the next chain on the key, or moved by a migration,
|
|
135
|
+
// and make the successor skip it.
|
|
136
|
+
if (!(0, poller_owner_1.mayActForPollerKey)(pollerKey))
|
|
137
|
+
return false;
|
|
130
138
|
responseHashCache.set(pollerKey, hash);
|
|
131
139
|
// Issue #3519: a new response starts a new run of duplicate ticks.
|
|
132
140
|
duplicateResponseSkipStreak.delete(pollerKey);
|