commandmate 0.49.1 → 0.49.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +128 -132
- package/.next/app-path-routes-manifest.json +22 -22
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +2 -2
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/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.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.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.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.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.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.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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 +2 -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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +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 +2 -2
- package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +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.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.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.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.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +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 +2 -2
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js.nft.json +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.js.nft.json +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.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.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.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.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 +2 -2
- 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 +22 -22
- package/.next/server/chunks/1062.js +1 -0
- package/.next/server/chunks/110.js +1 -0
- package/.next/server/chunks/1501.js +5 -4
- package/.next/server/chunks/1656.js +2 -2
- package/.next/server/chunks/1957.js +2 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2897.js +1 -0
- package/.next/server/chunks/3417.js +1 -0
- package/.next/server/chunks/3505.js +1 -1
- package/.next/server/chunks/3756.js +1 -0
- package/.next/server/chunks/3801.js +3 -3
- package/.next/server/chunks/4911.js +1 -0
- package/.next/server/chunks/4936.js +1 -0
- package/.next/server/chunks/5209.js +2 -1
- package/.next/server/chunks/5354.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6401.js +1 -1
- package/.next/server/chunks/7023.js +2 -2
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8581.js +15 -15
- package/.next/server/chunks/8728.js +2 -2
- package/.next/server/chunks/8782.js +1 -1
- package/.next/server/chunks/9390.js +1 -1
- package/.next/server/chunks/9584.js +1 -1
- 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/{2407-675ba6b21844dc3b.js → 2407-07a237575e1ceb9e.js} +1 -1
- package/.next/static/chunks/3931-61ad1a4fc0208d0e.js +1 -0
- package/.next/static/chunks/5794-7975b8e51e731b19.js +1 -0
- package/.next/static/chunks/6966-d8dc6032410ffaba.js +1 -0
- package/.next/static/chunks/7197-ed3b3d99ac3bd450.js +1 -0
- package/.next/static/chunks/7636-a48cf0f7110250c5.js +1 -0
- package/.next/static/chunks/app/layout-4f64316957b0a8e5.js +1 -0
- package/.next/static/chunks/app/more/page-ff5af5ca48774c89.js +1 -0
- package/.next/static/chunks/app/page-b4863bfe0452e09d.js +1 -0
- package/.next/static/chunks/app/review/page-ff3efb96fdf9bb4b.js +1 -0
- package/.next/static/chunks/app/sessions/{page-890fd50ec9739973.js → page-c6eb7c02db2f4c80.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/{page-f6d3ab8185d93aae.js → page-33afc6aa96289fb0.js} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/ask.d.ts.map +1 -1
- package/dist/cli/commands/ask.js +56 -5
- package/dist/cli/commands/attach.d.ts +4 -1
- package/dist/cli/commands/attach.d.ts.map +1 -1
- package/dist/cli/commands/attach.js +19 -7
- package/dist/cli/commands/command-target.d.ts +7 -0
- package/dist/cli/commands/command-target.d.ts.map +1 -1
- package/dist/cli/commands/command-target.js +10 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +38 -2
- package/dist/cli/commands/message-dispatch.d.ts +17 -3
- package/dist/cli/commands/message-dispatch.d.ts.map +1 -1
- package/dist/cli/commands/message-dispatch.js +14 -8
- package/dist/cli/commands/relays.d.ts +2 -1
- package/dist/cli/commands/relays.d.ts.map +1 -1
- package/dist/cli/commands/relays.js +4 -3
- package/dist/cli/commands/respond-strict.d.ts.map +1 -1
- package/dist/cli/commands/respond-strict.js +22 -5
- package/dist/cli/commands/respond.d.ts +2 -2
- package/dist/cli/commands/respond.d.ts.map +1 -1
- package/dist/cli/commands/respond.js +40 -37
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +8 -4
- package/dist/cli/commands/wait-instance.d.ts +9 -1
- package/dist/cli/commands/wait-instance.d.ts.map +1 -1
- package/dist/cli/commands/wait-instance.js +15 -0
- package/dist/cli/commands/wait-poll-state.d.ts +18 -0
- package/dist/cli/commands/wait-poll-state.d.ts.map +1 -1
- package/dist/cli/commands/wait-verify.d.ts +2 -1
- package/dist/cli/commands/wait-verify.d.ts.map +1 -1
- package/dist/cli/commands/wait-verify.js +5 -1
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +37 -13
- package/dist/cli/commands/whoami.d.ts.map +1 -1
- package/dist/cli/commands/whoami.js +3 -1
- package/dist/cli/docs/agent-operations.d.ts +1 -1
- package/dist/cli/docs/agent-operations.d.ts.map +1 -1
- package/dist/cli/docs/agent-operations.js +1 -0
- package/dist/cli/types/api-responses.d.ts +3 -1
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/cli/utils/api-client.d.ts +55 -1
- package/dist/cli/utils/api-client.d.ts.map +1 -1
- package/dist/cli/utils/api-client.js +220 -18
- package/dist/cli/utils/follow-up-command.d.ts +38 -0
- package/dist/cli/utils/follow-up-command.d.ts.map +1 -0
- package/dist/cli/utils/follow-up-command.js +57 -0
- package/dist/cli/utils/reply-ledger.d.ts +1 -1
- package/dist/cli/utils/reply-ledger.d.ts.map +1 -1
- package/dist/cli/utils/reply-ledger.js +7 -2
- package/dist/cli/utils/server-capabilities.d.ts +18 -0
- package/dist/cli/utils/server-capabilities.d.ts.map +1 -1
- package/dist/cli/utils/server-capabilities.js +36 -3
- package/dist/cli/utils/session-target.d.ts +1 -1
- package/dist/cli/utils/session-target.d.ts.map +1 -1
- package/dist/cli/utils/session-target.js +3 -0
- package/dist/cli/utils/verify-runner.d.ts +7 -0
- package/dist/cli/utils/verify-runner.d.ts.map +1 -1
- package/dist/cli/utils/verify-runner.js +51 -15
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -1
- package/dist/lib/cli-tools/session-name.js +11 -3
- package/dist/lib/session/send-attempt-types.d.ts +25 -0
- package/dist/lib/session/send-attempt-types.d.ts.map +1 -1
- package/dist/lib/session/send-attempt-types.js +10 -1
- package/dist/lib/verification/session-kill-ledger.d.ts +110 -0
- package/dist/lib/verification/session-kill-ledger.d.ts.map +1 -0
- package/dist/lib/verification/session-kill-ledger.js +174 -0
- package/dist/server/locales/en/worktree.json +2 -0
- package/dist/server/locales/ja/worktree.json +2 -0
- package/dist/server/src/config/cli-tool-timing-config.js +1 -7
- package/dist/server/src/lib/auto-yes-poller.js +5 -1
- package/dist/server/src/lib/cli-tools/antigravity.js +5 -2
- package/dist/server/src/lib/cli-tools/base.js +39 -0
- package/dist/server/src/lib/cli-tools/codex.js +7 -4
- package/dist/server/src/lib/cli-tools/command-code.js +7 -3
- package/dist/server/src/lib/cli-tools/copilot.js +5 -3
- package/dist/server/src/lib/cli-tools/gemini.js +10 -2
- package/dist/server/src/lib/cli-tools/launch-keys.js +39 -0
- package/dist/server/src/lib/cli-tools/opencode-v2.js +6 -2
- package/dist/server/src/lib/cli-tools/opencode.js +5 -2
- package/dist/server/src/lib/cli-tools/session-name.js +11 -3
- package/dist/server/src/lib/cli-tools/submit-composer-read.js +16 -6
- package/dist/server/src/lib/cli-tools/submit-verified-sender.js +164 -7
- package/dist/server/src/lib/cli-tools/vibe-local.js +4 -2
- package/dist/server/src/lib/db/db-migration-path.js +63 -2
- package/dist/server/src/lib/detection/prompt-detect-multiple-choice.js +5 -4
- package/dist/server/src/lib/hooks/sources/copilot/hook-settings.js +2 -3
- package/dist/server/src/lib/prompt-answer-errors.js +76 -2
- package/dist/server/src/lib/session/agent-event-state.js +4 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +6 -1
- package/dist/server/src/lib/session/claude-session.js +22 -6
- package/dist/server/src/lib/session/current-output-builder.js +5 -3
- package/dist/server/src/lib/session/current-output-history-writers.js +1 -1
- package/dist/server/src/lib/session/prompt-submit-receipt.js +155 -0
- package/dist/server/src/lib/session/prompt-waiting-guard.js +10 -3
- package/dist/server/src/lib/session/send-attempt-state.js +48 -0
- package/dist/server/src/lib/session/send-attempt-types.js +10 -1
- package/dist/server/src/lib/session/send-user-message.js +5 -4
- package/dist/server/src/lib/session/session-launch-flight.js +243 -0
- package/dist/server/src/lib/session/session-starting-state.js +40 -4
- package/dist/server/src/lib/session/structured-prompt.js +12 -9
- package/dist/server/src/lib/session/waiting-episode-binding.js +4 -2
- package/dist/server/src/lib/session-cleanup.js +32 -0
- package/dist/server/src/lib/session-key-sender.js +0 -27
- package/dist/server/src/lib/verification/env-clean-gate.js +129 -0
- package/dist/server/src/lib/verification/env-snapshot.js +11 -2
- package/dist/server/src/lib/verification/session-kill-ledger.js +174 -0
- package/package.json +5 -1
- package/release-notes/0.49.2.json +49 -0
- package/.next/server/chunks/3773.js +0 -1
- package/.next/server/chunks/5775.js +0 -1
- package/.next/server/chunks/7604.js +0 -2
- package/.next/static/chunks/3931-1a1abab16248f14d.js +0 -1
- package/.next/static/chunks/4768-ad6f82f034f21eae.js +0 -1
- package/.next/static/chunks/5794-80ac3f06f098ea29.js +0 -1
- package/.next/static/chunks/6654-f3534f35f16644bc.js +0 -1
- package/.next/static/chunks/7665-e9ef6e0a85b9fa49.js +0 -1
- package/.next/static/chunks/8606-ce17ffa77f39608e.js +0 -1
- package/.next/static/chunks/app/layout-8bfac4724277b47f.js +0 -1
- package/.next/static/chunks/app/more/page-87c84987b2765213.js +0 -1
- package/.next/static/chunks/app/page-1b820c421db48c2c.js +0 -1
- package/.next/static/chunks/app/review/page-e2fd4a590646a2d8.js +0 -1
- /package/.next/static/{fqfSDqQMweROeHUzOt_m1 → yGatWDsS532awSs51kXyd}/_buildManifest.js +0 -0
- /package/.next/static/{fqfSDqQMweROeHUzOt_m1 → yGatWDsS532awSs51kXyd}/_ssgManifest.js +0 -0
|
@@ -92,7 +92,8 @@ class VibeLocalTool extends base_1.BaseCLITool {
|
|
|
92
92
|
}
|
|
93
93
|
// Start vibe-local in interactive mode with auto-approve (-y)
|
|
94
94
|
// -y flag skips the permission confirmation prompt
|
|
95
|
-
|
|
95
|
+
// Issue #3981: in one writer's turn of the input lock.
|
|
96
|
+
await this.typeLaunchLines(sessionName, [(0, launch_screen_1.withLaunchScreenCleared)(vibeLocalCommand)]);
|
|
96
97
|
// Wait for vibe-local to initialize (banner + model loading)
|
|
97
98
|
await new Promise((resolve) => setTimeout(resolve, VIBE_LOCAL_INIT_WAIT_MS));
|
|
98
99
|
logger.info('started-vibe-local-session');
|
|
@@ -137,7 +138,8 @@ class VibeLocalTool extends base_1.BaseCLITool {
|
|
|
137
138
|
}
|
|
138
139
|
catch (error) {
|
|
139
140
|
const errorMessage = (0, errors_1.getErrorMessage)(error);
|
|
140
|
-
|
|
141
|
+
// Issue #4031: the cause keeps a failed `load-buffer`'s code (`classifySendFailure`).
|
|
142
|
+
throw new Error(`Failed to send message to Vibe Local: ${errorMessage}`, { cause: error });
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
/**
|
|
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.resolveAndValidatePath = resolveAndValidatePath;
|
|
16
16
|
exports.getLegacyDbPaths = getLegacyDbPaths;
|
|
17
17
|
exports.migrateDbIfNeeded = migrateDbIfNeeded;
|
|
18
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
19
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
18
20
|
const fs_1 = __importDefault(require("fs"));
|
|
19
21
|
const path_1 = __importDefault(require("path"));
|
|
20
22
|
const os_1 = require("os");
|
|
@@ -83,6 +85,61 @@ function getLegacyDbPaths() {
|
|
|
83
85
|
}
|
|
84
86
|
return paths;
|
|
85
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Whether committed updates of `dbPath` may still live only in its `-wal` file.
|
|
90
|
+
*
|
|
91
|
+
* An empty or absent `-wal` means the main file is the whole database.
|
|
92
|
+
*/
|
|
93
|
+
function hasPendingWal(dbPath) {
|
|
94
|
+
try {
|
|
95
|
+
return fs_1.default.statSync(`${dbPath}-wal`).size > 0;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Write a self-contained copy of the database at `sourcePath` to `destPath`
|
|
103
|
+
* (Issue #3993).
|
|
104
|
+
*
|
|
105
|
+
* Same tool as the pre-migration backup (`migrations/pre-migration-backup.ts`,
|
|
106
|
+
* Issue #3985): `VACUUM INTO` reads inside one read transaction, so updates
|
|
107
|
+
* still in `-wal` are included, and the result is a rollback-journal file that
|
|
108
|
+
* needs no sidecar. Copying the main file alone dropped them. The source is
|
|
109
|
+
* opened read-only; the copy is written to a temporary name and renamed into
|
|
110
|
+
* place, because `VACUUM INTO` refuses a non-empty destination.
|
|
111
|
+
*/
|
|
112
|
+
function snapshotDatabase(sourcePath, destPath) {
|
|
113
|
+
const tempPath = `${destPath}.${crypto_1.default.randomBytes(4).toString('hex')}.partial`;
|
|
114
|
+
try {
|
|
115
|
+
// VACUUM INTO accepts an empty existing file; creating it first fixes the mode.
|
|
116
|
+
fs_1.default.closeSync(fs_1.default.openSync(tempPath, 'wx', 0o600));
|
|
117
|
+
const source = new better_sqlite3_1.default(sourcePath, { readonly: true, fileMustExist: true });
|
|
118
|
+
try {
|
|
119
|
+
source.prepare('VACUUM INTO ?').run(tempPath);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
source.close();
|
|
123
|
+
}
|
|
124
|
+
fs_1.default.renameSync(tempPath, destPath);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
fs_1.default.rmSync(tempPath, { force: true });
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Copy a legacy database: a consistent snapshot when it has a non-empty `-wal`,
|
|
133
|
+
* the file itself otherwise (unchanged from before Issue #3993).
|
|
134
|
+
*/
|
|
135
|
+
function copyLegacyDatabase(sourcePath, destPath) {
|
|
136
|
+
if (hasPendingWal(sourcePath)) {
|
|
137
|
+
snapshotDatabase(sourcePath, destPath);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
fs_1.default.copyFileSync(sourcePath, destPath);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
86
143
|
/**
|
|
87
144
|
* Migrate database to new path if legacy DB exists
|
|
88
145
|
*
|
|
@@ -92,6 +149,10 @@ function getLegacyDbPaths() {
|
|
|
92
149
|
* 3. Creates a backup of the legacy database
|
|
93
150
|
* 4. Copies the database to the new location
|
|
94
151
|
*
|
|
152
|
+
* A legacy database with a non-empty `-wal` is copied as a `VACUUM INTO`
|
|
153
|
+
* snapshot (both the backup and the new location), so updates not yet written
|
|
154
|
+
* back to the main file are kept (Issue #3993).
|
|
155
|
+
*
|
|
95
156
|
* Security features:
|
|
96
157
|
* - SEC-002: Symlink resolution via realpathSync
|
|
97
158
|
* - SEC-003: Directory creation with mode 0o700
|
|
@@ -125,7 +186,7 @@ function migrateDbIfNeeded(targetPath) {
|
|
|
125
186
|
}
|
|
126
187
|
// Create backup (SEC-006)
|
|
127
188
|
const backupPath = `${resolvedLegacyPath}.bak`;
|
|
128
|
-
|
|
189
|
+
copyLegacyDatabase(resolvedLegacyPath, backupPath);
|
|
129
190
|
fs_1.default.chmodSync(backupPath, 0o600);
|
|
130
191
|
// Create target directory if needed (SEC-003)
|
|
131
192
|
const targetDir = path_1.default.dirname(resolvedTargetPath);
|
|
@@ -133,7 +194,7 @@ function migrateDbIfNeeded(targetPath) {
|
|
|
133
194
|
fs_1.default.mkdirSync(targetDir, { recursive: true, mode: 0o700 });
|
|
134
195
|
}
|
|
135
196
|
// Copy database to new location
|
|
136
|
-
|
|
197
|
+
copyLegacyDatabase(resolvedLegacyPath, resolvedTargetPath);
|
|
137
198
|
logger.info(`[Migration] Database migrated from ${resolvedLegacyPath} to ${resolvedTargetPath}`);
|
|
138
199
|
logger.info(`[Migration] Backup created at ${backupPath}`);
|
|
139
200
|
return {
|
|
@@ -753,7 +753,7 @@ function detectMultipleChoicePrompt(output, options, truncateRawContentFn) {
|
|
|
753
753
|
// Issue #1699: the same block, cut at the previous turn's boundary. Display
|
|
754
754
|
// keeps the wide window; deny patterns are judged against this one.
|
|
755
755
|
const approvalBlock = extractApprovalTarget(lines, questionEndIndex, effectiveEnd, pickerTop);
|
|
756
|
-
// Issue #616: Determine submitMode from confirmation footer (detected in single-pass
|
|
756
|
+
// Issue #616: Determine submitMode from confirmation footer (detected in single-pass by findConfirmationFooter())
|
|
757
757
|
const submitMode = hasConfirmationFooter
|
|
758
758
|
? (hasNumberFooter ? 'answer_only' : 'answer_then_enter')
|
|
759
759
|
: undefined;
|
|
@@ -808,7 +808,7 @@ function hasModelOverlayFooter(scanWindow) {
|
|
|
808
808
|
// [Issue #1495] Claude `/model` local-settings overlay guard.
|
|
809
809
|
// The `/model` overlay renders a ❯-marked numbered model list ("1. Default …
|
|
810
810
|
// 5. Haiku") under a "Select model" header, which the option-collection logic
|
|
811
|
-
//
|
|
811
|
+
// (collectOptions()) would otherwise return as a genuine multiple_choice prompt. Auto-Yes
|
|
812
812
|
// (detectAndRespondToPrompt) calls detectPrompt() directly and would resolve +
|
|
813
813
|
// Enter-confirm the default option — silently changing the user's default model.
|
|
814
814
|
// The overlay-unique "Enter to set as default …" footer never appears in real
|
|
@@ -948,10 +948,11 @@ function isMetadataRow(state, rawLine, line, paneCut) {
|
|
|
948
948
|
// would then poison isValidPrecedingOption() and cause every real option
|
|
949
949
|
// above (1./2./3.) to be rejected — resulting in collectedOptions.length<2
|
|
950
950
|
// and a spurious no_prompt verdict. Treat the summary line as metadata
|
|
951
|
-
// (same continuation handling as COLLAPSED_OUTPUT_PATTERN
|
|
951
|
+
// (same continuation handling as the COLLAPSED_OUTPUT_PATTERN check earlier
|
|
952
|
+
// in isMetadataRow()) so the
|
|
952
953
|
// reverse scan continues into the actual option block.
|
|
953
954
|
//
|
|
954
|
-
// Defense-in-depth: works alongside the S2 effectiveEnd trim
|
|
955
|
+
// Defense-in-depth: works alongside the S2 effectiveEnd trim in findScanWindow(). Either
|
|
955
956
|
// S1 or S2 alone is sufficient to fix Issue #704; keeping both protects
|
|
956
957
|
// against future Claude renderings where the footer line text changes
|
|
957
958
|
// (S1 still catches) or the summary line wording changes (S2 still
|
|
@@ -868,9 +868,8 @@ function writeCopilotHookSettings(options = {}) {
|
|
|
868
868
|
*
|
|
869
869
|
* Applied to the launched process rather than through `tmux set-environment`:
|
|
870
870
|
* the pane is created before the agent starts and the assignment then travels
|
|
871
|
-
* with the one process that matters, out of reach of
|
|
872
|
-
*
|
|
873
|
-
* environment later.
|
|
871
|
+
* with the one process that matters, out of reach of anything that edits
|
|
872
|
+
* the session's environment later (claude's `unset CLAUDECODE` among them).
|
|
874
873
|
*
|
|
875
874
|
* Returned as a map since Issue #1846. It used to be a pre-quoted
|
|
876
875
|
* `NAME=value NAME=value` string that the caller concatenated in front of the
|
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* The refusals and failures `prompt-answer-sender` throws, with the reason
|
|
4
4
|
* codes they carry (Issue #3965: moved out of `prompt-answer-sender`, which
|
|
5
|
-
* re-exports every
|
|
5
|
+
* re-exports every error and reason code here, so callers keep importing from it).
|
|
6
|
+
*
|
|
7
|
+
* Issue #3982: also how each of them is answered over HTTP
|
|
8
|
+
* ({@link promptAnswerErrorResponse}), in one table both answering routes read.
|
|
9
|
+
* That mapping is imported from this module directly.
|
|
6
10
|
*
|
|
7
11
|
* Type-only imports: this module must not import the sender back.
|
|
8
12
|
*/
|
|
9
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.PromptAnswerAbortedError = exports.PromptAnswerInputLostError = exports.ANSWER_INPUT_LOST_REASON = exports.PromptAnswerNotDeliveredError = exports.ANSWER_NOT_DELIVERED_REASON = exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
|
|
14
|
+
exports.PROMPT_ANSWER_ERROR_RESPONSES = exports.PromptAnswerAbortedError = exports.ANSWER_ABORTED_REASON = exports.PromptAnswerInputLostError = exports.ANSWER_INPUT_LOST_REASON = exports.PromptAnswerNotDeliveredError = exports.ANSWER_NOT_DELIVERED_REASON = exports.MultiSelectAnswerRejectedError = exports.MULTI_SELECT_NOT_COMMITTED_REASON = exports.FreeTextAtChoiceOnlyPromptError = exports.FreeTextAnswerRejectedError = exports.FREE_TEXT_AT_MENU_ROW_REASON = exports.PromptAnswerRejectedError = exports.ANSWER_MODE_KEYS_REASON = void 0;
|
|
15
|
+
exports.promptAnswerErrorResponse = promptAnswerErrorResponse;
|
|
11
16
|
/**
|
|
12
17
|
* The reason code a caller gets back when a digit meets a `keys`-mode dialog
|
|
13
18
|
* (Issue #2033).
|
|
@@ -269,6 +274,12 @@ class PromptAnswerInputLostError extends Error {
|
|
|
269
274
|
}
|
|
270
275
|
}
|
|
271
276
|
exports.PromptAnswerInputLostError = PromptAnswerInputLostError;
|
|
277
|
+
/**
|
|
278
|
+
* The reason code of {@link PromptAnswerAbortedError} on the wire (Issue #3982).
|
|
279
|
+
* Neither answering route passes a `stillCurrent`, so neither is expected to
|
|
280
|
+
* see one; it has a code so that the mapping below has no hole.
|
|
281
|
+
*/
|
|
282
|
+
exports.ANSWER_ABORTED_REASON = 'answer_aborted';
|
|
272
283
|
/**
|
|
273
284
|
* The caller's `stillCurrent` said no after one of the send's waits
|
|
274
285
|
* (Issue #3706): the keys not yet sent were not sent. Keys already typed cannot
|
|
@@ -286,3 +297,66 @@ class PromptAnswerAbortedError extends Error {
|
|
|
286
297
|
}
|
|
287
298
|
}
|
|
288
299
|
exports.PromptAnswerAbortedError = PromptAnswerAbortedError;
|
|
300
|
+
function row(errorClass, facts, status) {
|
|
301
|
+
return [errorClass, { facts: facts, status }];
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Every error class this module exports, and how each route answers it
|
|
305
|
+
* (Issue #3982).
|
|
306
|
+
*
|
|
307
|
+
* Before this table each route had its own `instanceof` chain, and an error
|
|
308
|
+
* added to one was missing from the other: `/prompt-response` answered
|
|
309
|
+
* {@link PromptAnswerInputLostError} as a bare 500 with neither `reason` nor
|
|
310
|
+
* `keysSent`, so a caller could only find the reason by reading the message —
|
|
311
|
+
* which is also where a quoted answer lands. A unit test enumerates this
|
|
312
|
+
* module's exported classes and fails when one has no row here.
|
|
313
|
+
*
|
|
314
|
+
* `keysSent` is stated here for the refusals that never touch the pane rather
|
|
315
|
+
* than put on those errors: Auto-Yes reads `keysSent` off a thrown error to
|
|
316
|
+
* count its attempt, and that count is not this table's to change.
|
|
317
|
+
*/
|
|
318
|
+
exports.PROMPT_ANSWER_ERROR_RESPONSES = new Map([
|
|
319
|
+
row(PromptAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
|
|
320
|
+
row(FreeTextAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
|
|
321
|
+
row(FreeTextAtChoiceOnlyPromptError, (e) => ({ reason: e.reason, keysSent: false }), { 'prompt-response': 200, respond: 500 }),
|
|
322
|
+
row(MultiSelectAnswerRejectedError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 200, respond: 500 }),
|
|
323
|
+
row(PromptAnswerNotDeliveredError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 200, respond: 409 }),
|
|
324
|
+
// Keys reached the pane: a failure, not a refusal, on both routes (#3952 review P2).
|
|
325
|
+
row(PromptAnswerInputLostError, (e) => ({ reason: e.reason, keysSent: e.keysSent }), { 'prompt-response': 500, respond: 500 }),
|
|
326
|
+
row(PromptAnswerAbortedError, (e) => ({ reason: exports.ANSWER_ABORTED_REASON, keysSent: e.keysSent }), { 'prompt-response': 500, respond: 500 }),
|
|
327
|
+
]);
|
|
328
|
+
/** The mapping row for an error, or null when it is not one of this module's. */
|
|
329
|
+
function mappingOf(error) {
|
|
330
|
+
if (!(error instanceof Error))
|
|
331
|
+
return null;
|
|
332
|
+
for (const [errorClass, mapping] of exports.PROMPT_ANSWER_ERROR_RESPONSES) {
|
|
333
|
+
if (error instanceof errorClass)
|
|
334
|
+
return mapping;
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* How `route` answers an error `sendPromptAnswer` threw (Issue #3982), or null
|
|
340
|
+
* for an error this module does not define (the route keeps its own 500).
|
|
341
|
+
*
|
|
342
|
+
* The body always carries `reason` and `keysSent`. Its other keys are the ones
|
|
343
|
+
* each status already had: `success: false` + `message` for a 200 refusal (the
|
|
344
|
+
* route adds `answer`), `error` for a 409, and `error` prefixed
|
|
345
|
+
* `Failed to send answer to tmux:` for a 500. That 500's `error` still quotes
|
|
346
|
+
* the message, so a CLI older than this table reads it as before.
|
|
347
|
+
*/
|
|
348
|
+
function promptAnswerErrorResponse(error, route) {
|
|
349
|
+
const mapping = mappingOf(error);
|
|
350
|
+
if (mapping === null)
|
|
351
|
+
return null;
|
|
352
|
+
const err = error;
|
|
353
|
+
const { reason, keysSent } = mapping.facts(err);
|
|
354
|
+
const status = mapping.status[route];
|
|
355
|
+
if (status === 200) {
|
|
356
|
+
return { status, body: { success: false, reason, message: err.message, keysSent } };
|
|
357
|
+
}
|
|
358
|
+
if (status >= 500) {
|
|
359
|
+
return { status, body: { error: `Failed to send answer to tmux: ${err.message}`, reason, keysSent } };
|
|
360
|
+
}
|
|
361
|
+
return { status, body: { error: err.message, reason, keysSent } };
|
|
362
|
+
}
|
|
@@ -69,6 +69,7 @@ const agent_event_structured_state_1 = require("../../lib/session/agent-event-st
|
|
|
69
69
|
const agent_event_awaiting_instruction_1 = require("../../lib/session/agent-event-awaiting-instruction");
|
|
70
70
|
const agent_event_ask_user_question_1 = require("../../lib/session/agent-event-ask-user-question");
|
|
71
71
|
const global_state_1 = require("../global-state");
|
|
72
|
+
const prompt_submit_receipt_1 = require("../../lib/session/prompt-submit-receipt");
|
|
72
73
|
var agent_event_dedup_2 = require("../../lib/session/agent-event-dedup");
|
|
73
74
|
Object.defineProperty(exports, "AGENT_EVENT_DEDUP_WINDOW_MS", { enumerable: true, get: function () { return agent_event_dedup_2.AGENT_EVENT_DEDUP_WINDOW_MS; } });
|
|
74
75
|
Object.defineProperty(exports, "agentEventKeyClaimedAt", { enumerable: true, get: function () { return agent_event_dedup_2.agentEventKeyClaimedAt; } });
|
|
@@ -224,6 +225,9 @@ function recordAgentEvent(worktreeId, cliToolId, instanceId, record, options = {
|
|
|
224
225
|
return { recorded: false, skipped: 'late-session-start' };
|
|
225
226
|
}
|
|
226
227
|
lastAgentEvent.set(key, record);
|
|
228
|
+
// Issue #4035: what the sender asks before trusting an empty-looking composer
|
|
229
|
+
// on a session's first prompt.
|
|
230
|
+
(0, prompt_submit_receipt_1.notePromptSubmitHook)({ worktreeId, cliToolId, instanceId }, record.event, record.at);
|
|
227
231
|
const outcomes = [];
|
|
228
232
|
if (record.event === 'session_start') {
|
|
229
233
|
// Issue #2357: a new agent process, whatever model it names first is its
|
|
@@ -46,6 +46,7 @@ const session_generation_archive_1 = require("../../lib/session/session-generati
|
|
|
46
46
|
const session_starting_state_1 = require("../../lib/session/session-starting-state");
|
|
47
47
|
const auto_yes_enter_fallback_state_1 = require("../../lib/polling/auto-yes-enter-fallback-state");
|
|
48
48
|
const instance_input_lock_1 = require("../../lib/session/instance-input-lock");
|
|
49
|
+
const prompt_submit_receipt_1 = require("../../lib/session/prompt-submit-receipt");
|
|
49
50
|
const session_name_1 = require("../../lib/cli-tools/session-name");
|
|
50
51
|
const logger_1 = require("../../lib/logger");
|
|
51
52
|
const logger = (0, logger_1.createLogger)('lib/session/agent-session-lifecycle');
|
|
@@ -93,7 +94,11 @@ function beginAgentSession(target, at = Date.now()) {
|
|
|
93
94
|
// `invalidateInstanceInput`). In memory only; a name that does not resolve
|
|
94
95
|
// has no lock to expire.
|
|
95
96
|
try {
|
|
96
|
-
|
|
97
|
+
const sessionName = (0, session_name_1.resolveSessionName)(target.cliToolId, target.worktreeId, target.instanceId);
|
|
98
|
+
(0, instance_input_lock_1.invalidateInstanceInput)(sessionName);
|
|
99
|
+
// Issue #4035: the new process's first prompt is confirmed by its own
|
|
100
|
+
// `UserPromptSubmit`, which is looked up by this session name.
|
|
101
|
+
(0, prompt_submit_receipt_1.notePromptSubmitSession)(sessionName, target, at);
|
|
97
102
|
}
|
|
98
103
|
catch (error) {
|
|
99
104
|
logger.warn('instance-input-invalidate-failed', {
|
|
@@ -35,6 +35,8 @@ const agent_event_state_1 = require("../../lib/session/agent-event-state");
|
|
|
35
35
|
const session_start_error_1 = require("../../lib/session/session-start-error");
|
|
36
36
|
const launch_screen_1 = require("../../lib/session/launch-screen");
|
|
37
37
|
const instance_input_lock_1 = require("../../lib/session/instance-input-lock");
|
|
38
|
+
const session_launch_flight_1 = require("../../lib/session/session-launch-flight");
|
|
39
|
+
const launch_keys_1 = require("../../lib/cli-tools/launch-keys");
|
|
38
40
|
const logger = (0, logger_1.createLogger)('claude-session');
|
|
39
41
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
40
42
|
// ----- Helper Functions -----
|
|
@@ -686,12 +688,22 @@ async function startClaudeSession(options) {
|
|
|
686
688
|
sessionName,
|
|
687
689
|
workingDirectory: worktreePath,
|
|
688
690
|
});
|
|
689
|
-
// SF-S2-003: Sanitize environment after createSession, before launching
|
|
690
|
-
|
|
691
|
-
//
|
|
692
|
-
//
|
|
693
|
-
//
|
|
694
|
-
|
|
691
|
+
// SF-S2-003: Sanitize environment after createSession, before launching
|
|
692
|
+
// Claude CLI (what session-key-sender's `sanitizeSessionEnvironment` did
|
|
693
|
+
// until #4032 removed it): drop CLAUDECODE from
|
|
694
|
+
// tmux's global environment (MF-S3-002), then `unset` it in the pane's
|
|
695
|
+
// shell, then start Claude in interactive mode using the dynamically
|
|
696
|
+
// resolved path.
|
|
697
|
+
//
|
|
698
|
+
// Issue #3981: the two lines are typed in ONE writer's turn of the input
|
|
699
|
+
// lock (#3975 locked only the launch line; the `unset` went out before it
|
|
700
|
+
// with no lock), so neither lands inside a send's body. The sanitize's
|
|
701
|
+
// 100 ms pause between them is gone: both lines queue in the same shell's
|
|
702
|
+
// input in order, so the `unset` runs first without it, and a pause inside
|
|
703
|
+
// the turn would only hold sends off longer. The init polls below stay
|
|
704
|
+
// outside the lock.
|
|
705
|
+
await execAsync('tmux set-environment -g -u CLAUDECODE 2>/dev/null || true');
|
|
706
|
+
await (0, launch_keys_1.typeLaunchLines)(sessionName, ['unset CLAUDECODE', (0, launch_screen_1.withLaunchScreenCleared)(launchCommand)]);
|
|
695
707
|
// Wait for Claude to initialize with dynamic detection (OCP-001)
|
|
696
708
|
// Use constants instead of hardcoded values
|
|
697
709
|
const maxWaitTime = exports.CLAUDE_INIT_TIMEOUT;
|
|
@@ -799,6 +811,10 @@ async function startClaudeSession(options) {
|
|
|
799
811
|
*/
|
|
800
812
|
async function sendMessageToClaude(worktreeId, message, instanceId) {
|
|
801
813
|
const sessionName = getSessionName(worktreeId, instanceId);
|
|
814
|
+
// Issue #3981: a session another request is still launching shows a shell
|
|
815
|
+
// (`❯ ` can pass for Claude's prompt) — wait for that launch, or, holding the
|
|
816
|
+
// input lock as the send service does, refuse with nothing typed (R1).
|
|
817
|
+
await (0, session_launch_flight_1.settleSessionLaunch)(sessionName, 'Claude Code');
|
|
802
818
|
await (0, session_key_sender_1.sendMessageToSession)(sessionName, message, exports.CLAUDE_POST_PROMPT_DELAY, exports.CLAUDE_SEND_PROMPT_WAIT_TIMEOUT);
|
|
803
819
|
}
|
|
804
820
|
/**
|
|
@@ -237,7 +237,7 @@ function readAgentEvents(worktreeId, cliToolId, instanceId, resolvedInstanceId)
|
|
|
237
237
|
* every value below is derived from the arguments, and nothing is assigned
|
|
238
238
|
* outside this function.
|
|
239
239
|
*/
|
|
240
|
-
function composePromptData({ worktreeId, cliToolId, output, captureWindowLines, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
|
|
240
|
+
function composePromptData({ worktreeId, cliToolId, instanceId, output, captureWindowLines, statusResult, startingSince, promptWaiting, askUserQuestion, eventSource, }) {
|
|
241
241
|
const scraperPromptWaiting = statusResult.hasActivePrompt;
|
|
242
242
|
// Issue #1726: the agent's own account of what it asked. It contributes only
|
|
243
243
|
// where some other layer has already established that a dialog is on screen —
|
|
@@ -338,9 +338,9 @@ function composePromptData({ worktreeId, cliToolId, output, captureWindowLines,
|
|
|
338
338
|
: scraperPromptWaiting
|
|
339
339
|
? correctedPromptData ??
|
|
340
340
|
scraperPromptData ??
|
|
341
|
-
(structuredFacts ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts) : null)
|
|
341
|
+
(structuredFacts ? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts, instanceId) : null)
|
|
342
342
|
: structuredFacts
|
|
343
|
-
? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts)
|
|
343
|
+
? (0, structured_prompt_1.buildStructuredPromptData)(worktreeId, structuredFacts, instanceId)
|
|
344
344
|
: null;
|
|
345
345
|
// Issue #2870: whether `/prompt-response` would answer the prompt published
|
|
346
346
|
// above, read by the SAME function it re-verifies with. In #2868 `promptData`
|
|
@@ -813,6 +813,7 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
|
|
|
813
813
|
const { structuredFacts, promptData, promptAnswerable } = composePromptData({
|
|
814
814
|
worktreeId,
|
|
815
815
|
cliToolId,
|
|
816
|
+
instanceId,
|
|
816
817
|
output,
|
|
817
818
|
captureWindowLines,
|
|
818
819
|
statusResult,
|
|
@@ -920,6 +921,7 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
|
|
|
920
921
|
worktreeId,
|
|
921
922
|
cliToolId,
|
|
922
923
|
instanceId: resolvedInstanceId,
|
|
924
|
+
respondInstanceId: instanceId,
|
|
923
925
|
state: promptWaiting,
|
|
924
926
|
facts: structuredFacts,
|
|
925
927
|
});
|
|
@@ -221,7 +221,7 @@ function recordUnclassifiedFrame(db, params) {
|
|
|
221
221
|
* nothing else.
|
|
222
222
|
*/
|
|
223
223
|
function recordStructuredPrompt(db, params) {
|
|
224
|
-
const record = (0, structured_prompt_1.buildStructuredPromptHistoryRecord)(params.worktreeId, params.facts);
|
|
224
|
+
const record = (0, structured_prompt_1.buildStructuredPromptHistoryRecord)(params.worktreeId, params.facts, params.respondInstanceId);
|
|
225
225
|
try {
|
|
226
226
|
const message = (0, db_1.createMessage)(db, {
|
|
227
227
|
worktreeId: params.worktreeId,
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Whether the agent itself reported a sent prompt (Issue #4035).
|
|
4
|
+
*
|
|
5
|
+
* The submit-verified sender decides "the message left the composer" from the
|
|
6
|
+
* screen. Two of its rules say only that the body is NOT in the composer — B
|
|
7
|
+
* (no composer, or an empty one) and F (other text, such as claude's dim
|
|
8
|
+
* `Try "…"` placeholder) — and right after a claude session starts that is not
|
|
9
|
+
* the same thing: measured on Claude Code 2.1.314 (`tests/fixtures/claude-first-send-4035/`),
|
|
10
|
+
* keys typed in the first second after the prompt appeared were drawn into the
|
|
11
|
+
* composer ~1.7 s later, the Enter typed after them was lost, and the frame
|
|
12
|
+
* read after the Enter still showed the idle placeholder, so F answered
|
|
13
|
+
* `submitted` for a body that sat unsent until the next send threw it away.
|
|
14
|
+
*
|
|
15
|
+
* Claude reports every submitted prompt with its `UserPromptSubmit` hook. This
|
|
16
|
+
* module keeps, per tmux session this server started, when that hook last
|
|
17
|
+
* arrived, so the sender can ask for it before trusting B or F on the
|
|
18
|
+
* session's first prompt ({@link readPromptSubmitReceipt}). It also keeps a
|
|
19
|
+
* fingerprint (digests, never the text) of the last body the sender reported
|
|
20
|
+
* submitted, so a later send that has to clear that very body out of the
|
|
21
|
+
* composer can say so ({@link matchesSubmittedBody}).
|
|
22
|
+
*
|
|
23
|
+
* In memory on `globalThis`, like the other per-session state; a session this
|
|
24
|
+
* server did not start (one adopted after a restart) has no entry, and every
|
|
25
|
+
* question about it is answered "not required", i.e. exactly as before.
|
|
26
|
+
*
|
|
27
|
+
* @module lib/session/prompt-submit-receipt
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.notePromptSubmitSession = notePromptSubmitSession;
|
|
31
|
+
exports.notePromptSubmitHook = notePromptSubmitHook;
|
|
32
|
+
exports.getPromptSubmitTarget = getPromptSubmitTarget;
|
|
33
|
+
exports.readPromptSubmitReceipt = readPromptSubmitReceipt;
|
|
34
|
+
exports.noteSubmittedBody = noteSubmittedBody;
|
|
35
|
+
exports.matchesSubmittedBody = matchesSubmittedBody;
|
|
36
|
+
exports.clearPromptSubmitReceipts = clearPromptSubmitReceipts;
|
|
37
|
+
const crypto_1 = require("crypto");
|
|
38
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
39
|
+
const global_state_1 = require("../../lib/global-state");
|
|
40
|
+
/** How many sessions are tracked at once; the least recently started is forgotten first. */
|
|
41
|
+
const MAX_TRACKED_SESSIONS = 1024;
|
|
42
|
+
/**
|
|
43
|
+
* Compacted characters a body's prefix fingerprint covers. A composer read is
|
|
44
|
+
* cut by the reader, so a long body is recognised by its beginning.
|
|
45
|
+
*/
|
|
46
|
+
const BODY_PREFIX_CHARS = 64;
|
|
47
|
+
const sessions = (0, global_state_1.getOrInitGlobal)('__promptSubmitSessions', () => new Map());
|
|
48
|
+
const sessionByInstance = (0, global_state_1.getOrInitGlobal)('__promptSubmitSessionByInstance', () => new Map());
|
|
49
|
+
function instanceKey(target) {
|
|
50
|
+
return (0, auto_yes_state_1.buildCompositeKey)(target.worktreeId, target.cliToolId, target.instanceId);
|
|
51
|
+
}
|
|
52
|
+
/** The tools whose prompt hook is trusted as proof of a submit. */
|
|
53
|
+
function reportsPrompts(cliToolId) {
|
|
54
|
+
// Claude only. codex's hooks run in a machine-wide daemon that can file a
|
|
55
|
+
// turn under the wrong instance (#2874), and copilot's arrive out of order
|
|
56
|
+
// (#1903); neither is evidence about one pane's composer.
|
|
57
|
+
return cliToolId === 'claude';
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A session's generation began here (`beginAgentSession`). Forgets what was
|
|
61
|
+
* known about the previous process in the same pane name.
|
|
62
|
+
*/
|
|
63
|
+
function notePromptSubmitSession(sessionName, target, at = Date.now()) {
|
|
64
|
+
sessions.delete(sessionName);
|
|
65
|
+
sessions.set(sessionName, { target, startedAt: at, lastEventAt: null, lastPromptAt: null, submittedBody: null });
|
|
66
|
+
sessionByInstance.set(instanceKey(target), sessionName);
|
|
67
|
+
while (sessions.size > MAX_TRACKED_SESSIONS) {
|
|
68
|
+
const oldest = sessions.keys().next().value;
|
|
69
|
+
if (oldest === undefined)
|
|
70
|
+
break;
|
|
71
|
+
const entry = sessions.get(oldest);
|
|
72
|
+
sessions.delete(oldest);
|
|
73
|
+
if (entry !== undefined && sessionByInstance.get(instanceKey(entry.target)) === oldest) {
|
|
74
|
+
sessionByInstance.delete(instanceKey(entry.target));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** A hook was applied for this instance (`recordAgentEvent`). */
|
|
79
|
+
function notePromptSubmitHook(target, event, at) {
|
|
80
|
+
let sessionName;
|
|
81
|
+
try {
|
|
82
|
+
sessionName = sessionByInstance.get(instanceKey(target));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const entry = sessionName === undefined ? undefined : sessions.get(sessionName);
|
|
88
|
+
if (entry === undefined)
|
|
89
|
+
return;
|
|
90
|
+
entry.lastEventAt = at;
|
|
91
|
+
if (event === 'user_prompt_submit')
|
|
92
|
+
entry.lastPromptAt = at;
|
|
93
|
+
}
|
|
94
|
+
/** The instance a session this server started runs, or null. */
|
|
95
|
+
function getPromptSubmitTarget(sessionName) {
|
|
96
|
+
return sessions.get(sessionName)?.target ?? null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether the screen's B/F verdict for a send whose first Enter went in at
|
|
100
|
+
* `enteredAt` needs the agent's own report (Issue #4035).
|
|
101
|
+
*/
|
|
102
|
+
function readPromptSubmitReceipt(sessionName, cliToolId, enteredAt) {
|
|
103
|
+
if (!reportsPrompts(cliToolId))
|
|
104
|
+
return 'not-required';
|
|
105
|
+
const entry = sessions.get(sessionName);
|
|
106
|
+
if (entry === undefined || entry.target.cliToolId !== cliToolId)
|
|
107
|
+
return 'not-required';
|
|
108
|
+
if (entry.lastPromptAt !== null && entry.lastPromptAt >= enteredAt)
|
|
109
|
+
return 'received';
|
|
110
|
+
if (entry.lastEventAt === null || entry.lastEventAt < entry.startedAt)
|
|
111
|
+
return 'not-required';
|
|
112
|
+
if (entry.lastPromptAt !== null && entry.lastPromptAt >= entry.startedAt)
|
|
113
|
+
return 'not-required';
|
|
114
|
+
return 'awaited';
|
|
115
|
+
}
|
|
116
|
+
function compact(text) {
|
|
117
|
+
return text.replace(/\s+/g, '');
|
|
118
|
+
}
|
|
119
|
+
function digest(text) {
|
|
120
|
+
return (0, crypto_1.createHash)('sha256').update(text, 'utf8').digest('hex').slice(0, 16);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The sender reported this body submitted on this session from the screen
|
|
124
|
+
* alone — not for one the agent's hook reported, which did leave.
|
|
125
|
+
*/
|
|
126
|
+
function noteSubmittedBody(sessionName, message) {
|
|
127
|
+
const entry = sessions.get(sessionName);
|
|
128
|
+
if (entry === undefined)
|
|
129
|
+
return;
|
|
130
|
+
const body = compact(message);
|
|
131
|
+
entry.submittedBody = {
|
|
132
|
+
full: digest(body),
|
|
133
|
+
prefix: body.length >= BODY_PREFIX_CHARS ? digest(body.slice(0, BODY_PREFIX_CHARS)) : null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Whether a composer read is the body last reported submitted on this session:
|
|
138
|
+
* the whole of it, or — for a read long enough — its beginning.
|
|
139
|
+
*/
|
|
140
|
+
function matchesSubmittedBody(sessionName, composerText) {
|
|
141
|
+
const body = sessions.get(sessionName)?.submittedBody;
|
|
142
|
+
if (body === null || body === undefined)
|
|
143
|
+
return false;
|
|
144
|
+
const read = compact(composerText);
|
|
145
|
+
if (read === '')
|
|
146
|
+
return false;
|
|
147
|
+
if (digest(read) === body.full)
|
|
148
|
+
return true;
|
|
149
|
+
return body.prefix !== null && read.length >= BODY_PREFIX_CHARS && digest(read.slice(0, BODY_PREFIX_CHARS)) === body.prefix;
|
|
150
|
+
}
|
|
151
|
+
/** Forget every session (tests). */
|
|
152
|
+
function clearPromptSubmitReceipts() {
|
|
153
|
+
sessions.clear();
|
|
154
|
+
sessionByInstance.clear();
|
|
155
|
+
}
|
|
@@ -128,13 +128,20 @@ async function isPromptWaiting(worktreeId, cliToolId, instanceId, options) {
|
|
|
128
128
|
* That is precisely the state where a guard turns into an outage, so the message
|
|
129
129
|
* has to name the way past it and how long it lasts if they do nothing.
|
|
130
130
|
*
|
|
131
|
+
* Issue #4031: the commands it names carry ` --instance <id>` when the refused
|
|
132
|
+
* request named an instance, so the answer goes to the instance that is
|
|
133
|
+
* waiting. A request for the primary instance (no `instanceId`) gets the
|
|
134
|
+
* sentence as before.
|
|
135
|
+
*
|
|
131
136
|
* @param blockedBy - Which layer refused; omitted callers get the plain message
|
|
137
|
+
* @param instanceId - The instance the refused request named, if any
|
|
132
138
|
*/
|
|
133
|
-
function promptWaitingMessage(worktreeId, blockedBy) {
|
|
139
|
+
function promptWaitingMessage(worktreeId, blockedBy, instanceId) {
|
|
140
|
+
const target = instanceId ? ` --instance ${instanceId}` : '';
|
|
134
141
|
const base = `${worktreeId} is waiting on a prompt. Sending now would type into the ` +
|
|
135
142
|
`prompt's input line instead of reaching the agent, and would leave that ` +
|
|
136
143
|
`text in place for the next answer. Answer the prompt first: ` +
|
|
137
|
-
`\`commandmate respond ${worktreeId} <answer
|
|
144
|
+
`\`commandmate respond ${worktreeId} <answer>${target}\`.`;
|
|
138
145
|
if (blockedBy !== 'structured')
|
|
139
146
|
return base;
|
|
140
147
|
const ttlMinutes = Math.round(prompt_waiting_composition_1.STRUCTURED_SEND_BLOCK_MAX_AGE_MS / 60_000);
|
|
@@ -142,6 +149,6 @@ function promptWaitingMessage(worktreeId, blockedBy) {
|
|
|
142
149
|
`visible to the terminal scraper, so if the pane looks idle the record has ` +
|
|
143
150
|
`outlived its dialog: it stops blocking sends ${ttlMinutes} minutes after ` +
|
|
144
151
|
`it was reported, or immediately with ` +
|
|
145
|
-
`\`commandmate send ${worktreeId} <message
|
|
152
|
+
`\`commandmate send ${worktreeId} <message>${target} --ignore-structured-prompt\` ` +
|
|
146
153
|
`(server-wide: ${prompt_waiting_composition_1.STRUCTURED_SEND_GUARD_ENV}=off).`);
|
|
147
154
|
}
|