commandmate 0.29.2 → 0.30.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 +271 -264
- package/.next/app-path-routes-manifest.json +35 -34
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +8 -8
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +18 -18
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +19 -19
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route.js +1 -0
- package/.next/server/app/api/settings/default-surface-mode/route.js.nft.json +1 -0
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -0
- 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/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route.js +1 -0
- package/.next/server/app/api/worktrees/[id]/cli-reference/route.js.nft.json +1 -0
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_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/opencode/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_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_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.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 +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 +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.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_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 +11 -11
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page.js +3 -3
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +35 -34
- package/.next/server/chunks/1058.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1191.js +1 -1
- package/.next/server/chunks/1341.js +1 -1
- package/.next/server/chunks/1886.js +3 -3
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/261.js +1 -0
- package/.next/server/chunks/2739.js +1 -0
- package/.next/server/chunks/2816.js +1 -1
- package/.next/server/chunks/3099.js +5 -0
- package/.next/server/chunks/3123.js +1 -0
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3543.js +1 -1
- package/.next/server/chunks/3945.js +1 -1
- package/.next/server/chunks/4325.js +1 -0
- package/.next/server/chunks/4390.js +1 -1
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/4443.js +6 -0
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5043.js +1 -0
- package/.next/server/chunks/5120.js +1 -0
- package/.next/server/chunks/552.js +25 -0
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/6337.js +1 -1
- package/.next/server/chunks/663.js +1 -1
- package/.next/server/chunks/6894.js +8 -0
- package/.next/server/chunks/7685.js +1 -1
- package/.next/server/chunks/7836.js +1 -0
- package/.next/server/chunks/8356.js +1 -1
- package/.next/server/chunks/880.js +1 -1
- package/.next/server/chunks/8807.js +1 -1
- package/.next/server/chunks/9123.js +2 -2
- package/.next/server/chunks/9130.js +3 -3
- package/.next/server/chunks/9627.js +48 -26
- package/.next/server/chunks/9696.js +3 -0
- package/.next/server/chunks/9798.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/server/src/middleware.js +1 -1
- package/.next/server/src/middleware.js.map +1 -1
- package/.next/static/chunks/{4882-388e94fe0a03c2ba.js → 3916-0e929d089282dc5d.js} +1 -1
- package/.next/static/chunks/{5229-b2a81bb8fb5c19e9.js → 5229-6c89475b61bd2c8b.js} +1 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +1 -0
- package/.next/static/chunks/6381-dbf04a99647f6018.js +1 -0
- package/.next/static/chunks/app/api/agents/update/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/agents/versions/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/app/update/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/app/update-check/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/conversation/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/current-output/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/messages/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/session/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/start/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/terminal/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/assistant/tools/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/auth/login/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/auth/logout/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/auth/status/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/capabilities/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/daily-summary/status/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/external-apps/[id]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/external-apps/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/fs/browse/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/fs/recent-paths/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/hooks/agent-event/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/hooks/claude-done/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/hooks/permission-request/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/metrics/vibe/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/ollama/models/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/push/escalation/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/push/subscriptions/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/push/vapid/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/remote/pair/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/clone/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/excluded/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/restore/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/scan/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/sync/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/repositories/validate-path/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/settings/default-agents/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/settings/default-surface-mode/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/sidebar/group-order/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/skills/[id]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/skills/installations/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/skills/operations/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/skills/reindex/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/skills/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/slash-commands/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/tasks/[taskId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/templates/[id]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/templates/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/todos/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/verification/runs/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-reference/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/api/worktrees/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/manifest.webmanifest/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/more/{page-75d3783da0d49a25.js → page-333bba1c8bbc9c11.js} +1 -1
- package/.next/static/chunks/app/proxy/[...path]/route-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/layout-ee11f7b8a34cba8c.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-aac399392ec8c273.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-2631bc5c4b0a9fb8.js +1 -0
- package/.next/static/css/23f9c40ecc458c77.css +1 -0
- package/.next/static/pcpB4K6KreMzu2qbhvuRY/_buildManifest.js +1 -0
- package/.next/trace +13 -13
- package/.next/types/app/api/settings/default-surface-mode/route.ts +347 -0
- package/.next/types/app/api/worktrees/[id]/{start-polling → cli-reference}/route.ts +3 -3
- package/.next/types/routes.d.ts +3 -2
- package/.next/types/validator.ts +18 -9
- package/dist/server/server.js +58 -0
- package/dist/server/src/lib/claude-output.js +1 -0
- package/dist/server/src/lib/db/app-settings-db.js +60 -0
- package/dist/server/src/lib/db/chat-db.js +120 -7
- package/dist/server/src/lib/detection/status-detector.js +3 -2
- package/dist/server/src/lib/env.js +122 -0
- package/dist/server/src/lib/git/worktrees.js +154 -0
- package/dist/server/src/lib/history/transcript-tail.js +80 -0
- package/dist/server/src/lib/history/user-turn-recorder.js +252 -0
- package/dist/server/src/lib/hooks/agent-event-service.js +40 -6
- package/dist/server/src/lib/hooks/permission-decision-service.js +85 -1
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +607 -0
- package/dist/server/src/lib/hooks/sources/antigravity/source.js +7 -0
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +407 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +797 -0
- package/dist/server/src/lib/hooks/sources/claude/source.js +4 -0
- package/dist/server/src/lib/hooks/sources/claude/transcript.js +518 -0
- package/dist/server/src/lib/hooks/sources/codex/history.js +663 -0
- package/dist/server/src/lib/hooks/sources/codex/source.js +4 -0
- package/dist/server/src/lib/hooks/sources/codex/transcript.js +448 -0
- package/dist/server/src/lib/hooks/sources/copilot/source.js +2 -0
- package/dist/server/src/lib/hooks/sources/gemini/source.js +2 -0
- package/dist/server/src/lib/hooks/sources/legacy-relay.js +3 -0
- package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -0
- package/dist/server/src/lib/hooks/sources/opencode/source.js +4 -0
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +10 -28
- package/dist/server/src/lib/hooks/sources/turn-body.js +118 -0
- package/dist/server/src/lib/hooks/stop-history-capture.js +161 -0
- package/dist/server/src/lib/polling/prompt-dedup.js +2 -4
- package/dist/server/src/lib/polling/response-checker.js +87 -6
- package/dist/server/src/lib/polling/response-dedup.js +2 -4
- package/dist/server/src/lib/polling/response-poller-core.js +191 -29
- package/dist/server/src/lib/polling/structured-history-gate.js +272 -16
- package/dist/server/src/lib/push/push-sender.js +21 -1
- package/dist/server/src/lib/push/waiting-push-notifier.js +126 -8
- package/dist/server/src/lib/realtime/publisher-registry.js +171 -0
- package/dist/server/src/lib/realtime/terminal-broadcast.js +14 -1
- package/dist/server/src/lib/realtime/types.js +96 -1
- package/dist/server/src/lib/session/current-output-builder.js +365 -4
- package/dist/server/src/lib/session/send-user-message.js +90 -2
- package/dist/server/src/lib/tui-accumulator.js +2 -8
- package/dist/server/src/lib/ws-server.js +143 -6
- package/dist/server/src/types/agent-transcript.js +241 -5
- package/dist/server/src/types/ui-state.js +24 -1
- package/package.json +1 -1
- package/public/sw.js +15 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js +0 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +0 -1
- package/.next/server/app/api/worktrees/[id]/start-polling/route_client-reference-manifest.js +0 -1
- package/.next/server/chunks/1714.js +0 -7
- package/.next/server/chunks/2198.js +0 -1
- package/.next/server/chunks/221.js +0 -25
- package/.next/server/chunks/2759.js +0 -8
- package/.next/server/chunks/3558.js +0 -1
- package/.next/server/chunks/6781.js +0 -1
- package/.next/server/chunks/9508.js +0 -1
- package/.next/static/0YoRrahue4Vchxg1z83IQ/_buildManifest.js +0 -1
- package/.next/static/chunks/1379-af7af9e08f47c979.js +0 -1
- package/.next/static/chunks/6381-9ba5198c0a6ff197.js +0 -1
- package/.next/static/chunks/app/api/agents/update/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/agents/versions/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/app/update/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/app/update-check/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/conversation/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/current-output/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/messages/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/session/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/start/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/terminal/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/assistant/tools/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/auth/login/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/auth/logout/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/auth/status/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/capabilities/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/daily-summary/status/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/health/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/external-apps/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/external-apps/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/fs/browse/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/fs/recent-paths/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/hooks/agent-event/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/hooks/claude-done/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/hooks/permission-request/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/metrics/vibe/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/ollama/models/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/push/escalation/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/push/subscriptions/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/push/vapid/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/remote/pair/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/[todoId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/[id]/todos/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/[jobId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/clone/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/excluded/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/restore/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/scan/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/sync/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/repositories/validate-path/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/settings/default-agents/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/sidebar/group-order/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/skills/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/skills/installations/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/skills/operations/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/skills/reindex/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/skills/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/slash-commands/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/cancel/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/tasks/[taskId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/templates/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/templates/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/todos/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/[runId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/verification/runs/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/auto-yes/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/capture/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/clear-composer/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cli-tool/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/cmate/schedules/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/current-output/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/env/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/[logId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/execution-logs/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/files/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/create/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branch/delete/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/branches/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/checkout/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/commit/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/diff/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/fetch/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/log/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/pull/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/push/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/reset/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/revert/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/show/[commitHash]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stage/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/staged/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/[index]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/apply/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/pop/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/push/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/stash/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/status/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/unstage/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/git/working-diff/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/instances/opencode/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/interrupt/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/kill-session/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/[filename]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/logs/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/marp-render/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/[memoId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/memos/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/messages/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/diff/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/session/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/opencode/share/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/prompt-response/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/resolve-target/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/respond/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/[scheduleId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/active/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/schedules/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/search/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/send/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/install/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/plan/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/[skillId]/update-plan/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/skills/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/slash-commands/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/special-keys/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/start-polling/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tasks/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/terminal/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/history/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/timers/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/[todoId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/todos/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/tree/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/upload/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/config/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/[runId]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/verify/runs/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/[id]/viewed/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/apply-default-agents/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/api/worktrees/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/manifest.webmanifest/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/proxy/[...path]/route-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/layout-1c30fb8d4d6fa6ef.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-ce6279d581d1df95.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/terminal/page-00ad5d9a62a71cab.js +0 -1
- package/.next/static/css/b326c8a734e1928e.css +0 -1
- /package/.next/static/{0YoRrahue4Vchxg1z83IQ → pcpB4K6KreMzu2qbhvuRY}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Writing Claude Code's own words into conversation history (Issue #2121).
|
|
4
|
+
*
|
|
5
|
+
* The second writer of `chat_messages` for a Claude turn, on the same terms
|
|
6
|
+
* `../opencode/history` established for opencode (#2041): the first writer is
|
|
7
|
+
* `lib/polling/response-checker`, which captures the pane and cleans it, and the
|
|
8
|
+
* two are mutually exclusive.
|
|
9
|
+
*
|
|
10
|
+
* ## Pull, where opencode is push
|
|
11
|
+
*
|
|
12
|
+
* That is the one structural difference, and it decides the shape of this file.
|
|
13
|
+
* opencode has a server CommandMate holds an SSE connection to, so its history
|
|
14
|
+
* writer is driven by frames and flushed by `session.idle`. Claude has no
|
|
15
|
+
* connection at all — its hooks are one-way HTTP posts that this process answers
|
|
16
|
+
* and forgets. What it has instead is a **file**: every record of a session is
|
|
17
|
+
* appended to `~/.claude/projects/<slug>/<session-id>.jsonl` as it happens.
|
|
18
|
+
*
|
|
19
|
+
* So there is nothing to subscribe to and nothing to flush, and the trigger has
|
|
20
|
+
* to come from whatever already knows a turn just ended. That is the poller —
|
|
21
|
+
* which is also the writer being replaced, so the handover happens in one place
|
|
22
|
+
* and cannot half-happen: `lib/polling/structured-history-gate` calls
|
|
23
|
+
* {@link captureClaudeTranscriptTurn} at the moment the scraped reply would be
|
|
24
|
+
* saved, and saves it only if this returns false.
|
|
25
|
+
*
|
|
26
|
+
* ## Which file is this instance's
|
|
27
|
+
*
|
|
28
|
+
* The Issue's own framing, kept: **the session id is not a key, it is a mutable
|
|
29
|
+
* pointer.** Identity stays the (worktree, tool, instance) triple that
|
|
30
|
+
* `buildCompositeKey` has always spelled; the session id is only the answer to
|
|
31
|
+
* "which transcript does that triple point at *right now*", and `/clear`
|
|
32
|
+
* changing it is correct rather than a problem, because the conversation really
|
|
33
|
+
* did change.
|
|
34
|
+
*
|
|
35
|
+
* The pointer is read from the structured events the agent already sends —
|
|
36
|
+
* `getLastAgentEvent(...).sessionId`, which the `/api/hooks/agent-event`
|
|
37
|
+
* receiver records for every hook — and latched here, because most events carry
|
|
38
|
+
* a session id but the record is replaced by whichever event was newest. Two
|
|
39
|
+
* consequences worth stating:
|
|
40
|
+
*
|
|
41
|
+
* - **Two Claude instances in one worktree do not collide.** They share the
|
|
42
|
+
* project directory (the slug is a function of `cwd`), but the hook URL
|
|
43
|
+
* CommandMate injects carries `instanceId`, so each triple latches its own
|
|
44
|
+
* session id and therefore its own file.
|
|
45
|
+
* - **A session with no hooks has no pointer**, and this module returns false
|
|
46
|
+
* for it. That is the fail-open the acceptance criteria ask for: no
|
|
47
|
+
* transcript we can name means the scraper is still the only record there is.
|
|
48
|
+
*
|
|
49
|
+
* ## Nothing here throws
|
|
50
|
+
*
|
|
51
|
+
* Same contract as `../opencode/history`, for the same reason, and one more: a
|
|
52
|
+
* throw here would propagate into the poller's save path and could cost the
|
|
53
|
+
* scraped reply *as well as* the structured one. The database imports are
|
|
54
|
+
* dynamic so that `better-sqlite3` does not enter the module graph of everything
|
|
55
|
+
* that imports `@/lib/hooks/sources`.
|
|
56
|
+
*
|
|
57
|
+
* @module lib/hooks/sources/claude/history
|
|
58
|
+
*/
|
|
59
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
60
|
+
if (k2 === undefined) k2 = k;
|
|
61
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
62
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
63
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
64
|
+
}
|
|
65
|
+
Object.defineProperty(o, k2, desc);
|
|
66
|
+
}) : (function(o, m, k, k2) {
|
|
67
|
+
if (k2 === undefined) k2 = k;
|
|
68
|
+
o[k2] = m[k];
|
|
69
|
+
}));
|
|
70
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
71
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
72
|
+
}) : function(o, v) {
|
|
73
|
+
o["default"] = v;
|
|
74
|
+
});
|
|
75
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
76
|
+
var ownKeys = function(o) {
|
|
77
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
78
|
+
var ar = [];
|
|
79
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
80
|
+
return ar;
|
|
81
|
+
};
|
|
82
|
+
return ownKeys(o);
|
|
83
|
+
};
|
|
84
|
+
return function (mod) {
|
|
85
|
+
if (mod && mod.__esModule) return mod;
|
|
86
|
+
var result = {};
|
|
87
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
88
|
+
__setModuleDefault(result, mod);
|
|
89
|
+
return result;
|
|
90
|
+
};
|
|
91
|
+
})();
|
|
92
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
93
|
+
exports.CLAUDE_TRANSCRIPT_TAIL_BYTES = void 0;
|
|
94
|
+
exports.resetClaudeTranscriptSessions = resetClaudeTranscriptSessions;
|
|
95
|
+
exports.resolveClaudeSessionId = resolveClaudeSessionId;
|
|
96
|
+
exports.claudeProjectsRoot = claudeProjectsRoot;
|
|
97
|
+
exports.claudeTranscriptPath = claudeTranscriptPath;
|
|
98
|
+
exports.acceptClaudeTranscriptHint = acceptClaudeTranscriptHint;
|
|
99
|
+
exports.captureClaudeTranscriptTurn = captureClaudeTranscriptTurn;
|
|
100
|
+
exports.resolveClaudeTranscriptPath = resolveClaudeTranscriptPath;
|
|
101
|
+
exports.readClaudeTurnProgress = readClaudeTurnProgress;
|
|
102
|
+
const promises_1 = require("fs/promises");
|
|
103
|
+
const os_1 = require("os");
|
|
104
|
+
const path_1 = require("path");
|
|
105
|
+
const auto_yes_state_1 = require("../../../../lib/auto-yes-state");
|
|
106
|
+
const user_turn_recorder_1 = require("../../../../lib/history/user-turn-recorder");
|
|
107
|
+
const logger_1 = require("../../../../lib/logger");
|
|
108
|
+
const agent_transcript_1 = require("../../../../types/agent-transcript");
|
|
109
|
+
const transcript_1 = require("./transcript");
|
|
110
|
+
const logger = (0, logger_1.createLogger)('lib/hooks/sources/claude/history');
|
|
111
|
+
/**
|
|
112
|
+
* How much of the transcript's tail is read.
|
|
113
|
+
*
|
|
114
|
+
* The file grows for the life of the session and a long one is tens of
|
|
115
|
+
* megabytes — the largest on this machine on 2026-08-31 was 23 MB — so reading
|
|
116
|
+
* it whole on every finished turn would be the most expensive thing the poller
|
|
117
|
+
* does. Only turns whose prompt record is inside the window are ever written
|
|
118
|
+
* (see {@link captureClaudeTranscriptTurn}), which is also what stops a turn the
|
|
119
|
+
* window opened halfway through being written from its middle.
|
|
120
|
+
*
|
|
121
|
+
* 4 MiB is roughly two orders of magnitude above the measured size of a single
|
|
122
|
+
* turn and still small enough to read and parse in one tick. A turn that
|
|
123
|
+
* genuinely does not fit produces orphaned assistant records, which is detected
|
|
124
|
+
* and reported rather than written as a headless reply.
|
|
125
|
+
*/
|
|
126
|
+
exports.CLAUDE_TRANSCRIPT_TAIL_BYTES = 4 * 1024 * 1024;
|
|
127
|
+
/** `.jsonl`; the only extension this reader will open. */
|
|
128
|
+
const CLAUDE_TRANSCRIPT_EXTENSION = '.jsonl';
|
|
129
|
+
/**
|
|
130
|
+
* The last session id seen for each instance.
|
|
131
|
+
*
|
|
132
|
+
* On `globalThis` for the reason every shared map in this subsystem is (#1736):
|
|
133
|
+
* under `next dev` the poller's bundle and the hook receiver's bundle would each
|
|
134
|
+
* get a private copy of a module-scoped map.
|
|
135
|
+
*
|
|
136
|
+
* A latch and not a cache: `getLastAgentEvent` holds only the newest event, and
|
|
137
|
+
* an event that carried no `session_id` would otherwise blank the pointer
|
|
138
|
+
* mid-session. Same reasoning as `getLastKnownAgentModel`, which latches for the
|
|
139
|
+
* same reason.
|
|
140
|
+
*/
|
|
141
|
+
const sessionPointers = (globalThis.__claudeTranscriptSessions ??= new Map());
|
|
142
|
+
function keyOf(target) {
|
|
143
|
+
return (0, auto_yes_state_1.buildCompositeKey)(target.worktreeId, target.cliToolId, target.instanceId);
|
|
144
|
+
}
|
|
145
|
+
/** Forget every instance's pointer. Test seam. */
|
|
146
|
+
function resetClaudeTranscriptSessions() {
|
|
147
|
+
sessionPointers.clear();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The session id this instance's transcript is under, or null.
|
|
151
|
+
*
|
|
152
|
+
* Reads the structured event state first and falls back to the latched value.
|
|
153
|
+
* The import is dynamic so that `agent-event-state`'s module graph does not
|
|
154
|
+
* become a static dependency of the poller.
|
|
155
|
+
*/
|
|
156
|
+
async function resolveClaudeSessionId(target) {
|
|
157
|
+
const key = keyOf(target);
|
|
158
|
+
try {
|
|
159
|
+
const { getLastAgentEvent } = await Promise.resolve().then(() => __importStar(require('../../../../lib/session/agent-event-state')));
|
|
160
|
+
const sessionId = getLastAgentEvent(target.worktreeId, target.cliToolId, target.instanceId)?.sessionId;
|
|
161
|
+
if (typeof sessionId === 'string' && sessionId.length > 0) {
|
|
162
|
+
sessionPointers.set(key, sessionId);
|
|
163
|
+
return sessionId;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// A state module that cannot be reached is one that knows no session id.
|
|
168
|
+
logger.debug('claude-transcript-session-lookup-failed', {
|
|
169
|
+
worktreeId: target.worktreeId,
|
|
170
|
+
instanceId: target.instanceId ?? target.cliToolId,
|
|
171
|
+
error: error instanceof Error ? error.message : String(error),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return sessionPointers.get(key) ?? null;
|
|
175
|
+
}
|
|
176
|
+
/** `<home>/.claude/projects`. */
|
|
177
|
+
function claudeProjectsRoot(homeDir) {
|
|
178
|
+
return (0, path_1.join)(homeDir, ...transcript_1.CLAUDE_PROJECTS_DIR_SEGMENTS);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Where this session's transcript is, from the worktree's own path.
|
|
182
|
+
*
|
|
183
|
+
* `cwd` is the agent's working directory, and CommandMate starts every pane at
|
|
184
|
+
* the worktree root, so the worktree path is the slug input. An agent the
|
|
185
|
+
* operator `cd`-ed somewhere else writes to a different directory and this
|
|
186
|
+
* answers a path that does not exist — read as "no transcript", which is the
|
|
187
|
+
* fail-open direction.
|
|
188
|
+
*/
|
|
189
|
+
function claudeTranscriptPath(homeDir, worktreePath, sessionId) {
|
|
190
|
+
return (0, path_1.join)(claudeProjectsRoot(homeDir), (0, transcript_1.claudeProjectSlug)(worktreePath), `${sessionId}${CLAUDE_TRANSCRIPT_EXTENSION}`);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* A path named by something other than this module, accepted only if it is
|
|
194
|
+
* really a transcript.
|
|
195
|
+
*
|
|
196
|
+
* The one caller is the `📄 Session log: …jsonl` line `lib/claude-output` reads
|
|
197
|
+
* off the pane, which is text the agent printed and therefore text an agent
|
|
198
|
+
* could print. Two conditions, both necessary: it must be under
|
|
199
|
+
* `~/.claude/projects`, so a crafted line cannot make this open
|
|
200
|
+
* `/etc/passwd`; and it must end in `.jsonl`.
|
|
201
|
+
*
|
|
202
|
+
* Containment is checked on the resolved path so that `..` cannot climb out,
|
|
203
|
+
* and `resolve` is safe to use here — unlike in `validateHookCwd`, where the
|
|
204
|
+
* value is echoed back — because the resolved string is the only thing that is
|
|
205
|
+
* ever used.
|
|
206
|
+
*
|
|
207
|
+
* @returns The resolved path, or null when it is not acceptable
|
|
208
|
+
*/
|
|
209
|
+
function acceptClaudeTranscriptHint(homeDir, hint) {
|
|
210
|
+
if (!hint.endsWith(CLAUDE_TRANSCRIPT_EXTENSION))
|
|
211
|
+
return null;
|
|
212
|
+
if (hint.includes('\0'))
|
|
213
|
+
return null;
|
|
214
|
+
const root = (0, path_1.resolve)(claudeProjectsRoot(homeDir));
|
|
215
|
+
const resolved = (0, path_1.resolve)(hint);
|
|
216
|
+
if (resolved !== root && !resolved.startsWith(root + path_1.sep))
|
|
217
|
+
return null;
|
|
218
|
+
return resolved;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Read this instance's unwritten turns out of its transcript and write them.
|
|
222
|
+
*
|
|
223
|
+
* ## Why this is no longer "only the newest turn" (Issue #2246)
|
|
224
|
+
*
|
|
225
|
+
* #2121 wrote `built.turns.at(-1)` and nothing else, for a reason that was
|
|
226
|
+
* sound and is still half true: every earlier turn of this session already has
|
|
227
|
+
* a `chat_messages` row that the *scraper* wrote, and writing a Markdown row
|
|
228
|
+
* for it as well would put the same reply in History twice — once as prose and
|
|
229
|
+
* once as the pane drew it.
|
|
230
|
+
*
|
|
231
|
+
* What that argument did not cover is a turn **no writer recorded at all**. The
|
|
232
|
+
* trigger for this reader is the poller deciding a turn finished, so a poll that
|
|
233
|
+
* misjudges one completion (#2247's launch-banner heuristic, measured on
|
|
234
|
+
* 2026-09-02) does not merely delay the turn: by the time the next completion is
|
|
235
|
+
* judged, "the newest turn" is the *next* one, and the missed turn is nobody's.
|
|
236
|
+
* One dropped completion cost one turn permanently.
|
|
237
|
+
*
|
|
238
|
+
* So the unit of work is now "every turn in the window that is not already a
|
|
239
|
+
* row", written oldest first, and what preserves #2121's argument is the
|
|
240
|
+
* **anchor**: the newest turn in the window that this reader has already written
|
|
241
|
+
* is where the backfill starts. Turns after it are turns this reader was live
|
|
242
|
+
* for, so a scraper row for them exists only in the case the anchor cannot see
|
|
243
|
+
* — the reader answering false once for a transient reason (an empty body) and
|
|
244
|
+
* the scraper saving that turn's pane copy. That trade is deliberate and in the
|
|
245
|
+
* direction every Issue in this subsystem picks: two writers duplicate a reply,
|
|
246
|
+
* no writer loses one.
|
|
247
|
+
*
|
|
248
|
+
* When the window holds **no** anchor — a session the reader has never written
|
|
249
|
+
* for, and equally the first read after a `/clear` — this falls back to #2121's
|
|
250
|
+
* behaviour exactly: the newest turn, and nothing before it. That is the case
|
|
251
|
+
* where the earlier turns really are the scraper's, and there is no evidence in
|
|
252
|
+
* the window that says otherwise.
|
|
253
|
+
*
|
|
254
|
+
* The return value is the poller's instruction, so the two failure directions
|
|
255
|
+
* are worth stating plainly. **True** means this path has recorded the turn and
|
|
256
|
+
* the scrape must be dropped. **False** means it has not, for any reason at all
|
|
257
|
+
* — no session pointer, no file, an unreadable file, a turn with no assistant
|
|
258
|
+
* text yet — and the scrape must be saved. Everything that can go wrong answers
|
|
259
|
+
* false, which is the fail-open the acceptance criteria require: two writers
|
|
260
|
+
* duplicate a reply, no writer loses one.
|
|
261
|
+
*
|
|
262
|
+
* **It is the newest turn the answer is about**, backfill or not. A run that
|
|
263
|
+
* wrote three missed turns and then found the newest one still empty answers
|
|
264
|
+
* false, because the scrape the poller is holding is the pane's copy of *that*
|
|
265
|
+
* turn and dropping it would lose it.
|
|
266
|
+
*
|
|
267
|
+
* Never throws.
|
|
268
|
+
*
|
|
269
|
+
* @param target - The instance whose turn just ended
|
|
270
|
+
* @returns Whether History now holds this instance's newest turn as Markdown
|
|
271
|
+
*/
|
|
272
|
+
async function captureClaudeTranscriptTurn(target, capture) {
|
|
273
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
274
|
+
try {
|
|
275
|
+
const homeDir = capture.homeDir ?? (0, os_1.homedir)();
|
|
276
|
+
if (typeof capture.worktreePath !== 'string' || capture.worktreePath.length === 0) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const sessionId = await resolveClaudeSessionId(target);
|
|
280
|
+
const path = await locateClaudeTranscript(homeDir, capture, sessionId);
|
|
281
|
+
if (!path) {
|
|
282
|
+
logger.debug('claude-transcript-unavailable', {
|
|
283
|
+
worktreeId: target.worktreeId,
|
|
284
|
+
instanceId,
|
|
285
|
+
sessionId,
|
|
286
|
+
reason: sessionId ? 'no-file' : 'no-session-pointer',
|
|
287
|
+
});
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
const text = await readClaudeTranscriptTail(path);
|
|
291
|
+
if (text === null)
|
|
292
|
+
return false;
|
|
293
|
+
const parsed = (0, transcript_1.parseClaudeTranscript)(text);
|
|
294
|
+
const built = (0, transcript_1.buildClaudeTurns)(parsed.records, sessionId ?? '');
|
|
295
|
+
if (built.turns.length === 0) {
|
|
296
|
+
logger.info('claude-transcript-no-turn', {
|
|
297
|
+
worktreeId: target.worktreeId,
|
|
298
|
+
instanceId,
|
|
299
|
+
path,
|
|
300
|
+
records: parsed.records.length,
|
|
301
|
+
malformedLines: parsed.malformedLines,
|
|
302
|
+
orphanedAssistantRecords: built.orphanedAssistantRecords,
|
|
303
|
+
});
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
if (parsed.malformedLines > 0 || built.orphanedAssistantRecords > 0) {
|
|
307
|
+
// Both are expected in small numbers — a fragment at the tail of a file
|
|
308
|
+
// being appended to, and the head of the window landing mid-turn — and
|
|
309
|
+
// both are the kind of thing that must be visible when it stops being
|
|
310
|
+
// small.
|
|
311
|
+
//
|
|
312
|
+
// `orphanedAssistantRecords` is also the shape the Issue #2196 tail-window
|
|
313
|
+
// trap takes: a turn whose prompt record fell outside
|
|
314
|
+
// CLAUDE_TRANSCRIPT_TAIL_BYTES has assistant records and no prompt to
|
|
315
|
+
// record a user row from. It is reported here rather than dropped in
|
|
316
|
+
// silence, exactly as #2121 left it.
|
|
317
|
+
logger.info('claude-transcript-partial-read', {
|
|
318
|
+
worktreeId: target.worktreeId,
|
|
319
|
+
instanceId,
|
|
320
|
+
path,
|
|
321
|
+
malformedLines: parsed.malformedLines,
|
|
322
|
+
orphanedAssistantRecords: built.orphanedAssistantRecords,
|
|
323
|
+
sidechainRecords: built.sidechainRecords,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
const pending = await selectUnwrittenClaudeTurns(target, built.turns);
|
|
327
|
+
if (pending.turns.length === 0) {
|
|
328
|
+
// The anchor is the newest turn in the window, so there is nothing to
|
|
329
|
+
// write and the newest turn is a row. True, for the reason
|
|
330
|
+
// {@link writeClaudeTurn} answers true to an already-saved turn: a second
|
|
331
|
+
// poll of one finished turn must not put the pane's copy on top of it.
|
|
332
|
+
logger.debug('claude-transcript-turns-already-saved', {
|
|
333
|
+
worktreeId: target.worktreeId,
|
|
334
|
+
instanceId,
|
|
335
|
+
turnsInWindow: built.turns.length,
|
|
336
|
+
});
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
if (pending.turns.length > 1) {
|
|
340
|
+
// The #2246 case, and the one worth a line in the log: more than one turn
|
|
341
|
+
// was unwritten, so a completion went unnoticed at the time.
|
|
342
|
+
logger.info('claude-transcript-backfilling-turns', {
|
|
343
|
+
worktreeId: target.worktreeId,
|
|
344
|
+
instanceId,
|
|
345
|
+
path,
|
|
346
|
+
pendingTurns: pending.turns.length,
|
|
347
|
+
turnsInWindow: built.turns.length,
|
|
348
|
+
anchored: pending.anchored,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// Oldest first, and the ordering is load-bearing twice over: History sorts
|
|
352
|
+
// by timestamp, and each turn's `/send` row is adopted against the previous
|
|
353
|
+
// turn's start, so a later turn must not get to claim a row an earlier one
|
|
354
|
+
// is about to ask for.
|
|
355
|
+
let captured = false;
|
|
356
|
+
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
357
|
+
const turn = pending.turns[index];
|
|
358
|
+
const previousStartedAt = index === 0 ? pending.previousStartedAt : pending.turns[index - 1].startedAt;
|
|
359
|
+
const userRow = await recordClaudeUserTurn(target, turn, previousStartedAt);
|
|
360
|
+
captured = await writeClaudeTurn(target, (0, transcript_1.renderClaudeTurn)(turn), resolveAssistantTimestampMs(turn, userRow), path);
|
|
361
|
+
}
|
|
362
|
+
return captured;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
logger.error('claude-transcript-capture-failed', {
|
|
366
|
+
worktreeId: target.worktreeId,
|
|
367
|
+
instanceId,
|
|
368
|
+
error: error instanceof Error ? error.message : String(error),
|
|
369
|
+
});
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* The turns {@link captureClaudeTranscriptTurn} still has to write (Issue #2246).
|
|
375
|
+
*
|
|
376
|
+
* The search runs **backwards from the newest turn** and stops at the first one
|
|
377
|
+
* that is already a row. That turn is the *anchor*, and everything after it is
|
|
378
|
+
* pending — by construction, since the anchor is the newest written turn in the
|
|
379
|
+
* window.
|
|
380
|
+
*
|
|
381
|
+
* Two properties of that rule are worth stating because both were required:
|
|
382
|
+
*
|
|
383
|
+
* - **Order, not time.** The comparison is the transcript's own record order
|
|
384
|
+
* and never a timestamp. A turn's assistant row is dated one millisecond
|
|
385
|
+
* after its user row (`resolveAssistantTimestampMs`), so the rows do not
|
|
386
|
+
* carry an ordering that could be trusted for this.
|
|
387
|
+
* - **The window bounds it.** `buildClaudeTurns` only opens a turn on a prompt
|
|
388
|
+
* record, so a turn whose prompt fell outside
|
|
389
|
+
* {@link CLAUDE_TRANSCRIPT_TAIL_BYTES} is not in `turns` at all and cannot be
|
|
390
|
+
* backfilled from its middle. Its records are counted as
|
|
391
|
+
* `orphanedAssistantRecords` instead, which is what the caller reports.
|
|
392
|
+
*
|
|
393
|
+
* A window with no anchor answers with the newest turn alone. See
|
|
394
|
+
* {@link captureClaudeTranscriptTurn} for why that is #2121's behaviour rather
|
|
395
|
+
* than a degraded one.
|
|
396
|
+
*
|
|
397
|
+
* @param turns - Every turn in the window, oldest first
|
|
398
|
+
*/
|
|
399
|
+
async function selectUnwrittenClaudeTurns(target, turns) {
|
|
400
|
+
const [{ getDbInstance }, { findMessageByRequestId }] = await Promise.all([
|
|
401
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
402
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
403
|
+
]);
|
|
404
|
+
const db = getDbInstance();
|
|
405
|
+
for (let index = turns.length - 1; index >= 0; index -= 1) {
|
|
406
|
+
const requestId = (0, agent_transcript_1.claudeTurnRequestId)(turns[index].promptUuid);
|
|
407
|
+
if (!findMessageByRequestId(db, target.worktreeId, requestId))
|
|
408
|
+
continue;
|
|
409
|
+
return {
|
|
410
|
+
turns: turns.slice(index + 1),
|
|
411
|
+
previousStartedAt: turns[index].startedAt,
|
|
412
|
+
anchored: true,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
turns: turns.slice(-1),
|
|
417
|
+
previousStartedAt: turns.length > 1 ? turns[turns.length - 2].startedAt : 0,
|
|
418
|
+
anchored: false,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* The transcript file this instance would be read from, or null (Issue #2246).
|
|
423
|
+
*
|
|
424
|
+
* The same two steps {@link captureClaudeTranscriptTurn} opens with — resolve
|
|
425
|
+
* the session pointer, then check the filesystem — asked without reading or
|
|
426
|
+
* writing anything. The Stop receiver uses it to decide whether waiting half a
|
|
427
|
+
* second and asking again could possibly help: a session with no transcript to
|
|
428
|
+
* name will not have grown one by then, and a hook handler that sleeps for
|
|
429
|
+
* nothing is a hook handler that slows every turn of every tool.
|
|
430
|
+
*
|
|
431
|
+
* Never throws.
|
|
432
|
+
*/
|
|
433
|
+
async function resolveClaudeTranscriptPath(target, capture) {
|
|
434
|
+
try {
|
|
435
|
+
const homeDir = capture.homeDir ?? (0, os_1.homedir)();
|
|
436
|
+
if (typeof capture.worktreePath !== 'string' || capture.worktreePath.length === 0) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
return await locateClaudeTranscript(homeDir, capture, await resolveClaudeSessionId(target));
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* The key for a body read with no prompt record in the window.
|
|
447
|
+
*
|
|
448
|
+
* `partial:` cannot be the prefix of a UUID, so this can never collide with
|
|
449
|
+
* `claudeTurnRequestId(promptUuid)` — which matters because the two mean
|
|
450
|
+
* different things to the client. A prompt-derived key is a promise that a row
|
|
451
|
+
* with the same id is coming; this one is a promise that no such row exists, so
|
|
452
|
+
* the bubble it draws is cleared by the session going idle rather than by a swap.
|
|
453
|
+
*/
|
|
454
|
+
function headlessClaudeTurnKey(sessionId) {
|
|
455
|
+
return (0, agent_transcript_1.claudeTurnRequestId)(`partial:${sessionId}`);
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Everything the window holds for a turn whose prompt record is outside it.
|
|
459
|
+
*
|
|
460
|
+
* Built here rather than in `buildClaudeTurns` on purpose: that function drops
|
|
461
|
+
* orphaned records for a stated reason — their text must never be attached to an
|
|
462
|
+
* invented turn key, because an invented key is a row no later run can recognise
|
|
463
|
+
* as already written. That argument is about **writing**, and this path writes
|
|
464
|
+
* nothing. So the records are gathered separately, into an accumulator that is
|
|
465
|
+
* rendered by the same `renderClaudeTurn` and never handed to a writer.
|
|
466
|
+
*
|
|
467
|
+
* Only the records before the first prompt record are taken, which is exactly
|
|
468
|
+
* the set `buildClaudeTurns` counted as orphaned.
|
|
469
|
+
*/
|
|
470
|
+
function collectHeadlessClaudeTurn(records, sessionId) {
|
|
471
|
+
const blocks = [];
|
|
472
|
+
let assistantRecords = 0;
|
|
473
|
+
let overflowed = false;
|
|
474
|
+
for (const record of records) {
|
|
475
|
+
if ((0, transcript_1.isClaudePromptRecord)(record))
|
|
476
|
+
break;
|
|
477
|
+
if (record.isSidechain || record.type !== 'assistant')
|
|
478
|
+
continue;
|
|
479
|
+
assistantRecords += 1;
|
|
480
|
+
for (const block of record.blocks) {
|
|
481
|
+
if (blocks.length >= transcript_1.MAX_CLAUDE_TURN_BLOCKS) {
|
|
482
|
+
overflowed = true;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
blocks.push(block);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
sessionId,
|
|
490
|
+
promptUuid: `partial:${sessionId}`,
|
|
491
|
+
startedAt: 0,
|
|
492
|
+
promptText: '',
|
|
493
|
+
promptIsOperatorInput: false,
|
|
494
|
+
blocks,
|
|
495
|
+
assistantRecords,
|
|
496
|
+
overflowed,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Read the turn that is open right now, without writing anything (Issue #2199).
|
|
501
|
+
*
|
|
502
|
+
* The read half of {@link captureClaudeTranscriptTurn}, and *only* the read
|
|
503
|
+
* half: no `chat_messages` row, no user row, no `broadcastMessage`. That
|
|
504
|
+
* separation is the whole safety argument for this function. The write path is
|
|
505
|
+
* idempotent because `findMessageByRequestId` answers for a `requestId` derived
|
|
506
|
+
* from the prompt record's `uuid`; running it on every poll tick of an
|
|
507
|
+
* unfinished turn would mean writing the reply as it grows and then finding the
|
|
508
|
+
* row already there, so the row would freeze at whatever the first tick saw.
|
|
509
|
+
* This path never reaches that code at all.
|
|
510
|
+
*
|
|
511
|
+
* The two also cannot fight over the file: both open it read-only, and the
|
|
512
|
+
* writer is Claude.
|
|
513
|
+
*
|
|
514
|
+
* Deliberately **not** gated on whether the turn has ended. It cannot be — the
|
|
515
|
+
* transcript has no end-of-turn record this reader could trust, which is why
|
|
516
|
+
* #2121 put the trigger in the poller. The caller supplies that judgement (it
|
|
517
|
+
* asks only while the session is generating), and a body read from a turn that
|
|
518
|
+
* has just finished is harmless: the settled row carries the same
|
|
519
|
+
* {@link ClaudeTurnProgress.turnKey}, so the client replaces one with the other.
|
|
520
|
+
*
|
|
521
|
+
* Never throws.
|
|
522
|
+
*
|
|
523
|
+
* @param target - The instance whose turn is in flight
|
|
524
|
+
* @param capture - Where to look; the same {@link ClaudeTranscriptCapture} the writer takes
|
|
525
|
+
* @returns The open turn's body, or null when there is nothing to show yet
|
|
526
|
+
*/
|
|
527
|
+
async function readClaudeTurnProgress(target, capture) {
|
|
528
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
529
|
+
try {
|
|
530
|
+
const homeDir = capture.homeDir ?? (0, os_1.homedir)();
|
|
531
|
+
if (typeof capture.worktreePath !== 'string' || capture.worktreePath.length === 0) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
const sessionId = await resolveClaudeSessionId(target);
|
|
535
|
+
const path = await locateClaudeTranscript(homeDir, capture, sessionId);
|
|
536
|
+
if (!path)
|
|
537
|
+
return null;
|
|
538
|
+
const text = await readClaudeTranscriptTail(path);
|
|
539
|
+
if (text === null)
|
|
540
|
+
return null;
|
|
541
|
+
// A fragment at the tail of a file being appended to is the normal case here
|
|
542
|
+
// — this reader runs *while* Claude is writing — and `parseClaudeTranscript`
|
|
543
|
+
// already counts it rather than throwing. Nothing extra is needed, and that
|
|
544
|
+
// is the property `claude-transcript-progress-2199` pins.
|
|
545
|
+
const parsed = (0, transcript_1.parseClaudeTranscript)(text);
|
|
546
|
+
const built = (0, transcript_1.buildClaudeTurns)(parsed.records, sessionId ?? '');
|
|
547
|
+
const turn = built.turns.at(-1);
|
|
548
|
+
if (turn) {
|
|
549
|
+
const rendered = (0, transcript_1.renderClaudeTurn)(turn);
|
|
550
|
+
if (rendered.body.length === 0)
|
|
551
|
+
return null;
|
|
552
|
+
return {
|
|
553
|
+
turnKey: (0, agent_transcript_1.claudeTurnRequestId)(rendered.promptUuid),
|
|
554
|
+
body: rendered.body,
|
|
555
|
+
partial: false,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
// No prompt record anywhere in the window. See {@link ClaudeTurnProgress.partial}.
|
|
559
|
+
if (built.orphanedAssistantRecords === 0)
|
|
560
|
+
return null;
|
|
561
|
+
const headless = collectHeadlessClaudeTurn(parsed.records, sessionId ?? '');
|
|
562
|
+
const rendered = (0, transcript_1.renderClaudeTurn)(headless);
|
|
563
|
+
if (rendered.body.length === 0)
|
|
564
|
+
return null;
|
|
565
|
+
logger.info('claude-transcript-progress-headless', {
|
|
566
|
+
worktreeId: target.worktreeId,
|
|
567
|
+
instanceId,
|
|
568
|
+
path,
|
|
569
|
+
orphanedAssistantRecords: built.orphanedAssistantRecords,
|
|
570
|
+
malformedLines: parsed.malformedLines,
|
|
571
|
+
});
|
|
572
|
+
return {
|
|
573
|
+
turnKey: headlessClaudeTurnKey(sessionId ?? ''),
|
|
574
|
+
body: rendered.body,
|
|
575
|
+
partial: true,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
catch (error) {
|
|
579
|
+
logger.debug('claude-transcript-progress-failed', {
|
|
580
|
+
worktreeId: target.worktreeId,
|
|
581
|
+
instanceId,
|
|
582
|
+
error: error instanceof Error ? error.message : String(error),
|
|
583
|
+
});
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Record the prompt this turn answers, before the reply is written (Issue #2196).
|
|
589
|
+
*
|
|
590
|
+
* Ordering is the reason this is a separate call and not a branch inside
|
|
591
|
+
* {@link writeClaudeTurn}: the user row has to exist *before* the assistant row
|
|
592
|
+
* so that {@link resolveAssistantTimestampMs} can put the reply after it, and so
|
|
593
|
+
* that a browser watching the broadcast sees a prompt appear and then an answer
|
|
594
|
+
* rather than the other way round.
|
|
595
|
+
*
|
|
596
|
+
* A turn whose prompt was not the operator's — a `<task-notification>`, a
|
|
597
|
+
* compaction summary, a headless `sdk` run; see `isClaudeOperatorPromptRecord` —
|
|
598
|
+
* is skipped and said so in the log. The assistant row is still written: the
|
|
599
|
+
* agent really did reply, and #2121's behaviour for those turns is unchanged.
|
|
600
|
+
*
|
|
601
|
+
* Never throws; `recordUserTurn` reports its failures in the return value.
|
|
602
|
+
*
|
|
603
|
+
* @param previousStartedAt - When the turn before this one opened, or 0. Widens
|
|
604
|
+
* `/send` adoption backwards to that instant (Issue #2246): a prompt the agent
|
|
605
|
+
* queued for eleven minutes is still the row CommandMate wrote when it sent
|
|
606
|
+
* the text, and #2196's symmetric two-minute window cannot reach it. Never
|
|
607
|
+
* narrows — see {@link RecordUserTurnOptions}.
|
|
608
|
+
*/
|
|
609
|
+
async function recordClaudeUserTurn(target, turn, previousStartedAt = 0) {
|
|
610
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
611
|
+
if (!turn.promptIsOperatorInput) {
|
|
612
|
+
logger.debug('claude-transcript-user-turn-skipped', {
|
|
613
|
+
worktreeId: target.worktreeId,
|
|
614
|
+
instanceId,
|
|
615
|
+
promptUuid: turn.promptUuid,
|
|
616
|
+
reason: 'not-operator-input',
|
|
617
|
+
});
|
|
618
|
+
return { outcome: 'skipped', messageId: null, timestampMs: null };
|
|
619
|
+
}
|
|
620
|
+
const adoption = previousStartedAt > 0 ? { adoptionFromMs: previousStartedAt } : {};
|
|
621
|
+
const recorded = await (0, user_turn_recorder_1.recordUserTurn)(target, (0, agent_transcript_1.claudePromptRequestId)(turn.promptUuid), turn.promptText, turn.startedAt, adoption);
|
|
622
|
+
if (recorded.outcome === 'failed') {
|
|
623
|
+
logger.warn('claude-transcript-user-turn-failed', {
|
|
624
|
+
worktreeId: target.worktreeId,
|
|
625
|
+
instanceId,
|
|
626
|
+
sessionId: turn.sessionId,
|
|
627
|
+
promptUuid: turn.promptUuid,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
return recorded;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* When the assistant row for this turn is dated.
|
|
634
|
+
*
|
|
635
|
+
* #2121 dated it by the prompt record's clock so that a row written a poll late
|
|
636
|
+
* still sorts where the conversation put it, and that is still what happens for
|
|
637
|
+
* every turn that produced no user row.
|
|
638
|
+
*
|
|
639
|
+
* When there *is* a user row, it sits on that same instant — both come from the
|
|
640
|
+
* one prompt record — and `groupMessagesIntoPairs` orders by timestamp and
|
|
641
|
+
* nothing else. A tie there is decided by whichever row the database happened to
|
|
642
|
+
* return first, and the losing arrangement (assistant, then user) is exactly the
|
|
643
|
+
* `orphan` pair this Issue exists to remove. So the reply is moved to the first
|
|
644
|
+
* millisecond after the prompt: the smallest change that makes the order a
|
|
645
|
+
* property of the data rather than of the query plan.
|
|
646
|
+
*/
|
|
647
|
+
function resolveAssistantTimestampMs(turn, userRow) {
|
|
648
|
+
if (userRow.timestampMs === null)
|
|
649
|
+
return turn.startedAt;
|
|
650
|
+
return Math.max(turn.startedAt, userRow.timestampMs + 1);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* The transcript file for this instance, or null.
|
|
654
|
+
*
|
|
655
|
+
* The session pointer first, the pane's own claim second. Both are checked
|
|
656
|
+
* against the filesystem rather than trusted, because "the path we would use"
|
|
657
|
+
* and "the path that exists" differ for every session the operator started
|
|
658
|
+
* outside CommandMate.
|
|
659
|
+
*/
|
|
660
|
+
async function locateClaudeTranscript(homeDir, capture, sessionId) {
|
|
661
|
+
if (sessionId) {
|
|
662
|
+
const path = claudeTranscriptPath(homeDir, capture.worktreePath, sessionId);
|
|
663
|
+
if (await isReadableFile(path))
|
|
664
|
+
return path;
|
|
665
|
+
}
|
|
666
|
+
const hint = capture.transcriptPathHint;
|
|
667
|
+
if (typeof hint === 'string' && hint.length > 0) {
|
|
668
|
+
const accepted = acceptClaudeTranscriptHint(homeDir, hint);
|
|
669
|
+
if (accepted && (await isReadableFile(accepted)))
|
|
670
|
+
return accepted;
|
|
671
|
+
}
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
async function isReadableFile(path) {
|
|
675
|
+
try {
|
|
676
|
+
return (await (0, promises_1.stat)(path)).isFile();
|
|
677
|
+
}
|
|
678
|
+
catch {
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* The last {@link CLAUDE_TRANSCRIPT_TAIL_BYTES} of the file, as UTF-8.
|
|
684
|
+
*
|
|
685
|
+
* Read at an offset rather than whole, and the first line of a windowed read is
|
|
686
|
+
* dropped: starting mid-line would hand `parseClaudeTranscript` a fragment that
|
|
687
|
+
* it would count as malformed anyway, and dropping it deliberately keeps that
|
|
688
|
+
* counter meaning "the writer was mid-append", which is the thing worth seeing.
|
|
689
|
+
*
|
|
690
|
+
* @returns The text, or null when the file could not be read
|
|
691
|
+
*/
|
|
692
|
+
async function readClaudeTranscriptTail(path) {
|
|
693
|
+
let handle;
|
|
694
|
+
try {
|
|
695
|
+
handle = await (0, promises_1.open)(path, 'r');
|
|
696
|
+
const { size } = await handle.stat();
|
|
697
|
+
const offset = Math.max(0, size - exports.CLAUDE_TRANSCRIPT_TAIL_BYTES);
|
|
698
|
+
const length = size - offset;
|
|
699
|
+
if (length <= 0)
|
|
700
|
+
return '';
|
|
701
|
+
const buffer = Buffer.alloc(length);
|
|
702
|
+
const { bytesRead } = await handle.read(buffer, 0, length, offset);
|
|
703
|
+
const text = buffer.subarray(0, bytesRead).toString('utf8');
|
|
704
|
+
if (offset === 0)
|
|
705
|
+
return text;
|
|
706
|
+
const firstBreak = text.indexOf('\n');
|
|
707
|
+
return firstBreak === -1 ? '' : text.slice(firstBreak + 1);
|
|
708
|
+
}
|
|
709
|
+
catch (error) {
|
|
710
|
+
logger.warn('claude-transcript-read-failed', {
|
|
711
|
+
path,
|
|
712
|
+
error: error instanceof Error ? error.message : String(error),
|
|
713
|
+
});
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
finally {
|
|
717
|
+
await handle?.close().catch(() => { });
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Write one rendered turn, unless it is already there.
|
|
722
|
+
*
|
|
723
|
+
* `findMessageByRequestId` is both the idempotency check and the reason a
|
|
724
|
+
* repeat poll does not duplicate the row: the id is derived from the prompt
|
|
725
|
+
* record's `uuid`, which does not change between reads of the same file.
|
|
726
|
+
*
|
|
727
|
+
* Answering **true** for a turn that was already saved is deliberate. It means
|
|
728
|
+
* "History holds this turn as Markdown", which is exactly what the poller needs
|
|
729
|
+
* to know — a second poll of the same finished turn must not save the pane's
|
|
730
|
+
* copy on top of the row this path wrote for it.
|
|
731
|
+
*
|
|
732
|
+
* @returns Whether History holds this turn as the agent's own Markdown
|
|
733
|
+
*/
|
|
734
|
+
async function writeClaudeTurn(target, rendered, timestampMs, path) {
|
|
735
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
736
|
+
if (rendered.body.length === 0) {
|
|
737
|
+
// The turn is open but the agent has not written anything to the file yet —
|
|
738
|
+
// the prompt record is there and the assistant records are not. Answering
|
|
739
|
+
// false hands the turn back to the scraper, which is the only correct
|
|
740
|
+
// answer: an empty row would show as a blank reply forever, and suppressing
|
|
741
|
+
// the scrape would lose the reply outright.
|
|
742
|
+
logger.info('claude-transcript-turn-empty', {
|
|
743
|
+
worktreeId: target.worktreeId,
|
|
744
|
+
instanceId,
|
|
745
|
+
sessionId: rendered.sessionId,
|
|
746
|
+
promptUuid: rendered.promptUuid,
|
|
747
|
+
});
|
|
748
|
+
return false;
|
|
749
|
+
}
|
|
750
|
+
if (rendered.unknownBlockTypes.length > 0) {
|
|
751
|
+
logger.info('claude-transcript-unknown-blocks', {
|
|
752
|
+
worktreeId: target.worktreeId,
|
|
753
|
+
instanceId,
|
|
754
|
+
sessionId: rendered.sessionId,
|
|
755
|
+
blockTypes: rendered.unknownBlockTypes,
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
const requestId = (0, agent_transcript_1.claudeTurnRequestId)(rendered.promptUuid);
|
|
759
|
+
const [{ getDbInstance }, { createMessage, findMessageByRequestId }, { broadcastMessage }] = await Promise.all([
|
|
760
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
761
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
762
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
|
|
763
|
+
]);
|
|
764
|
+
const db = getDbInstance();
|
|
765
|
+
if (findMessageByRequestId(db, target.worktreeId, requestId)) {
|
|
766
|
+
logger.debug('claude-transcript-turn-already-saved', {
|
|
767
|
+
worktreeId: target.worktreeId,
|
|
768
|
+
instanceId,
|
|
769
|
+
requestId,
|
|
770
|
+
});
|
|
771
|
+
return true;
|
|
772
|
+
}
|
|
773
|
+
const message = createMessage(db, {
|
|
774
|
+
worktreeId: target.worktreeId,
|
|
775
|
+
role: 'assistant',
|
|
776
|
+
content: rendered.body,
|
|
777
|
+
messageType: 'normal',
|
|
778
|
+
// The agent's own clock, from the prompt record's `timestamp`, so a row
|
|
779
|
+
// written a poll late still sorts where the conversation put it.
|
|
780
|
+
timestamp: new Date(timestampMs > 0 ? timestampMs : Date.now()),
|
|
781
|
+
cliToolId: target.cliToolId,
|
|
782
|
+
instanceId,
|
|
783
|
+
requestId,
|
|
784
|
+
});
|
|
785
|
+
broadcastMessage('message', { worktreeId: target.worktreeId, message });
|
|
786
|
+
logger.info('claude-transcript-turn-saved', {
|
|
787
|
+
worktreeId: target.worktreeId,
|
|
788
|
+
instanceId,
|
|
789
|
+
sessionId: rendered.sessionId,
|
|
790
|
+
requestId,
|
|
791
|
+
path,
|
|
792
|
+
bodyLength: rendered.body.length,
|
|
793
|
+
textBlocks: rendered.textBlocks,
|
|
794
|
+
toolBlocks: rendered.toolBlocks,
|
|
795
|
+
});
|
|
796
|
+
return true;
|
|
797
|
+
}
|