commandmate 0.33.1 → 0.33.3
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 +307 -307
- package/.next/app-path-routes-manifest.json +28 -28
- 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 +15 -15
- 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.js +1 -1
- package/.next/server/app/api/app/update-check/route.js.nft.json +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 +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 +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.js.nft.json +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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js +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 +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.js +1 -1
- package/.next/server/app/api/skills/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route.js +1 -1
- package/.next/server/app/api/skills/installations/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/skills/route.js.nft.json +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_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 +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 +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route.js.nft.json +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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route.js.nft.json +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.js +2 -2
- package/.next/server/app/api/worktrees/[id]/tasks/route.js.nft.json +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.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_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 +10 -10
- 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 +28 -28
- 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/1501.js +6 -2
- package/.next/server/chunks/1886.js +2 -2
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/2839.js +1 -0
- package/.next/server/chunks/3123.js +1 -1
- 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/6130.js +1 -0
- package/.next/server/chunks/650.js +1 -0
- package/.next/server/chunks/6661.js +1 -1
- package/.next/server/chunks/6781.js +1 -0
- package/.next/server/chunks/6808.js +1 -0
- package/.next/server/chunks/7875.js +3 -3
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8918.js +107 -5
- package/.next/server/chunks/9553.js +1 -0
- package/.next/server/chunks/9627.js +1 -1
- 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-814f4ecfd7fcc513.js} +1 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/page-3af707e74a75172b.js +1 -0
- package/.next/static/chunks/{main-6092074a0dc78280.js → main-ac91ed6e71380841.js} +1 -1
- package/.next/trace +13 -14
- package/dist/server/locales/en/worktree.json +9 -2
- package/dist/server/locales/ja/worktree.json +9 -2
- package/dist/server/src/lib/assistant-response-saver.js +168 -12
- package/dist/server/src/lib/cli-tools/vibe-local.js +10 -0
- package/dist/server/src/lib/hooks/hook-settings-generator.js +61 -1
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +497 -27
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +103 -0
- 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 +94 -10
- package/dist/server/src/lib/response-cleaner.js +84 -0
- package/dist/server/src/lib/session/agent-session-lifecycle.js +31 -1
- package/dist/server/src/lib/session/session-generation-archive.js +194 -0
- package/dist/server/src/lib/tasks/contract-message.js +83 -9
- package/dist/server/src/lib/tasks/contract-parser.js +2 -0
- package/package.json +2 -2
- package/.next/server/chunks/153.js +0 -1
- 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/4299.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/6838.js +0 -1
- package/.next/server/chunks/7366.js +0 -5
- 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/6022-2fa0b5a82d4ce7b6.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-13ca0ba551fe5cfb.js +0 -1
- /package/.next/static/{9lgw9hA727UMyFhXryGWG → 9x6U1h52hH_r6pOsGwI_p}/_buildManifest.js +0 -0
- /package/.next/static/{9lgw9hA727UMyFhXryGWG → 9x6U1h52hH_r6pOsGwI_p}/_ssgManifest.js +0 -0
|
@@ -47,6 +47,25 @@
|
|
|
47
47
|
* module reads only the former — see {@link ANTIGRAVITY_CLI_HOME_SEGMENTS} — and
|
|
48
48
|
* the conversation ids are uuids in any case.
|
|
49
49
|
*
|
|
50
|
+
* ## Saving and finishing are two questions (Issue #2443)
|
|
51
|
+
*
|
|
52
|
+
* agy writes no record that closes a turn, so "may this be saved" has to be
|
|
53
|
+
* answered from the shape of its last words — and an interim report has the
|
|
54
|
+
* same shape as a conclusion. #2438 made the row that follows repairable. #2443
|
|
55
|
+
* separates the *second* consequence of the same evidence: whether the body may
|
|
56
|
+
* be handed onward as the answer. Two states, and the reader reports which one
|
|
57
|
+
* the newest turn is in:
|
|
58
|
+
*
|
|
59
|
+
* - **provisional** — History holds the turn, the scraper stands down, the row
|
|
60
|
+
* keeps being re-read and grown, and `broadcastMessage('message_updated', …)`
|
|
61
|
+
* refreshes what a browser is showing. Nothing leaves the server.
|
|
62
|
+
* - **settled** — agy's own `Stop` arrived at or after the turn's newest
|
|
63
|
+
* record, so the body is the one it finished on. The gate announces the
|
|
64
|
+
* completion edge exactly once for that body.
|
|
65
|
+
*
|
|
66
|
+
* `docs/design/antigravity-turn-completion-2443.md` is the argument, including
|
|
67
|
+
* what happens when the evidence never arrives.
|
|
68
|
+
*
|
|
50
69
|
* ## Nothing here throws
|
|
51
70
|
*
|
|
52
71
|
* Same contract as the other three readers, for the same reason: this runs
|
|
@@ -91,8 +110,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
91
110
|
};
|
|
92
111
|
})();
|
|
93
112
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
94
|
-
exports.ANTIGRAVITY_CLI_HOME_SEGMENTS = exports.ANTIGRAVITY_TRANSCRIPT_TAIL_BYTES = void 0;
|
|
113
|
+
exports.ANTIGRAVITY_TURN_RECHECK_LIMIT = exports.ANTIGRAVITY_UNSETTLED_TURN_LIMIT = exports.ANTIGRAVITY_CLI_HOME_SEGMENTS = exports.ANTIGRAVITY_TRANSCRIPT_TAIL_BYTES = void 0;
|
|
95
114
|
exports.resetAntigravityTranscriptConversations = resetAntigravityTranscriptConversations;
|
|
115
|
+
exports.resetAntigravityUnsettledTurns = resetAntigravityUnsettledTurns;
|
|
96
116
|
exports.resolveAntigravityConversationId = resolveAntigravityConversationId;
|
|
97
117
|
exports.resolveAntigravityHome = resolveAntigravityHome;
|
|
98
118
|
exports.antigravityBrainRoot = antigravityBrainRoot;
|
|
@@ -106,6 +126,7 @@ const path_1 = require("path");
|
|
|
106
126
|
const auto_yes_state_1 = require("../../../../lib/auto-yes-state");
|
|
107
127
|
const transcript_tail_1 = require("../../../../lib/history/transcript-tail");
|
|
108
128
|
const user_turn_recorder_1 = require("../../../../lib/history/user-turn-recorder");
|
|
129
|
+
const assistant_response_saver_1 = require("../../../../lib/assistant-response-saver");
|
|
109
130
|
const logger_1 = require("../../../../lib/logger");
|
|
110
131
|
const agent_transcript_1 = require("../../../../types/agent-transcript");
|
|
111
132
|
const transcript_1 = require("./transcript");
|
|
@@ -158,12 +179,153 @@ const ANTIGRAVITY_CONVERSATION_ID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9
|
|
|
158
179
|
* did not would otherwise blank the pointer mid-session.
|
|
159
180
|
*/
|
|
160
181
|
const conversationPointers = (globalThis.__antigravityTranscriptConversations ??= new Map());
|
|
182
|
+
/**
|
|
183
|
+
* How many written-but-unconfirmed turns one instance may be following (#2443).
|
|
184
|
+
*
|
|
185
|
+
* The bound on the answer to "a saved row must be able to catch up with its
|
|
186
|
+
* conclusion even once three later turns have been written". Sixteen and not
|
|
187
|
+
* "however many are in the window", because the list is walked on **every**
|
|
188
|
+
* poll: each entry costs one indexed `findMessageByRequestId` and, only when
|
|
189
|
+
* that finds a row, one render of a turn that is already parsed. Sixteen turns
|
|
190
|
+
* is more than a working session accumulates without a single `Stop` arriving,
|
|
191
|
+
* and it is a fixed ceiling on a per-instance map rather than a function of a
|
|
192
|
+
* file somebody else appends to.
|
|
193
|
+
*
|
|
194
|
+
* Eviction is oldest-first and is a real loss of coverage, which is why it is
|
|
195
|
+
* logged (`antigravity-transcript-unsettled-evicted`) rather than silent. What
|
|
196
|
+
* is left is #2438's behaviour for that row: the newest
|
|
197
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT} turns are re-read regardless of this
|
|
198
|
+
* list, so an evicted entry loses the *extra* reach and not the ordinary one.
|
|
199
|
+
*/
|
|
200
|
+
exports.ANTIGRAVITY_UNSETTLED_TURN_LIMIT = 16;
|
|
201
|
+
/**
|
|
202
|
+
* Which written turns are still waiting for agy to vouch for them (#2443).
|
|
203
|
+
*
|
|
204
|
+
* On `globalThis` for the reason {@link conversationPointers} is: under `next
|
|
205
|
+
* dev` the poller's bundle and the hook receiver's bundle each get their own
|
|
206
|
+
* copy of a module-scoped map, and a list only one of the two writers can see is
|
|
207
|
+
* not a list.
|
|
208
|
+
*
|
|
209
|
+
* In memory and not in SQLite, deliberately. The entry describes a turn this
|
|
210
|
+
* *process* wrote provisionally and has not seen confirmed; a restart loses it,
|
|
211
|
+
* and what remains is exactly {@link ANTIGRAVITY_TURN_RECHECK_LIMIT} — the same
|
|
212
|
+
* coverage #2438 shipped. Persisting it would make a row's repair depend on a
|
|
213
|
+
* table that outlives the transcript window it can only be repaired from.
|
|
214
|
+
*/
|
|
215
|
+
const unsettledTurns = (globalThis.__antigravityUnsettledTurns ??= new Map());
|
|
161
216
|
function keyOf(target) {
|
|
162
217
|
return (0, auto_yes_state_1.buildCompositeKey)(target.worktreeId, target.cliToolId, target.instanceId);
|
|
163
218
|
}
|
|
164
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* Forget every instance's pointer and every unconfirmed row it was following.
|
|
221
|
+
*
|
|
222
|
+
* Test seam. Both maps, because they are two halves of one per-instance state:
|
|
223
|
+
* a suite that reset the pointer and kept the follow list would carry one test's
|
|
224
|
+
* `step_index` values into the next one's conversation.
|
|
225
|
+
*/
|
|
165
226
|
function resetAntigravityTranscriptConversations() {
|
|
166
227
|
conversationPointers.clear();
|
|
228
|
+
unsettledTurns.clear();
|
|
229
|
+
}
|
|
230
|
+
/** Forget the unconfirmed rows alone. Test seam. */
|
|
231
|
+
function resetAntigravityUnsettledTurns() {
|
|
232
|
+
unsettledTurns.clear();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The steps this instance is following in `conversationId`, oldest first.
|
|
236
|
+
*
|
|
237
|
+
* A conversation that is not the one the list was built for answers empty and
|
|
238
|
+
* drops the list: `/clear` mints a new conversation id, and following the old
|
|
239
|
+
* one's `step_index` values into it would re-check turns that are not the same
|
|
240
|
+
* turns. This is the leak test #2443 asks for, expressed as the read path
|
|
241
|
+
* rather than as a promise.
|
|
242
|
+
*/
|
|
243
|
+
function unsettledStepsFor(key, conversationId) {
|
|
244
|
+
const entry = unsettledTurns.get(key);
|
|
245
|
+
if (!entry)
|
|
246
|
+
return [];
|
|
247
|
+
if (entry.conversationId !== conversationId) {
|
|
248
|
+
unsettledTurns.delete(key);
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
return entry.steps;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Start, or stop, following one written turn (Issue #2443).
|
|
255
|
+
*
|
|
256
|
+
* `confirmed` is {@link AntigravityTurnCompletion.confirmed}: a turn agy has
|
|
257
|
+
* vouched for cannot grow again without a later record, and a later record takes
|
|
258
|
+
* the confirmation away and re-adds it here on the very next pass. So the list
|
|
259
|
+
* holds exactly the rows whose body is still provisional.
|
|
260
|
+
*
|
|
261
|
+
* @returns The step that was evicted to make room, or null
|
|
262
|
+
*/
|
|
263
|
+
function noteAntigravityTurnCompletion(key, conversationId, stepIndex, confirmed) {
|
|
264
|
+
const entry = unsettledTurns.get(key);
|
|
265
|
+
if (entry && entry.conversationId !== conversationId)
|
|
266
|
+
unsettledTurns.delete(key);
|
|
267
|
+
if (confirmed) {
|
|
268
|
+
const current = unsettledTurns.get(key);
|
|
269
|
+
if (!current)
|
|
270
|
+
return null;
|
|
271
|
+
current.steps = current.steps.filter((step) => step !== stepIndex);
|
|
272
|
+
if (current.steps.length === 0)
|
|
273
|
+
unsettledTurns.delete(key);
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
const current = unsettledTurns.get(key) ?? { conversationId, steps: [] };
|
|
277
|
+
unsettledTurns.set(key, current);
|
|
278
|
+
if (current.steps.includes(stepIndex))
|
|
279
|
+
return null;
|
|
280
|
+
current.steps.push(stepIndex);
|
|
281
|
+
if (current.steps.length <= exports.ANTIGRAVITY_UNSETTLED_TURN_LIMIT)
|
|
282
|
+
return null;
|
|
283
|
+
return current.steps.shift() ?? null;
|
|
284
|
+
}
|
|
285
|
+
/** Stop following steps the current read window no longer contains. */
|
|
286
|
+
function forgetAntigravityTurnsOutsideWindow(key, conversationId, present) {
|
|
287
|
+
const entry = unsettledTurns.get(key);
|
|
288
|
+
if (!entry || entry.conversationId !== conversationId)
|
|
289
|
+
return [];
|
|
290
|
+
const dropped = entry.steps.filter((step) => !present.has(step));
|
|
291
|
+
if (dropped.length === 0)
|
|
292
|
+
return [];
|
|
293
|
+
entry.steps = entry.steps.filter((step) => present.has(step));
|
|
294
|
+
if (entry.steps.length === 0)
|
|
295
|
+
unsettledTurns.delete(key);
|
|
296
|
+
return dropped;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* When this instance last reported that its loop stopped, or null (#2443).
|
|
300
|
+
*
|
|
301
|
+
* The one piece of evidence {@link resolveAntigravityTurnCompletion} is asked to
|
|
302
|
+
* judge against, read the way {@link resolveAntigravityConversationId} reads its
|
|
303
|
+
* own: dynamically, so `agent-event-state`'s module graph is not a static
|
|
304
|
+
* dependency of the poller, and defensively, so a state module that cannot be
|
|
305
|
+
* reached — or a build in which this reader is newer than its neighbour — is one
|
|
306
|
+
* that knows of no stop rather than one that throws inside the save path.
|
|
307
|
+
*
|
|
308
|
+
* `recordAgentStopEvent` runs **before** the Stop receiver asks for a capture
|
|
309
|
+
* (`lib/hooks/agent-event-service`), so the value is already there on the read
|
|
310
|
+
* that stop itself triggers. That ordering is what lets one seam serve both
|
|
311
|
+
* triggers instead of the receiver having to hand a flag down through the gate.
|
|
312
|
+
*/
|
|
313
|
+
async function resolveAntigravityStopAt(target) {
|
|
314
|
+
try {
|
|
315
|
+
const state = await Promise.resolve().then(() => __importStar(require('../../../../lib/session/agent-event-state')));
|
|
316
|
+
const read = state.getLastStopEventAt;
|
|
317
|
+
if (typeof read !== 'function')
|
|
318
|
+
return null;
|
|
319
|
+
return read(target.worktreeId, target.cliToolId, target.instanceId) ?? null;
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
logger.debug('antigravity-transcript-stop-lookup-failed', {
|
|
323
|
+
worktreeId: target.worktreeId,
|
|
324
|
+
instanceId: target.instanceId ?? target.cliToolId,
|
|
325
|
+
error: error instanceof Error ? error.message : String(error),
|
|
326
|
+
});
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
167
329
|
}
|
|
168
330
|
/**
|
|
169
331
|
* The conversation id this instance's transcript is under, or null.
|
|
@@ -288,11 +450,43 @@ function acceptAntigravityTranscriptPath(agyHome, candidate) {
|
|
|
288
450
|
*
|
|
289
451
|
* Never throws.
|
|
290
452
|
*
|
|
453
|
+
* **A row this reader wrote is not final (Issue #2438).** Before anything is
|
|
454
|
+
* written, the newest already-written turns — at most
|
|
455
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT} of them — are re-rendered and compared
|
|
456
|
+
* against the rows they produced, and a row whose turn now renders *strictly
|
|
457
|
+
* longer* is replaced in place. agy has no record that closes a turn, so an
|
|
458
|
+
* interim report reads as a finished answer (`isAntigravityTurnClosingRecord`)
|
|
459
|
+
* and used to freeze a half-written reply into History forever. That is a
|
|
460
|
+
* repair and not a second verdict: growing an older row changes neither the
|
|
461
|
+
* return value nor `report`, both of which are about the **newest** turn.
|
|
462
|
+
*
|
|
463
|
+
* Since Issue #2436 the false can explain itself: pass a
|
|
464
|
+
* `StructuredHistoryCaptureReport` and `outcome` is set to `'not_yet_closed'`
|
|
465
|
+
* when the newest turn is one the agent has not finished writing — the case the
|
|
466
|
+
* `-turn-open` line below reports, and the one where the caller's scraped copy
|
|
467
|
+
* is worth holding rather than saving. Every other false leaves it unset, which
|
|
468
|
+
* the gate reads as `'unavailable'`.
|
|
469
|
+
*
|
|
470
|
+
* **A saved turn is not a finished turn (Issue #2443).** #2438 made the frozen
|
|
471
|
+
* row repairable and left the other half of the damage in place: the same
|
|
472
|
+
* `true` that tells the poller to drop its scrape also told the relay that the
|
|
473
|
+
* turn was over, so an interim report was **delivered** to whoever had asked
|
|
474
|
+
* agy a question, and no later `message_updated` could take that back. So the
|
|
475
|
+
* `true` now carries a second word. `report.completion` is `'settled'` only
|
|
476
|
+
* when {@link resolveAntigravityTurnCompletion} can show, from agy's own `Stop`
|
|
477
|
+
* event, that the body in hand is the one it finished on; otherwise it is
|
|
478
|
+
* `'provisional'` — History still holds the row, the repair still runs on every
|
|
479
|
+
* later read, and nothing is announced to a relay. Rows written provisionally
|
|
480
|
+
* are followed by `step_index` (see {@link ANTIGRAVITY_UNSETTLED_TURN_LIMIT}),
|
|
481
|
+
* so the conclusion is still picked up once the turn has fallen out of
|
|
482
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}'s window.
|
|
483
|
+
*
|
|
291
484
|
* @param target - The instance whose turn just ended
|
|
292
485
|
* @param capture - See {@link AntigravityTranscriptCapture}
|
|
486
|
+
* @param report - Optional out-parameter; see `StructuredHistoryCaptureReport`
|
|
293
487
|
* @returns Whether History now holds this turn as the agent's own Markdown
|
|
294
488
|
*/
|
|
295
|
-
async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
489
|
+
async function captureAntigravityTranscriptTurn(target, capture = {}, report) {
|
|
296
490
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
297
491
|
try {
|
|
298
492
|
const agyHome = capture.antigravityHome ?? resolveAntigravityHome();
|
|
@@ -347,13 +541,55 @@ async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
|
347
541
|
preludeRecords: built.preludeRecords,
|
|
348
542
|
});
|
|
349
543
|
}
|
|
544
|
+
// Issue #2443: one read of the evidence, applied to every turn in the
|
|
545
|
+
// window. `stopAt` is agy's own account of when its loop ended; see
|
|
546
|
+
// {@link resolveAntigravityTurnCompletion} for why an ordering against the
|
|
547
|
+
// turn's newest record — rather than a word, a silence or a `status` — is
|
|
548
|
+
// what the promotion to "final" rests on.
|
|
549
|
+
const instanceKey = keyOf(target);
|
|
550
|
+
const stopAt = await resolveAntigravityStopAt(target);
|
|
551
|
+
const completions = new Map();
|
|
552
|
+
for (const turn of built.turns) {
|
|
553
|
+
completions.set(turn.stepIndex, (0, transcript_1.resolveAntigravityTurnCompletion)(turn, stopAt));
|
|
554
|
+
}
|
|
555
|
+
const newestTurn = built.turns[built.turns.length - 1];
|
|
556
|
+
const newestCompletion = completions.get(newestTurn.stepIndex) ??
|
|
557
|
+
(0, transcript_1.resolveAntigravityTurnCompletion)(newestTurn, stopAt);
|
|
558
|
+
// A step this read can no longer see is a step no later read can repair:
|
|
559
|
+
// the 4 MiB tail slid past it, its `USER_INPUT` is outside the window, or
|
|
560
|
+
// the file was replaced. Logged rather than dropped in silence, because it
|
|
561
|
+
// is the boundary of what #2443 promises.
|
|
562
|
+
const forgotten = forgetAntigravityTurnsOutsideWindow(instanceKey, conversationId, new Set(built.turns.map((turn) => turn.stepIndex)));
|
|
563
|
+
if (forgotten.length > 0) {
|
|
564
|
+
logger.info('antigravity-transcript-unsettled-out-of-window', {
|
|
565
|
+
worktreeId: target.worktreeId,
|
|
566
|
+
instanceId,
|
|
567
|
+
conversationId,
|
|
568
|
+
steps: forgotten,
|
|
569
|
+
turnsInWindow: built.turns.length,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
350
572
|
const pending = await selectUnwrittenAntigravityTurns(target, built.turns);
|
|
573
|
+
const writtenTurns = built.turns.slice(0, built.turns.length - pending.turns.length);
|
|
574
|
+
// Before anything is written: the rows that are already there (#2438). This
|
|
575
|
+
// is deliberately ahead of the early return below, because "the newest turn
|
|
576
|
+
// is already a row" is exactly the state the frozen row the Issue measured
|
|
577
|
+
// was stuck in — agy said "waiting for the worker", the writer saved that,
|
|
578
|
+
// and every later read answered true and did nothing while the conclusion
|
|
579
|
+
// sat in the transcript beside it. Written turns are re-checked whether or
|
|
580
|
+
// not anything is pending, so an old turn can be repaired in the same pass
|
|
581
|
+
// that writes a new one.
|
|
582
|
+
await refreshAntigravityTurnRows(target, selectAntigravityRecheckCandidates(writtenTurns, unsettledStepsFor(instanceKey, conversationId)), path, { instanceKey, conversationId, completions });
|
|
351
583
|
if (pending.turns.length === 0) {
|
|
352
584
|
logger.debug('antigravity-transcript-turns-already-saved', {
|
|
353
585
|
worktreeId: target.worktreeId,
|
|
354
586
|
instanceId,
|
|
355
587
|
turnsInWindow: built.turns.length,
|
|
356
588
|
});
|
|
589
|
+
// Issue #2437: this turn is already History's Markdown, so the pane rows
|
|
590
|
+
// behind it must stop being "unsaved output" the pre-send flush can pick up.
|
|
591
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
592
|
+
reportAntigravityCompletion(report, newestTurn, newestCompletion);
|
|
357
593
|
return true;
|
|
358
594
|
}
|
|
359
595
|
if (pending.turns.length > 1) {
|
|
@@ -380,7 +616,22 @@ async function captureAntigravityTranscriptTurn(target, capture = {}) {
|
|
|
380
616
|
let captured = false;
|
|
381
617
|
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
382
618
|
const turn = pending.turns[index];
|
|
383
|
-
captured = await writeAntigravityTurn(target, turn, (0, transcript_1.renderAntigravityTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index],
|
|
619
|
+
captured = await writeAntigravityTurn(target, turn, (0, transcript_1.renderAntigravityTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], (0, transcript_1.antigravityTurnLastRecordAt)(turn), nextTurnOpensAt(pending.turns, userRows, index)), path, report);
|
|
620
|
+
// Issue #2443: a row now exists for this turn, and whether it is the body
|
|
621
|
+
// agy finished on is a separate question from whether it could be saved.
|
|
622
|
+
// An unconfirmed one joins the follow list so that its conclusion is still
|
|
623
|
+
// picked up once three later turns have pushed it out of #2438's window.
|
|
624
|
+
if (captured) {
|
|
625
|
+
noteUnsettledAntigravityTurn(target, instanceKey, turn, completions.get(turn.stepIndex) ?? (0, transcript_1.resolveAntigravityTurnCompletion)(turn, stopAt));
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
if (captured) {
|
|
629
|
+
// Issue #2437: History now holds this turn as the agent's own Markdown.
|
|
630
|
+
// Park the pre-send flush's cursor past the pane rows it covers, or a
|
|
631
|
+
// `/send` arriving before the next poll tick saves the whole finished turn
|
|
632
|
+
// a second time.
|
|
633
|
+
await (0, assistant_response_saver_1.advanceCapturedLineForTranscriptTurn)(target);
|
|
634
|
+
reportAntigravityCompletion(report, newestTurn, newestCompletion);
|
|
384
635
|
}
|
|
385
636
|
return captured;
|
|
386
637
|
}
|
|
@@ -545,23 +796,6 @@ function resolveAssistantTimestampMs(turn, userRow, lastRecordAt = 0, nextTurnOp
|
|
|
545
796
|
const latest = nextTurnOpensAt === null ? Number.POSITIVE_INFINITY : nextTurnOpensAt - 1;
|
|
546
797
|
return Math.max(earliest, Math.min(lastRecordAt, latest));
|
|
547
798
|
}
|
|
548
|
-
/**
|
|
549
|
-
* When the last record agy wrote for this turn was made (Issue #2273).
|
|
550
|
-
*
|
|
551
|
-
* The maximum rather than `records.at(-1)`: `created_at` is agy's own field and
|
|
552
|
-
* a record that carries none reads as null, so the last record in file order is
|
|
553
|
-
* not always the last one with a clock on it.
|
|
554
|
-
*
|
|
555
|
-
* @returns Epoch ms, or 0 when the turn has no timestamped record
|
|
556
|
-
*/
|
|
557
|
-
function lastAntigravityRecordAt(turn) {
|
|
558
|
-
let at = 0;
|
|
559
|
-
for (const record of turn.records) {
|
|
560
|
-
if (record.timestampMs !== null && record.timestampMs > at)
|
|
561
|
-
at = record.timestampMs;
|
|
562
|
-
}
|
|
563
|
-
return at;
|
|
564
|
-
}
|
|
565
799
|
/**
|
|
566
800
|
* The instant the next pending turn's prompt row carries, or null (Issue #2273).
|
|
567
801
|
*
|
|
@@ -577,6 +811,218 @@ function nextTurnOpensAt(turns, userRows, index) {
|
|
|
577
811
|
return null;
|
|
578
812
|
return userRows[index + 1]?.timestampMs ?? next.startedAt;
|
|
579
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* How many already-written turns are re-rendered and compared (Issue #2438).
|
|
816
|
+
*
|
|
817
|
+
* The repair half of #2438 has to look at rows this reader has **already**
|
|
818
|
+
* written, which is the one thing the anchor rule of
|
|
819
|
+
* {@link selectUnwrittenAntigravityTurns} deliberately does not do — so it is
|
|
820
|
+
* bounded here rather than by the read window. Three, the number claude and
|
|
821
|
+
* command-code settled on in #2264 and for the same arithmetic: the poller runs
|
|
822
|
+
* every couple of seconds, re-rendering the whole window on every tick would
|
|
823
|
+
* make a repair the most expensive thing the poll does, and a turn that is going
|
|
824
|
+
* to grow grows within seconds of being written.
|
|
825
|
+
*
|
|
826
|
+
* The cost of the bound is paid by rows a session has already moved three turns
|
|
827
|
+
* past: those keep whatever they were written with. The measured case — one
|
|
828
|
+
* conversation whose only turn was `#0` — is inside it by a wide margin.
|
|
829
|
+
*/
|
|
830
|
+
exports.ANTIGRAVITY_TURN_RECHECK_LIMIT = 3;
|
|
831
|
+
/**
|
|
832
|
+
* Replace a saved row whose body has since grown (Issue #2438).
|
|
833
|
+
*
|
|
834
|
+
* The defect this exists for is not that the wrong body was written; it is that
|
|
835
|
+
* the row was written **early**. `isAntigravityTurnClosingRecord` reads prose
|
|
836
|
+
* with no `tool_calls` as agy finishing, and an interim report — "waiting for
|
|
837
|
+
* the worker" — has exactly that shape. The row is keyed
|
|
838
|
+
* `antigravity-turn:<conversationId>#<stepIndex>`, so once it exists every later
|
|
839
|
+
* read finds it, answers "already saved", and the gate suppresses the scrape
|
|
840
|
+
* that could have carried the conclusion instead. Nothing else in the system
|
|
841
|
+
* ever revisits that row.
|
|
842
|
+
*
|
|
843
|
+
* **Strictly longer, never merely different.** Equality is the ordinary case and
|
|
844
|
+
* must cost nothing, and a body that got *shorter* between two reads is not a
|
|
845
|
+
* turn that grew — it is a window that slid, or a truncation marker, and
|
|
846
|
+
* overwriting a full reply with a shorter one is the one outcome worse than the
|
|
847
|
+
* bug. Longer implies different, so one comparison covers both.
|
|
848
|
+
*
|
|
849
|
+
* Only `content` moves. The row's `id`, `request_id`, `timestamp`, worktree,
|
|
850
|
+
* tool and instance are what History sorts and pairs on, and a repair that
|
|
851
|
+
* disturbed any of them would move an old answer to the bottom of the
|
|
852
|
+
* conversation.
|
|
853
|
+
*
|
|
854
|
+
* `message_updated`, never `message`: the row already existed and was already
|
|
855
|
+
* delivered when it was created, so a client that appended instead of replacing
|
|
856
|
+
* would show the reply twice.
|
|
857
|
+
*
|
|
858
|
+
* @param existing - The row `findMessageByRequestId` answered with
|
|
859
|
+
* @returns Whether the row was replaced
|
|
860
|
+
*/
|
|
861
|
+
async function growAntigravityTurnRow(target, existing, rendered, path) {
|
|
862
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
863
|
+
// The stored body is the only evidence of what History holds, so a row that
|
|
864
|
+
// carries none is not evidence that anything grew. Same answer as "not
|
|
865
|
+
// longer": leave it alone. This runs inside the poller's save path, where the
|
|
866
|
+
// module contract is that nothing throws.
|
|
867
|
+
const previous = existing.content;
|
|
868
|
+
if (typeof previous !== 'string')
|
|
869
|
+
return false;
|
|
870
|
+
const previousLength = previous.length;
|
|
871
|
+
if (rendered.body.length <= previousLength)
|
|
872
|
+
return false;
|
|
873
|
+
const [{ getDbInstance }, { updateMessageContent }, { broadcastMessage }] = await Promise.all([
|
|
874
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
875
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
876
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
|
|
877
|
+
]);
|
|
878
|
+
updateMessageContent(getDbInstance(), existing.id, rendered.body);
|
|
879
|
+
broadcastMessage('message_updated', {
|
|
880
|
+
worktreeId: target.worktreeId,
|
|
881
|
+
message: { ...existing, content: rendered.body },
|
|
882
|
+
});
|
|
883
|
+
logger.info('antigravity-transcript-turn-updated', {
|
|
884
|
+
worktreeId: target.worktreeId,
|
|
885
|
+
instanceId,
|
|
886
|
+
conversationId: rendered.conversationId,
|
|
887
|
+
stepIndex: rendered.stepIndex,
|
|
888
|
+
requestId: existing.requestId,
|
|
889
|
+
path,
|
|
890
|
+
previousLength,
|
|
891
|
+
bodyLength: rendered.body.length,
|
|
892
|
+
textBlocks: rendered.textBlocks,
|
|
893
|
+
toolBlocks: rendered.toolBlocks,
|
|
894
|
+
});
|
|
895
|
+
return true;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Re-read the newest already-written turns and grow the short ones (#2438).
|
|
899
|
+
*
|
|
900
|
+
* Runs before the pending turns are written and independently of whether there
|
|
901
|
+
* are any — the case it exists for is precisely the one
|
|
902
|
+
* {@link captureAntigravityTranscriptTurn} used to return `true` from without
|
|
903
|
+
* doing anything: the newest turn already has a row, and that row stopped at
|
|
904
|
+
* agy's interim report.
|
|
905
|
+
*
|
|
906
|
+
* Turns that are open again are skipped rather than compared. A turn whose last
|
|
907
|
+
* record is a `tool_calls` is one agy is still working through, its body is by
|
|
908
|
+
* definition not the final one, and a repair that raced the agent would rewrite
|
|
909
|
+
* the row on every poll of a long turn. **This is not a second chance to write
|
|
910
|
+
* a turn**: a candidate with no row is left alone, because the anchor rule
|
|
911
|
+
* already decided it is not this pass's to create.
|
|
912
|
+
*
|
|
913
|
+
* The database is asked before the turn is rendered, so a candidate with no row
|
|
914
|
+
* — every candidate, in a session this reader has never written to — costs one
|
|
915
|
+
* indexed lookup and no Markdown.
|
|
916
|
+
*
|
|
917
|
+
* Serialisation is the gate's, per instance: this adds no loop and no timer of
|
|
918
|
+
* its own, it is one more thing the poll's existing pass does.
|
|
919
|
+
*
|
|
920
|
+
* @param candidates - Already-written turns, oldest first, at most
|
|
921
|
+
* {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}
|
|
922
|
+
* @returns How many rows were replaced
|
|
923
|
+
*/
|
|
924
|
+
async function refreshAntigravityTurnRows(target, candidates, path, follow) {
|
|
925
|
+
if (candidates.length === 0)
|
|
926
|
+
return 0;
|
|
927
|
+
const [{ getDbInstance }, { findMessageByRequestId }] = await Promise.all([
|
|
928
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db/db-instance'))),
|
|
929
|
+
Promise.resolve().then(() => __importStar(require('../../../../lib/db'))),
|
|
930
|
+
]);
|
|
931
|
+
const db = getDbInstance();
|
|
932
|
+
let updated = 0;
|
|
933
|
+
for (const turn of candidates) {
|
|
934
|
+
// Issue #2443: the row lookup moved ahead of the writable check, because
|
|
935
|
+
// the follow list is a statement about ROWS. A turn that is open again has a
|
|
936
|
+
// row whose body is provisional by definition and must stay followed, and a
|
|
937
|
+
// candidate whose row has gone — History cleared, the key rewritten — is one
|
|
938
|
+
// nothing can repair and is dropped here rather than re-queried forever.
|
|
939
|
+
const existing = findMessageByRequestId(db, target.worktreeId, (0, agent_transcript_1.antigravityTurnRequestId)(turn.conversationId, turn.stepIndex));
|
|
940
|
+
if (!existing) {
|
|
941
|
+
noteAntigravityTurnCompletion(follow.instanceKey, follow.conversationId, turn.stepIndex, true);
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
noteUnsettledAntigravityTurn(target, follow.instanceKey, turn, follow.completions.get(turn.stepIndex) ?? (0, transcript_1.resolveAntigravityTurnCompletion)(turn, null));
|
|
945
|
+
if (!(0, transcript_1.isAntigravityTurnWritable)(turn))
|
|
946
|
+
continue;
|
|
947
|
+
if (await growAntigravityTurnRow(target, existing, (0, transcript_1.renderAntigravityTurn)(turn), path)) {
|
|
948
|
+
updated += 1;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return updated;
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* The written turns to re-read on this pass (Issue #2443).
|
|
955
|
+
*
|
|
956
|
+
* Two sources, concatenated oldest-first and de-duplicated:
|
|
957
|
+
*
|
|
958
|
+
* - **the newest {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}**, which is #2438's
|
|
959
|
+
* window exactly and is what covers the ordinary case — a row saved at an
|
|
960
|
+
* interim report and concluded seconds later, while the session has not moved
|
|
961
|
+
* on. It is kept as a floor rather than replaced, so a cold process (one that
|
|
962
|
+
* restarted, or one whose follow list was evicted) still has #2438's reach.
|
|
963
|
+
* - **the followed steps**, which are the rows this process wrote from a body
|
|
964
|
+
* agy had not vouched for. They are the ones the limit above loses: four
|
|
965
|
+
* prompts queued back to back push the first turn out of the window in
|
|
966
|
+
* seconds, and nothing else in the system ever revisits it.
|
|
967
|
+
*
|
|
968
|
+
* The result is bounded by `ANTIGRAVITY_TURN_RECHECK_LIMIT +
|
|
969
|
+
* {@link ANTIGRAVITY_UNSETTLED_TURN_LIMIT}` — a fixed 19 — whatever the window
|
|
970
|
+
* holds, so a long transcript cannot make a poll's cost grow with it.
|
|
971
|
+
*
|
|
972
|
+
* @param writtenTurns - Turns in the window that already have rows, oldest first
|
|
973
|
+
* @param followed - `step_index` values from the follow list
|
|
974
|
+
*/
|
|
975
|
+
function selectAntigravityRecheckCandidates(writtenTurns, followed) {
|
|
976
|
+
const recent = writtenTurns.slice(-exports.ANTIGRAVITY_TURN_RECHECK_LIMIT);
|
|
977
|
+
if (followed.length === 0)
|
|
978
|
+
return recent;
|
|
979
|
+
const inRecent = new Set(recent.map((turn) => turn.stepIndex));
|
|
980
|
+
const followedSteps = new Set(followed);
|
|
981
|
+
const older = writtenTurns.filter((turn) => followedSteps.has(turn.stepIndex) && !inRecent.has(turn.stepIndex));
|
|
982
|
+
return older.length === 0 ? recent : [...older, ...recent];
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Follow this row, or stop following it, and say so once (Issue #2443).
|
|
986
|
+
*
|
|
987
|
+
* The log line is the only place an operator can see why a repair did or did not
|
|
988
|
+
* keep happening, so it carries the reason word rather than the boolean:
|
|
989
|
+
* `no-stop-event` and `stop-before-last-record` are very different sessions.
|
|
990
|
+
*/
|
|
991
|
+
function noteUnsettledAntigravityTurn(target, instanceKey, turn, completion) {
|
|
992
|
+
const evicted = noteAntigravityTurnCompletion(instanceKey, turn.conversationId, turn.stepIndex, completion.confirmed);
|
|
993
|
+
if (evicted === null)
|
|
994
|
+
return;
|
|
995
|
+
logger.info('antigravity-transcript-unsettled-evicted', {
|
|
996
|
+
worktreeId: target.worktreeId,
|
|
997
|
+
instanceId: target.instanceId ?? target.cliToolId,
|
|
998
|
+
conversationId: turn.conversationId,
|
|
999
|
+
step: evicted,
|
|
1000
|
+
limit: exports.ANTIGRAVITY_UNSETTLED_TURN_LIMIT,
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Tell the caller whether the turn it was handed is final (Issue #2443).
|
|
1005
|
+
*
|
|
1006
|
+
* `completion` is what the gate reads to decide whether a relay may be told the
|
|
1007
|
+
* turn ended; `completionKey` is what stops it being told twice about one body.
|
|
1008
|
+
* The key names the turn **and** the instant of its newest record, so a turn
|
|
1009
|
+
* that grows after being confirmed is a new state and is announced again once
|
|
1010
|
+
* the new state is itself confirmed — which is exactly the `Stop`-then-`continue`
|
|
1011
|
+
* case `./source` warns about, handled without a second rule.
|
|
1012
|
+
*
|
|
1013
|
+
* Left entirely alone when the body is not confirmed, apart from the word
|
|
1014
|
+
* `provisional`: the gate defaults an absent `completion` to `settled`, so this
|
|
1015
|
+
* is the one place antigravity opts out of the pre-#2443 announcement.
|
|
1016
|
+
*/
|
|
1017
|
+
function reportAntigravityCompletion(report, turn, completion) {
|
|
1018
|
+
if (!report)
|
|
1019
|
+
return;
|
|
1020
|
+
report.completion = completion.confirmed ? 'settled' : 'provisional';
|
|
1021
|
+
report.completionKey = completion.confirmed
|
|
1022
|
+
? `${(0, agent_transcript_1.antigravityTurnRequestId)(turn.conversationId, turn.stepIndex)}@${completion.lastRecordAt}`
|
|
1023
|
+
: undefined;
|
|
1024
|
+
report.completionReason = completion.reason;
|
|
1025
|
+
}
|
|
580
1026
|
/**
|
|
581
1027
|
* Write one rendered turn, unless it is already there.
|
|
582
1028
|
*
|
|
@@ -587,20 +1033,36 @@ function nextTurnOpensAt(turns, userRows, index) {
|
|
|
587
1033
|
* Answering **true** for a turn that was already saved is deliberate. It means
|
|
588
1034
|
* "History holds this turn as Markdown", which is what the poller needs to know
|
|
589
1035
|
* — a second poll of the same finished turn must not save the pane's copy on top
|
|
590
|
-
* of the row this path wrote.
|
|
1036
|
+
* of the row this path wrote. Since #2438 that row is no longer left as it was
|
|
1037
|
+
* found: it is the same comparison {@link growAntigravityTurnRow} makes for the
|
|
1038
|
+
* turns the recheck window covers, made here where both the row and the turn
|
|
1039
|
+
* are already in hand.
|
|
591
1040
|
*
|
|
592
1041
|
* @returns Whether History holds this turn as the agent's own Markdown
|
|
593
1042
|
*/
|
|
594
|
-
async function writeAntigravityTurn(target, turn, rendered, timestampMs, path) {
|
|
1043
|
+
async function writeAntigravityTurn(target, turn, rendered, timestampMs, path, report) {
|
|
595
1044
|
const instanceId = target.instanceId ?? target.cliToolId;
|
|
1045
|
+
// Issue #2436: the caller's report is about the turn THIS call is deciding.
|
|
1046
|
+
// The loop above walks oldest-first, so a verdict left by an earlier turn has
|
|
1047
|
+
// to be cleared before this one's is written.
|
|
1048
|
+
if (report)
|
|
1049
|
+
report.outcome = undefined;
|
|
596
1050
|
if (!(0, transcript_1.isAntigravityTurnWritable)(turn)) {
|
|
597
1051
|
// agy has not finished this answer and no later prompt has taken over, so
|
|
598
1052
|
// 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
|
-
//
|
|
1053
|
+
// with its last paragraph missing into History — the row is keyed on
|
|
1054
|
+
// `(conversationId, step_index)`, so every later read finds it and answers
|
|
1055
|
+
// "already saved". That is Issue #2264, reported against claude and
|
|
602
1056
|
// structurally identical here: a turn cut off after its `tool_calls` renders
|
|
603
1057
|
// a *non-empty* body, so the emptiness guard below cannot see it.
|
|
1058
|
+
//
|
|
1059
|
+
// #2438 made such a row repairable rather than making it acceptable: a
|
|
1060
|
+
// short row only grows while its turn is still among the newest
|
|
1061
|
+
// {@link ANTIGRAVITY_TURN_RECHECK_LIMIT}, and nothing at all rewinds what a
|
|
1062
|
+
// relay already delivered from it. Not writing it in the first place is
|
|
1063
|
+
// still the fix; the repair is the second line.
|
|
1064
|
+
if (report)
|
|
1065
|
+
report.outcome = 'not_yet_closed';
|
|
604
1066
|
logger.info('antigravity-transcript-turn-open', {
|
|
605
1067
|
worktreeId: target.worktreeId,
|
|
606
1068
|
instanceId,
|
|
@@ -654,12 +1116,20 @@ async function writeAntigravityTurn(target, turn, rendered, timestampMs, path) {
|
|
|
654
1116
|
Promise.resolve().then(() => __importStar(require('../../../../lib/ws-server'))),
|
|
655
1117
|
]);
|
|
656
1118
|
const db = getDbInstance();
|
|
657
|
-
|
|
1119
|
+
const existing = findMessageByRequestId(db, target.worktreeId, requestId);
|
|
1120
|
+
if (existing) {
|
|
658
1121
|
logger.debug('antigravity-transcript-turn-already-saved', {
|
|
659
1122
|
worktreeId: target.worktreeId,
|
|
660
1123
|
instanceId,
|
|
661
1124
|
requestId,
|
|
662
1125
|
});
|
|
1126
|
+
// The row may be one of the ones #2438 was reported for — saved at agy's
|
|
1127
|
+
// interim report — and this is the one place that holds both the row and
|
|
1128
|
+
// the turn. The comparison and the notification are not repeated here; see
|
|
1129
|
+
// {@link growAntigravityTurnRow}. The verdict is unchanged: History holds
|
|
1130
|
+
// this turn either way, and `report.outcome` is about this turn's
|
|
1131
|
+
// completeness rather than about an edit.
|
|
1132
|
+
await growAntigravityTurnRow(target, existing, rendered, path);
|
|
663
1133
|
return true;
|
|
664
1134
|
}
|
|
665
1135
|
const message = createMessage(db, {
|