commandmate 0.33.1 → 0.33.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +290 -290
- package/.next/app-path-routes-manifest.json +29 -29
- package/.next/build-manifest.json +5 -5
- package/.next/diagnostics/framework.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.json +1 -2
- 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_client-reference-manifest.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.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 +32 -1
- 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 +33 -2
- 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.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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +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/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[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.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/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.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +103 -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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/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_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 +8 -8
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +29 -29
- package/.next/server/chunks/1068.js +1 -0
- package/.next/server/chunks/1210.js +1 -1
- package/.next/server/chunks/1331.js +2 -2
- package/.next/server/chunks/1366.js +5 -3
- package/.next/server/chunks/1886.js +2 -2
- package/.next/server/chunks/2839.js +1 -0
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3323.js +1 -0
- package/.next/server/chunks/3707.js +1 -1
- package/.next/server/chunks/3708.js +1 -1
- package/.next/server/chunks/4443.js +1 -1
- package/.next/server/chunks/5220.js +1 -1
- package/.next/server/chunks/595.js +2 -2
- package/.next/server/chunks/650.js +1 -0
- package/.next/server/chunks/6781.js +1 -0
- package/.next/server/chunks/6808.js +1 -0
- package/.next/server/chunks/6838.js +1 -1
- package/.next/server/chunks/7875.js +3 -3
- package/.next/server/chunks/8918.js +107 -5
- package/.next/server/middleware-build-manifest.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.map +1 -1
- package/.next/static/chunks/1255-7e5873f06b25e129.js +1 -0
- package/.next/static/chunks/{4718-2bc5cdf06573bf54.js → 4718-441a2af91f0374e9.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-38edcd53e51f53b0.js +1 -0
- package/.next/static/chunks/{main-6092074a0dc78280.js → main-ac91ed6e71380841.js} +1 -1
- package/.next/trace +13 -14
- package/dist/server/src/lib/assistant-response-saver.js +168 -12
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +204 -9
- package/dist/server/src/lib/hooks/sources/claude/history.js +29 -3
- package/dist/server/src/lib/hooks/sources/codex/history.js +29 -3
- package/dist/server/src/lib/hooks/sources/command-code/history.js +29 -3
- package/dist/server/src/lib/hooks/stop-history-capture.js +30 -4
- package/dist/server/src/lib/polling/response-checker.js +258 -9
- package/dist/server/src/lib/polling/response-poller-core.js +20 -0
- package/dist/server/src/lib/polling/structured-history-gate.js +26 -6
- package/dist/server/src/lib/response-cleaner.js +84 -0
- package/package.json +2 -2
- package/.next/server/chunks/21.js +0 -1
- package/.next/server/chunks/3086.js +0 -1
- package/.next/server/chunks/3270.js +0 -1
- package/.next/server/chunks/3925.js +0 -1
- package/.next/server/chunks/5043.js +0 -1
- package/.next/server/chunks/6306.js +0 -1
- package/.next/server/chunks/6363.js +0 -1
- package/.next/server/chunks/6491.js +0 -103
- package/.next/server/chunks/7890.js +0 -1
- package/.next/server/chunks/8063.js +0 -32
- package/.next/server/chunks/8687.js +0 -1
- package/.next/static/chunks/1255-8cb587d9170b45ed.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-13ca0ba551fe5cfb.js +0 -1
- /package/.next/static/{9lgw9hA727UMyFhXryGWG → 0a4qrU8WdUwQrlO4mfLMu}/_buildManifest.js +0 -0
- /package/.next/static/{9lgw9hA727UMyFhXryGWG → 0a4qrU8WdUwQrlO4mfLMu}/_ssgManifest.js +0 -0
|
@@ -18,9 +18,43 @@
|
|
|
18
18
|
* buffer, which is false for alternate-screen tools — those are handled by the
|
|
19
19
|
* response poller instead (Issue #1268 / #1292; see savePendingAssistantResponse).
|
|
20
20
|
*/
|
|
21
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
24
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
25
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(o, k2, desc);
|
|
28
|
+
}) : (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
o[k2] = m[k];
|
|
31
|
+
}));
|
|
32
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
33
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34
|
+
}) : function(o, v) {
|
|
35
|
+
o["default"] = v;
|
|
36
|
+
});
|
|
37
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
38
|
+
var ownKeys = function(o) {
|
|
39
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
40
|
+
var ar = [];
|
|
41
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
42
|
+
return ar;
|
|
43
|
+
};
|
|
44
|
+
return ownKeys(o);
|
|
45
|
+
};
|
|
46
|
+
return function (mod) {
|
|
47
|
+
if (mod && mod.__esModule) return mod;
|
|
48
|
+
var result = {};
|
|
49
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
50
|
+
__setModuleDefault(result, mod);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
21
54
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
55
|
exports.detectBufferReset = detectBufferReset;
|
|
23
56
|
exports.cleanCliResponse = cleanCliResponse;
|
|
57
|
+
exports.advanceCapturedLineForTranscriptTurn = advanceCapturedLineForTranscriptTurn;
|
|
24
58
|
exports.savePendingAssistantResponse = savePendingAssistantResponse;
|
|
25
59
|
const cli_session_1 = require("./session/cli-session");
|
|
26
60
|
const db_1 = require("./db");
|
|
@@ -82,6 +116,31 @@ function detectBufferReset(currentLineCount, lastCapturedLine) {
|
|
|
82
116
|
}
|
|
83
117
|
return { bufferReset: false, reason: null };
|
|
84
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* How many rows of a capture count as "read so far".
|
|
121
|
+
*
|
|
122
|
+
* Trailing blank rows are discarded, for consistency with the response poller's
|
|
123
|
+
* `extractResponse`: tmux pads the pane out to its height, and counting that
|
|
124
|
+
* padding inflates the stored cursor so far past the real content that the
|
|
125
|
+
* poller's dedup check (`result.lineCount <= lastCapturedLine`) can never fire
|
|
126
|
+
* again.
|
|
127
|
+
*
|
|
128
|
+
* The one definition of the count, shared by the two writers of
|
|
129
|
+
* `session_states.last_captured_line` in this module (Issue #2437): the
|
|
130
|
+
* pre-send flush and {@link advanceCapturedLineForTranscriptTurn}. Two spellings
|
|
131
|
+
* of "how far have I read" would be two cursors that disagree.
|
|
132
|
+
*
|
|
133
|
+
* @param output - Raw capture
|
|
134
|
+
* @returns Row count with trailing blank rows removed
|
|
135
|
+
*/
|
|
136
|
+
function countCapturedLines(output) {
|
|
137
|
+
const lines = output.split('\n');
|
|
138
|
+
let trimmedLength = lines.length;
|
|
139
|
+
while (trimmedLength > 0 && lines[trimmedLength - 1].trim() === '') {
|
|
140
|
+
trimmedLength--;
|
|
141
|
+
}
|
|
142
|
+
return trimmedLength;
|
|
143
|
+
}
|
|
85
144
|
/**
|
|
86
145
|
* Time offset (in milliseconds) for assistant message timestamp
|
|
87
146
|
* Ensures assistant response appears before user message in chronological order
|
|
@@ -91,8 +150,23 @@ const ASSISTANT_TIMESTAMP_OFFSET_MS = 1;
|
|
|
91
150
|
/**
|
|
92
151
|
* Clean CLI tool response based on tool type
|
|
93
152
|
*
|
|
153
|
+
* Every one of `CLI_TOOL_IDS`' eight tools has a branch (Issue #2437). Until
|
|
154
|
+
* then four of them — codex, command-code, antigravity and vibe-local — fell
|
|
155
|
+
* through to `output.trim()`, and codex's branch said so in as many words:
|
|
156
|
+
* *"Codex doesn't need special cleaning"*. It does. What that branch actually
|
|
157
|
+
* saved was codex's **idle composer**, ANSI and all, as an assistant reply:
|
|
158
|
+
*
|
|
159
|
+
* ```text
|
|
160
|
+
* › Ask Codex to do anything
|
|
161
|
+
*
|
|
162
|
+
* gpt-6-astra xhigh · ~/share/work/… · Main [default]
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* See {@link cleanScrollbackResponse} for how the four share one cleaner
|
|
166
|
+
* without sharing a boundary rule.
|
|
167
|
+
*
|
|
94
168
|
* @param output - Raw output from CLI tool
|
|
95
|
-
* @param cliToolId - CLI tool identifier
|
|
169
|
+
* @param cliToolId - CLI tool identifier
|
|
96
170
|
* @returns Cleaned response content
|
|
97
171
|
*/
|
|
98
172
|
function cleanCliResponse(output, cliToolId) {
|
|
@@ -106,12 +180,101 @@ function cleanCliResponse(output, cliToolId) {
|
|
|
106
180
|
case 'copilot':
|
|
107
181
|
return (0, response_cleaner_1.cleanCopilotResponse)(output);
|
|
108
182
|
case 'codex':
|
|
109
|
-
|
|
110
|
-
|
|
183
|
+
case 'command-code':
|
|
184
|
+
case 'antigravity':
|
|
185
|
+
case 'vibe-local':
|
|
186
|
+
return (0, response_cleaner_1.cleanScrollbackResponse)(output, cliToolId);
|
|
111
187
|
default:
|
|
112
188
|
return output.trim();
|
|
113
189
|
}
|
|
114
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Move `last_captured_line` past everything a transcript row now covers
|
|
193
|
+
* (Issue #2437).
|
|
194
|
+
*
|
|
195
|
+
* ## The defect this closes
|
|
196
|
+
*
|
|
197
|
+
* The pre-send flush ({@link savePendingAssistantResponse}) reads
|
|
198
|
+
* `lastCapturedLine`, and saves **everything past it** as the pending reply. The
|
|
199
|
+
* only writer of that cursor used to be the flush itself and the response
|
|
200
|
+
* poller — the Stop path that writes the agent's OWN Markdown into History
|
|
201
|
+
* (`hooks/sources/<tool>/history.ts`) never touched it. So on this ordering, which
|
|
202
|
+
* costs nothing to hit at a 2-second poll interval:
|
|
203
|
+
*
|
|
204
|
+
* ```text
|
|
205
|
+
* 1. turn ends → the Stop path writes the turn as a Markdown row (cursor unmoved)
|
|
206
|
+
* 2. `/send` arrives BEFORE the next poll tick
|
|
207
|
+
* 3. the flush saves "everything since the cursor" = the whole finished turn
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* The second copy is the pane's scrape of the very same turn, so the chat
|
|
211
|
+
* surface shows one reply twice. A cleaner cannot help: what is duplicated is
|
|
212
|
+
* the real body, not chrome.
|
|
213
|
+
*
|
|
214
|
+
* ## Why a capture rather than an arithmetic bump
|
|
215
|
+
*
|
|
216
|
+
* The cursor is a row index into the pane, and the transcript reader never looks
|
|
217
|
+
* at the pane at all — it reads a JSONL file. The only honest way to say "the
|
|
218
|
+
* pane up to here is already in History" is to ask the pane how tall it is now.
|
|
219
|
+
* The capture is the cached one ({@link captureSessionOutput}, 5s TTL shared
|
|
220
|
+
* with the poller), so a Stop that lands between two ticks usually costs no
|
|
221
|
+
* `tmux capture-pane` at all.
|
|
222
|
+
*
|
|
223
|
+
* ## What it deliberately does not do
|
|
224
|
+
*
|
|
225
|
+
* - **Alternate-screen tools are skipped.** For claude, opencode and copilot the
|
|
226
|
+
* line count is a screen-row constant rather than a cursor (Issue #1268), and
|
|
227
|
+
* {@link savePendingAssistantResponse} refuses to run for them at all — there
|
|
228
|
+
* is no cursor here to advance and writing one would be a lie.
|
|
229
|
+
* - **The cursor only ever moves forward.** A capture shorter than the stored
|
|
230
|
+
* value is a buffer reset, and `detectBufferReset` owns that reading; moving
|
|
231
|
+
* the cursor backwards from here would hand the flush a range it has already
|
|
232
|
+
* saved.
|
|
233
|
+
* - **It never throws, and never changes the caller's answer.** The transcript
|
|
234
|
+
* row is written whether or not this succeeds; a failure here costs one
|
|
235
|
+
* duplicated reply, and a failure that propagated would cost the row.
|
|
236
|
+
*
|
|
237
|
+
* @param target - The instance whose turn was just written to History
|
|
238
|
+
* @returns The cursor's new value, or null when it was left where it was
|
|
239
|
+
*/
|
|
240
|
+
async function advanceCapturedLineForTranscriptTurn(target) {
|
|
241
|
+
const { worktreeId, cliToolId } = target;
|
|
242
|
+
const resolvedInstanceId = target.instanceId ?? cliToolId;
|
|
243
|
+
try {
|
|
244
|
+
if ((0, types_1.usesAlternateScreen)(cliToolId)) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const output = await (0, cli_session_1.captureSessionOutput)(worktreeId, cliToolId, SESSION_OUTPUT_BUFFER_SIZE, target.instanceId);
|
|
248
|
+
if (!output) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const currentLineCount = countCapturedLines(output);
|
|
252
|
+
const { getDbInstance } = await Promise.resolve().then(() => __importStar(require('./db/db-instance')));
|
|
253
|
+
const db = getDbInstance();
|
|
254
|
+
const lastCapturedLine = (0, db_1.getSessionState)(db, worktreeId, resolvedInstanceId)?.lastCapturedLine || 0;
|
|
255
|
+
if (currentLineCount <= lastCapturedLine) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
(0, db_1.updateSessionState)(db, worktreeId, cliToolId, currentLineCount, target.instanceId);
|
|
259
|
+
logger.info('transcript:cursor-advanced', {
|
|
260
|
+
worktreeId,
|
|
261
|
+
instanceId: resolvedInstanceId,
|
|
262
|
+
from: lastCapturedLine,
|
|
263
|
+
to: currentLineCount,
|
|
264
|
+
});
|
|
265
|
+
return currentLineCount;
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
// Never the caller's problem: the transcript row is already written, and the
|
|
269
|
+
// worst this costs is the duplicate it was meant to prevent.
|
|
270
|
+
logger.debug('transcript:cursor-advance-failed', {
|
|
271
|
+
worktreeId,
|
|
272
|
+
instanceId: resolvedInstanceId,
|
|
273
|
+
error: error instanceof Error ? error.message : String(error),
|
|
274
|
+
});
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
115
278
|
/**
|
|
116
279
|
* Save pending assistant response before a new user message
|
|
117
280
|
*
|
|
@@ -170,16 +333,9 @@ async function savePendingAssistantResponse(db, worktreeId, cliToolId, userMessa
|
|
|
170
333
|
if (!output) {
|
|
171
334
|
return null;
|
|
172
335
|
}
|
|
173
|
-
// 3. Calculate current line count
|
|
174
|
-
// Trim trailing empty lines for consistency with response-poller's extractResponse.
|
|
175
|
-
// Without this, tmux buffer padding inflates the line count, causing the poller's
|
|
176
|
-
// dedup check (result.lineCount <= lastCapturedLine) to always trigger.
|
|
336
|
+
// 3. Calculate current line count (see countCapturedLines for the trim).
|
|
177
337
|
const lines = output.split('\n');
|
|
178
|
-
|
|
179
|
-
while (trimmedLength > 0 && lines[trimmedLength - 1].trim() === '') {
|
|
180
|
-
trimmedLength--;
|
|
181
|
-
}
|
|
182
|
-
const currentLineCount = trimmedLength;
|
|
338
|
+
const currentLineCount = countCapturedLines(output);
|
|
183
339
|
// 4. Detect buffer reset (Issue #59 fix)
|
|
184
340
|
const { bufferReset, reason } = detectBufferReset(currentLineCount, lastCapturedLine);
|
|
185
341
|
if (bufferReset) {
|
|
@@ -91,7 +91,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
91
91
|
};
|
|
92
92
|
})();
|
|
93
93
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
94
|
-
exports.ANTIGRAVITY_CLI_HOME_SEGMENTS = exports.ANTIGRAVITY_TRANSCRIPT_TAIL_BYTES = void 0;
|
|
94
|
+
exports.ANTIGRAVITY_TURN_RECHECK_LIMIT = exports.ANTIGRAVITY_CLI_HOME_SEGMENTS = exports.ANTIGRAVITY_TRANSCRIPT_TAIL_BYTES = void 0;
|
|
95
95
|
exports.resetAntigravityTranscriptConversations = resetAntigravityTranscriptConversations;
|
|
96
96
|
exports.resolveAntigravityConversationId = resolveAntigravityConversationId;
|
|
97
97
|
exports.resolveAntigravityHome = resolveAntigravityHome;
|
|
@@ -106,6 +106,7 @@ const path_1 = require("path");
|
|
|
106
106
|
const auto_yes_state_1 = require("../../../../lib/auto-yes-state");
|
|
107
107
|
const transcript_tail_1 = require("../../../../lib/history/transcript-tail");
|
|
108
108
|
const user_turn_recorder_1 = require("../../../../lib/history/user-turn-recorder");
|
|
109
|
+
const assistant_response_saver_1 = require("../../../../lib/assistant-response-saver");
|
|
109
110
|
const logger_1 = require("../../../../lib/logger");
|
|
110
111
|
const agent_transcript_1 = require("../../../../types/agent-transcript");
|
|
111
112
|
const transcript_1 = require("./transcript");
|
|
@@ -288,11 +289,29 @@ function acceptAntigravityTranscriptPath(agyHome, candidate) {
|
|
|
288
289
|
*
|
|
289
290
|
* Never throws.
|
|
290
291
|
*
|
|
292
|
+
* **A row this reader wrote is not final (Issue #2438).** Before anything is
|
|
293
|
+
* written, the newest already-written turns — at most
|
|
294
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT} of them — are re-rendered and compared
|
|
295
|
+
* against the rows they produced, and a row whose turn now renders *strictly
|
|
296
|
+
* longer* is replaced in place. agy has no record that closes a turn, so an
|
|
297
|
+
* interim report reads as a finished answer (`isAntigravityTurnClosingRecord`)
|
|
298
|
+
* and used to freeze a half-written reply into History forever. That is a
|
|
299
|
+
* repair and not a second verdict: growing an older row changes neither the
|
|
300
|
+
* return value nor `report`, both of which are about the **newest** turn.
|
|
301
|
+
*
|
|
302
|
+
* Since Issue #2436 the false can explain itself: pass a
|
|
303
|
+
* `StructuredHistoryCaptureReport` and `outcome` is set to `'not_yet_closed'`
|
|
304
|
+
* when the newest turn is one the agent has not finished writing — the case the
|
|
305
|
+
* `-turn-open` line below reports, and the one where the caller's scraped copy
|
|
306
|
+
* is worth holding rather than saving. Every other false leaves it unset, which
|
|
307
|
+
* the gate reads as `'unavailable'`.
|
|
308
|
+
*
|
|
291
309
|
* @param target - The instance whose turn just ended
|
|
292
310
|
* @param capture - See {@link AntigravityTranscriptCapture}
|
|
311
|
+
* @param report - Optional out-parameter; see `StructuredHistoryCaptureReport`
|
|
293
312
|
* @returns Whether History now holds this turn as the agent's own Markdown
|
|
294
313
|
*/
|
|
295
|
-
async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
314
|
+
async function captureAntigravityTranscriptTurn(target, capture = {}, report) {
|
|
296
315
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
297
316
|
try {
|
|
298
317
|
const agyHome = capture.antigravityHome ?? resolveAntigravityHome();
|
|
@@ -348,12 +367,26 @@ async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
|
348
367
|
});
|
|
349
368
|
}
|
|
350
369
|
const pending = await selectUnwrittenAntigravityTurns(target, built.turns);
|
|
370
|
+
// Before anything is written: the rows that are already there (#2438). This
|
|
371
|
+
// is deliberately ahead of the early return below, because "the newest turn
|
|
372
|
+
// is already a row" is exactly the state the frozen row the Issue measured
|
|
373
|
+
// was stuck in — agy said "waiting for the worker", the writer saved that,
|
|
374
|
+
// and every later read answered true and did nothing while the conclusion
|
|
375
|
+
// sat in the transcript beside it. Written turns are re-checked whether or
|
|
376
|
+
// not anything is pending, so an old turn can be repaired in the same pass
|
|
377
|
+
// that writes a new one.
|
|
378
|
+
await refreshAntigravityTurnRows(target, built.turns
|
|
379
|
+
.slice(0, built.turns.length - pending.turns.length)
|
|
380
|
+
.slice(-exports.ANTIGRAVITY_TURN_RECHECK_LIMIT), path);
|
|
351
381
|
if (pending.turns.length === 0) {
|
|
352
382
|
logger.debug('antigravity-transcript-turns-already-saved', {
|
|
353
383
|
worktreeId: target.worktreeId,
|
|
354
384
|
instanceId,
|
|
355
385
|
turnsInWindow: built.turns.length,
|
|
356
386
|
});
|
|
387
|
+
// Issue #2437: this turn is already History's Markdown, so the pane rows
|
|
388
|
+
// behind it must stop being "unsaved output" the pre-send flush can pick up.
|
|
389
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
357
390
|
return true;
|
|
358
391
|
}
|
|
359
392
|
if (pending.turns.length > 1) {
|
|
@@ -380,7 +413,14 @@ async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
|
380
413
|
let captured = false;
|
|
381
414
|
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
382
415
|
const turn = pending.turns[index];
|
|
383
|
-
captured = await writeAntigravityTurn(target, turn, (0, transcript_1.renderAntigravityTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastAntigravityRecordAt(turn), nextTurnOpensAt(pending.turns, userRows, index)), path);
|
|
416
|
+
captured = await writeAntigravityTurn(target, turn, (0, transcript_1.renderAntigravityTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastAntigravityRecordAt(turn), nextTurnOpensAt(pending.turns, userRows, index)), path, report);
|
|
417
|
+
}
|
|
418
|
+
if (captured) {
|
|
419
|
+
// Issue #2437: History now holds this turn as the agent's own Markdown.
|
|
420
|
+
// Park the pre-send flush's cursor past the pane rows it covers, or a
|
|
421
|
+
// `/send` arriving before the next poll tick saves the whole finished turn
|
|
422
|
+
// a second time.
|
|
423
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
384
424
|
}
|
|
385
425
|
return captured;
|
|
386
426
|
}
|
|
@@ -577,6 +617,137 @@ function nextTurnOpensAt(turns, userRows, index) {
|
|
|
577
617
|
return null;
|
|
578
618
|
return userRows[index + 1]?.timestampMs ?? next.startedAt;
|
|
579
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* How many already-written turns are re-rendered and compared (Issue #2438).
|
|
622
|
+
*
|
|
623
|
+
* The repair half of #2438 has to look at rows this reader has **already**
|
|
624
|
+
* written, which is the one thing the anchor rule of
|
|
625
|
+
* {@link selectUnwrittenAntigravityTurns} deliberately does not do — so it is
|
|
626
|
+
* bounded here rather than by the read window. Three, the number claude and
|
|
627
|
+
* command-code settled on in #2264 and for the same arithmetic: the poller runs
|
|
628
|
+
* every couple of seconds, re-rendering the whole window on every tick would
|
|
629
|
+
* make a repair the most expensive thing the poll does, and a turn that is going
|
|
630
|
+
* to grow grows within seconds of being written.
|
|
631
|
+
*
|
|
632
|
+
* The cost of the bound is paid by rows a session has already moved three turns
|
|
633
|
+
* past: those keep whatever they were written with. The measured case — one
|
|
634
|
+
* conversation whose only turn was `#0` — is inside it by a wide margin.
|
|
635
|
+
*/
|
|
636
|
+
exports.ANTIGRAVITY_TURN_RECHECK_LIMIT = 3;
|
|
637
|
+
/**
|
|
638
|
+
* Replace a saved row whose body has since grown (Issue #2438).
|
|
639
|
+
*
|
|
640
|
+
* The defect this exists for is not that the wrong body was written; it is that
|
|
641
|
+
* the row was written **early**. `isAntigravityTurnClosingRecord` reads prose
|
|
642
|
+
* with no `tool_calls` as agy finishing, and an interim report — "waiting for
|
|
643
|
+
* the worker" — has exactly that shape. The row is keyed
|
|
644
|
+
* `antigravity-turn:<conversationId>#<stepIndex>`, so once it exists every later
|
|
645
|
+
* read finds it, answers "already saved", and the gate suppresses the scrape
|
|
646
|
+
* that could have carried the conclusion instead. Nothing else in the system
|
|
647
|
+
* ever revisits that row.
|
|
648
|
+
*
|
|
649
|
+
* **Strictly longer, never merely different.** Equality is the ordinary case and
|
|
650
|
+
* must cost nothing, and a body that got *shorter* between two reads is not a
|
|
651
|
+
* turn that grew — it is a window that slid, or a truncation marker, and
|
|
652
|
+
* overwriting a full reply with a shorter one is the one outcome worse than the
|
|
653
|
+
* bug. Longer implies different, so one comparison covers both.
|
|
654
|
+
*
|
|
655
|
+
* Only `content` moves. The row's `id`, `request_id`, `timestamp`, worktree,
|
|
656
|
+
* tool and instance are what History sorts and pairs on, and a repair that
|
|
657
|
+
* disturbed any of them would move an old answer to the bottom of the
|
|
658
|
+
* conversation.
|
|
659
|
+
*
|
|
660
|
+
* `message_updated`, never `message`: the row already existed and was already
|
|
661
|
+
* delivered when it was created, so a client that appended instead of replacing
|
|
662
|
+
* would show the reply twice.
|
|
663
|
+
*
|
|
664
|
+
* @param existing - The row `findMessageByRequestId` answered with
|
|
665
|
+
* @returns Whether the row was replaced
|
|
666
|
+
*/
|
|
667
|
+
async function growAntigravityTurnRow(target, existing, rendered, path) {
|
|
668
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
669
|
+
// The stored body is the only evidence of what History holds, so a row that
|
|
670
|
+
// carries none is not evidence that anything grew. Same answer as "not
|
|
671
|
+
// longer": leave it alone. This runs inside the poller's save path, where the
|
|
672
|
+
// module contract is that nothing throws.
|
|
673
|
+
const previous = existing.content;
|
|
674
|
+
if (typeof previous !== 'string')
|
|
675
|
+
return false;
|
|
676
|
+
const previousLength = previous.length;
|
|
677
|
+
if (rendered.body.length <= previousLength)
|
|
678
|
+
return false;
|
|
679
|
+
const [{ getDbInstance }, { updateMessageContent }, { broadcastMessage }] = await Promise.all([
|
|
680
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
681
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
682
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
|
|
683
|
+
]);
|
|
684
|
+
updateMessageContent(getDbInstance(), existing.id, rendered.body);
|
|
685
|
+
broadcastMessage('message_updated', {
|
|
686
|
+
worktreeId: target.worktreeId,
|
|
687
|
+
message: { ...existing, content: rendered.body },
|
|
688
|
+
});
|
|
689
|
+
logger.info('antigravity-transcript-turn-updated', {
|
|
690
|
+
worktreeId: target.worktreeId,
|
|
691
|
+
instanceId,
|
|
692
|
+
conversationId: rendered.conversationId,
|
|
693
|
+
stepIndex: rendered.stepIndex,
|
|
694
|
+
requestId: existing.requestId,
|
|
695
|
+
path,
|
|
696
|
+
previousLength,
|
|
697
|
+
bodyLength: rendered.body.length,
|
|
698
|
+
textBlocks: rendered.textBlocks,
|
|
699
|
+
toolBlocks: rendered.toolBlocks,
|
|
700
|
+
});
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Re-read the newest already-written turns and grow the short ones (#2438).
|
|
705
|
+
*
|
|
706
|
+
* Runs before the pending turns are written and independently of whether there
|
|
707
|
+
* are any — the case it exists for is precisely the one
|
|
708
|
+
* {@link captureAntigravityTranscriptTurn} used to return `true` from without
|
|
709
|
+
* doing anything: the newest turn already has a row, and that row stopped at
|
|
710
|
+
* agy's interim report.
|
|
711
|
+
*
|
|
712
|
+
* Turns that are open again are skipped rather than compared. A turn whose last
|
|
713
|
+
* record is a `tool_calls` is one agy is still working through, its body is by
|
|
714
|
+
* definition not the final one, and a repair that raced the agent would rewrite
|
|
715
|
+
* the row on every poll of a long turn. **This is not a second chance to write
|
|
716
|
+
* a turn**: a candidate with no row is left alone, because the anchor rule
|
|
717
|
+
* already decided it is not this pass's to create.
|
|
718
|
+
*
|
|
719
|
+
* The database is asked before the turn is rendered, so a candidate with no row
|
|
720
|
+
* — every candidate, in a session this reader has never written to — costs one
|
|
721
|
+
* indexed lookup and no Markdown.
|
|
722
|
+
*
|
|
723
|
+
* Serialisation is the gate's, per instance: this adds no loop and no timer of
|
|
724
|
+
* its own, it is one more thing the poll's existing pass does.
|
|
725
|
+
*
|
|
726
|
+
* @param candidates - Already-written turns, oldest first, at most
|
|
727
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}
|
|
728
|
+
* @returns How many rows were replaced
|
|
729
|
+
*/
|
|
730
|
+
async function refreshAntigravityTurnRows(target, candidates, path) {
|
|
731
|
+
if (candidates.length === 0)
|
|
732
|
+
return 0;
|
|
733
|
+
const [{ getDbInstance }, { findMessageByRequestId }] = await Promise.all([
|
|
734
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
735
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
736
|
+
]);
|
|
737
|
+
const db = getDbInstance();
|
|
738
|
+
let updated = 0;
|
|
739
|
+
for (const turn of candidates) {
|
|
740
|
+
if (!(0, transcript_1.isAntigravityTurnWritable)(turn))
|
|
741
|
+
continue;
|
|
742
|
+
const existing = findMessageByRequestId(db, target.worktreeId, (0, agent_transcript_1.antigravityTurnRequestId)(turn.conversationId, turn.stepIndex));
|
|
743
|
+
if (!existing)
|
|
744
|
+
continue;
|
|
745
|
+
if (await growAntigravityTurnRow(target, existing, (0, transcript_1.renderAntigravityTurn)(turn), path)) {
|
|
746
|
+
updated += 1;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return updated;
|
|
750
|
+
}
|
|
580
751
|
/**
|
|
581
752
|
* Write one rendered turn, unless it is already there.
|
|
582
753
|
*
|
|
@@ -587,20 +758,36 @@ function nextTurnOpensAt(turns, userRows, index) {
|
|
|
587
758
|
* Answering **true** for a turn that was already saved is deliberate. It means
|
|
588
759
|
* "History holds this turn as Markdown", which is what the poller needs to know
|
|
589
760
|
* — a second poll of the same finished turn must not save the pane's copy on top
|
|
590
|
-
* of the row this path wrote.
|
|
761
|
+
* of the row this path wrote. Since #2438 that row is no longer left as it was
|
|
762
|
+
* found: it is the same comparison {@link growAntigravityTurnRow} makes for the
|
|
763
|
+
* turns the recheck window covers, made here where both the row and the turn
|
|
764
|
+
* are already in hand.
|
|
591
765
|
*
|
|
592
766
|
* @returns Whether History holds this turn as the agent's own Markdown
|
|
593
767
|
*/
|
|
594
|
-
async function writeAntigravityTurn(target, turn, rendered, timestampMs, path) {
|
|
768
|
+
async function writeAntigravityTurn(target, turn, rendered, timestampMs, path, report) {
|
|
595
769
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
770
|
+
// Issue #2436: the caller's report is about the turn THIS call is deciding.
|
|
771
|
+
// The loop above walks oldest-first, so a verdict left by an earlier turn has
|
|
772
|
+
// to be cleared before this one's is written.
|
|
773
|
+
if (report)
|
|
774
|
+
report.outcome = undefined;
|
|
596
775
|
if (!(0, transcript_1.isAntigravityTurnWritable)(turn)) {
|
|
597
776
|
// agy has not finished this answer and no later prompt has taken over, so
|
|
598
777
|
// what is in the file is a turn in progress. Writing it would put a reply
|
|
599
|
-
// with its last paragraph missing into History
|
|
600
|
-
//
|
|
601
|
-
//
|
|
778
|
+
// with its last paragraph missing into History — the row is keyed on
|
|
779
|
+
// `(conversationId, step_index)`, so every later read finds it and answers
|
|
780
|
+
// "already saved". That is Issue #2264, reported against claude and
|
|
602
781
|
// structurally identical here: a turn cut off after its `tool_calls` renders
|
|
603
782
|
// a *non-empty* body, so the emptiness guard below cannot see it.
|
|
783
|
+
//
|
|
784
|
+
// #2438 made such a row repairable rather than making it acceptable: a
|
|
785
|
+
// short row only grows while its turn is still among the newest
|
|
786
|
+
// {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}, and nothing at all rewinds what a
|
|
787
|
+
// relay already delivered from it. Not writing it in the first place is
|
|
788
|
+
// still the fix; the repair is the second line.
|
|
789
|
+
if (report)
|
|
790
|
+
report.outcome = 'not_yet_closed';
|
|
604
791
|
logger.info('antigravity-transcript-turn-open', {
|
|
605
792
|
worktreeId: target.worktreeId,
|
|
606
793
|
instanceId,
|
|
@@ -654,12 +841,20 @@ async function writeAntigravityTurn(target, turn, rendered, timestampMs, path) {
|
|
|
654
841
|
Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
|
|
655
842
|
]);
|
|
656
843
|
const db = getDbInstance();
|
|
657
|
-
|
|
844
|
+
const existing = findMessageByRequestId(db, target.worktreeId, requestId);
|
|
845
|
+
if (existing) {
|
|
658
846
|
logger.debug('antigravity-transcript-turn-already-saved', {
|
|
659
847
|
worktreeId: target.worktreeId,
|
|
660
848
|
instanceId,
|
|
661
849
|
requestId,
|
|
662
850
|
});
|
|
851
|
+
// The row may be one of the ones #2438 was reported for — saved at agy's
|
|
852
|
+
// interim report — and this is the one place that holds both the row and
|
|
853
|
+
// the turn. The comparison and the notification are not repeated here; see
|
|
854
|
+
// {@link growAntigravityTurnRow}. The verdict is unchanged: History holds
|
|
855
|
+
// this turn either way, and `report.outcome` is about this turn's
|
|
856
|
+
// completeness rather than about an edit.
|
|
857
|
+
await growAntigravityTurnRow(target, existing, rendered, path);
|
|
663
858
|
return true;
|
|
664
859
|
}
|
|
665
860
|
const message = createMessage(db, {
|
|
@@ -104,6 +104,7 @@ const os_1 = require("os");
|
|
|
104
104
|
const path_1 = require("path");
|
|
105
105
|
const auto_yes_state_1 = require("../../../../lib/auto-yes-state");
|
|
106
106
|
const user_turn_recorder_1 = require("../../../../lib/history/user-turn-recorder");
|
|
107
|
+
const assistant_response_saver_1 = require("../../../../lib/assistant-response-saver");
|
|
107
108
|
const logger_1 = require("../../../../lib/logger");
|
|
108
109
|
const agent_transcript_1 = require("../../../../types/agent-transcript");
|
|
109
110
|
const transcript_1 = require("./transcript");
|
|
@@ -266,10 +267,18 @@ function acceptClaudeTranscriptHint(homeDir, hint) {
|
|
|
266
267
|
*
|
|
267
268
|
* Never throws.
|
|
268
269
|
*
|
|
270
|
+
* Since Issue #2436 the false can explain itself: pass a
|
|
271
|
+
* `StructuredHistoryCaptureReport` and `outcome` is set to `'not_yet_closed'`
|
|
272
|
+
* when the newest turn is one the agent has not finished writing — the case the
|
|
273
|
+
* `-turn-open` line below reports, and the one where the caller's scraped copy
|
|
274
|
+
* is worth holding rather than saving. Every other false leaves it unset, which
|
|
275
|
+
* the gate reads as `'unavailable'`.
|
|
276
|
+
*
|
|
269
277
|
* @param target - The instance whose turn just ended
|
|
278
|
+
* @param report - Optional out-parameter; see `StructuredHistoryCaptureReport`
|
|
270
279
|
* @returns Whether History now holds this instance's newest turn as Markdown
|
|
271
280
|
*/
|
|
272
|
-
async function captureClaudeTranscriptTurn(target, capture) {
|
|
281
|
+
async function captureClaudeTranscriptTurn(target, capture, report) {
|
|
273
282
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
274
283
|
try {
|
|
275
284
|
const homeDir = capture.homeDir ?? (0, os_1.homedir)();
|
|
@@ -340,6 +349,9 @@ async function captureClaudeTranscriptTurn(target, capture) {
|
|
|
340
349
|
instanceId,
|
|
341
350
|
turnsInWindow: built.turns.length,
|
|
342
351
|
});
|
|
352
|
+
// Issue #2437: this turn is already History's Markdown, so the pane rows
|
|
353
|
+
// behind it must stop being "unsaved output" the pre-send flush can pick up.
|
|
354
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
343
355
|
return true;
|
|
344
356
|
}
|
|
345
357
|
if (pending.turns.length > 1) {
|
|
@@ -374,7 +386,14 @@ async function captureClaudeTranscriptTurn(target, capture) {
|
|
|
374
386
|
let captured = false;
|
|
375
387
|
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
376
388
|
const turn = pending.turns[index];
|
|
377
|
-
captured = await writeClaudeTurn(target, turn, (0, transcript_1.renderClaudeTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.promptUuid) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), path);
|
|
389
|
+
captured = await writeClaudeTurn(target, turn, (0, transcript_1.renderClaudeTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.promptUuid) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), path, report);
|
|
390
|
+
}
|
|
391
|
+
if (captured) {
|
|
392
|
+
// Issue #2437: History now holds this turn as the agent's own Markdown.
|
|
393
|
+
// Park the pre-send flush's cursor past the pane rows it covers, or a
|
|
394
|
+
// `/send` arriving before the next poll tick saves the whole finished turn
|
|
395
|
+
// a second time.
|
|
396
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
378
397
|
}
|
|
379
398
|
return captured;
|
|
380
399
|
}
|
|
@@ -925,8 +944,13 @@ async function refreshClaudeTurnRows(target, candidates, path) {
|
|
|
925
944
|
*
|
|
926
945
|
* @returns Whether History holds this turn as the agent's own Markdown
|
|
927
946
|
*/
|
|
928
|
-
async function writeClaudeTurn(target, turn, rendered, timestampMs, path) {
|
|
947
|
+
async function writeClaudeTurn(target, turn, rendered, timestampMs, path, report) {
|
|
929
948
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
949
|
+
// Issue #2436: the caller's report is about the turn THIS call is deciding.
|
|
950
|
+
// The loop above walks oldest-first, so a verdict left by an earlier turn has
|
|
951
|
+
// to be cleared before this one's is written.
|
|
952
|
+
if (report)
|
|
953
|
+
report.outcome = undefined;
|
|
930
954
|
if (!(0, transcript_1.isClaudeTurnWritable)(turn)) {
|
|
931
955
|
// The agent has not said `end_turn` for this prompt and no later prompt has
|
|
932
956
|
// taken over, so what is in the file is a turn in progress. Writing it would
|
|
@@ -941,6 +965,8 @@ async function writeClaudeTurn(target, turn, rendered, timestampMs, path) {
|
|
|
941
965
|
// Handing it back to the scraper costs the Markdown rendering for this turn
|
|
942
966
|
// and nothing else: the Stop receiver asks again after a short delay, and
|
|
943
967
|
// the poller asks again when the pane returns to the composer.
|
|
968
|
+
if (report)
|
|
969
|
+
report.outcome = 'not_yet_closed';
|
|
944
970
|
logger.info('claude-transcript-turn-open', {
|
|
945
971
|
worktreeId: target.worktreeId,
|
|
946
972
|
instanceId,
|
|
@@ -101,6 +101,7 @@ const path_1 = require("path");
|
|
|
101
101
|
const auto_yes_state_1 = require("../../../../lib/auto-yes-state");
|
|
102
102
|
const transcript_tail_1 = require("../../../../lib/history/transcript-tail");
|
|
103
103
|
const user_turn_recorder_1 = require("../../../../lib/history/user-turn-recorder");
|
|
104
|
+
const assistant_response_saver_1 = require("../../../../lib/assistant-response-saver");
|
|
104
105
|
const logger_1 = require("../../../../lib/logger");
|
|
105
106
|
const agent_transcript_1 = require("../../../../types/agent-transcript");
|
|
106
107
|
const transcript_1 = require("./transcript");
|
|
@@ -332,11 +333,19 @@ async function scanForRollout(dir, sessionId, depth) {
|
|
|
332
333
|
*
|
|
333
334
|
* Never throws.
|
|
334
335
|
*
|
|
336
|
+
* Since Issue #2436 the false can explain itself: pass a
|
|
337
|
+
* `StructuredHistoryCaptureReport` and `outcome` is set to `'not_yet_closed'`
|
|
338
|
+
* when the newest turn is one the agent has not finished writing — the case the
|
|
339
|
+
* `-turn-open` line below reports, and the one where the caller's scraped copy
|
|
340
|
+
* is worth holding rather than saving. Every other false leaves it unset, which
|
|
341
|
+
* the gate reads as `'unavailable'`.
|
|
342
|
+
*
|
|
335
343
|
* @param target - The instance whose turn just ended
|
|
336
344
|
* @param capture - See {@link CodexTranscriptCapture}
|
|
345
|
+
* @param report - Optional out-parameter; see `StructuredHistoryCaptureReport`
|
|
337
346
|
* @returns Whether History now holds this turn as the agent's own Markdown
|
|
338
347
|
*/
|
|
339
|
-
async function captureCodexTranscriptTurn(target, capture = {}) {
|
|
348
|
+
async function captureCodexTranscriptTurn(target, capture = {}, report) {
|
|
340
349
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
341
350
|
try {
|
|
342
351
|
const codexHome = capture.codexHome ?? resolveCodexHome();
|
|
@@ -395,6 +404,9 @@ async function captureCodexTranscriptTurn(target, capture = {}) {
|
|
|
395
404
|
instanceId,
|
|
396
405
|
turnsInWindow: built.turns.length,
|
|
397
406
|
});
|
|
407
|
+
// Issue #2437: this turn is already History's Markdown, so the pane rows
|
|
408
|
+
// behind it must stop being "unsaved output" the pre-send flush can pick up.
|
|
409
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
398
410
|
return true;
|
|
399
411
|
}
|
|
400
412
|
if (pending.turns.length > 1) {
|
|
@@ -428,7 +440,14 @@ async function captureCodexTranscriptTurn(target, capture = {}) {
|
|
|
428
440
|
let captured = false;
|
|
429
441
|
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
430
442
|
const turn = pending.turns[index];
|
|
431
|
-
captured = await writeCodexTurn(target, turn, (0, transcript_1.renderCodexTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.turnId) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), windowFacts);
|
|
443
|
+
captured = await writeCodexTurn(target, turn, (0, transcript_1.renderCodexTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.turnId) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), windowFacts, report);
|
|
444
|
+
}
|
|
445
|
+
if (captured) {
|
|
446
|
+
// Issue #2437: History now holds this turn as the agent's own Markdown.
|
|
447
|
+
// Park the pre-send flush's cursor past the pane rows it covers, or a
|
|
448
|
+
// `/send` arriving before the next poll tick saves the whole finished turn
|
|
449
|
+
// a second time.
|
|
450
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
432
451
|
}
|
|
433
452
|
return captured;
|
|
434
453
|
}
|
|
@@ -670,14 +689,21 @@ function nextTurnOpensAt(turns, userRows, index) {
|
|
|
670
689
|
*
|
|
671
690
|
* @returns Whether History holds this turn as the agent's own Markdown
|
|
672
691
|
*/
|
|
673
|
-
async function writeCodexTurn(target, turn, rendered, timestampMs, windowFacts) {
|
|
692
|
+
async function writeCodexTurn(target, turn, rendered, timestampMs, windowFacts, report) {
|
|
674
693
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
694
|
+
// Issue #2436: the caller's report is about the turn THIS call is deciding.
|
|
695
|
+
// The loop above walks oldest-first, so a verdict left by an earlier turn has
|
|
696
|
+
// to be cleared before this one's is written.
|
|
697
|
+
if (report)
|
|
698
|
+
report.outcome = undefined;
|
|
675
699
|
if (!turn.closed) {
|
|
676
700
|
// codex has not written the `task_complete` for this `turn_id` yet, so what
|
|
677
701
|
// is in the file is a turn in progress. Writing it would put a truncated
|
|
678
702
|
// reply in History permanently — and unlike an empty one, a truncated one
|
|
679
703
|
// looks finished. Handing it back to the scraper costs the Markdown
|
|
680
704
|
// rendering for this turn and nothing else.
|
|
705
|
+
if (report)
|
|
706
|
+
report.outcome = 'not_yet_closed';
|
|
681
707
|
logger.info('codex-transcript-turn-open', {
|
|
682
708
|
worktreeId: target.worktreeId,
|
|
683
709
|
instanceId,
|