commandmate 0.33.2 → 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 +122 -122
- package/.next/app-path-routes-manifest.json +24 -24
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +15 -15
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/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 +1 -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 +1 -1
- 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.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 +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 +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.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 +24 -24
- 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/3123.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3323.js +1 -1
- package/.next/server/chunks/4443.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 -1
- package/.next/server/chunks/6661.js +1 -1
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/7875.js +1 -1
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8918.js +3 -3
- package/.next/server/chunks/9553.js +1 -0
- package/.next/server/chunks/9627.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/static/chunks/{4718-441a2af91f0374e9.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/trace +13 -13
- package/dist/server/locales/en/worktree.json +9 -2
- package/dist/server/locales/ja/worktree.json +9 -2
- 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 +302 -27
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +103 -0
- package/dist/server/src/lib/polling/structured-history-gate.js +68 -4
- 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 +1 -1
- package/.next/server/chunks/153.js +0 -1
- package/.next/server/chunks/4299.js +0 -1
- package/.next/server/chunks/6838.js +0 -1
- package/.next/server/chunks/7366.js +0 -5
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-38edcd53e51f53b0.js +0 -1
- /package/.next/static/{0a4qrU8WdUwQrlO4mfLMu → 9x6U1h52hH_r6pOsGwI_p}/_buildManifest.js +0 -0
- /package/.next/static/{0a4qrU8WdUwQrlO4mfLMu → 9x6U1h52hH_r6pOsGwI_p}/_ssgManifest.js +0 -0
|
@@ -76,6 +76,8 @@ exports.isAntigravityTurnClosingRecord = isAntigravityTurnClosingRecord;
|
|
|
76
76
|
exports.isAntigravityTurnWritable = isAntigravityTurnWritable;
|
|
77
77
|
exports.isAntigravityPromptRecord = isAntigravityPromptRecord;
|
|
78
78
|
exports.renderAntigravityTurn = renderAntigravityTurn;
|
|
79
|
+
exports.antigravityTurnLastRecordAt = antigravityTurnLastRecordAt;
|
|
80
|
+
exports.resolveAntigravityTurnCompletion = resolveAntigravityTurnCompletion;
|
|
79
81
|
const event_mapper_1 = require("../event-mapper");
|
|
80
82
|
const turn_body_1 = require("../turn-body");
|
|
81
83
|
/**
|
|
@@ -444,3 +446,104 @@ function renderAntigravityTurn(turn) {
|
|
|
444
446
|
unknownRecordTypes: [...unknown],
|
|
445
447
|
};
|
|
446
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Epoch ms of the newest record agy wrote inside this turn, or 0 (Issue #2443).
|
|
451
|
+
*
|
|
452
|
+
* The maximum rather than `records.at(-1)`: `created_at` is agy's own field and
|
|
453
|
+
* a record that carries none reads as null, so the last record in file order is
|
|
454
|
+
* not always the last one with a clock on it. The prompt record is deliberately
|
|
455
|
+
* outside the walk — `records` holds everything *after* the `USER_INPUT` — which
|
|
456
|
+
* is why {@link resolveAntigravityTurnCompletion} floors the comparison at
|
|
457
|
+
* {@link AntigravityTurnAccumulator.startedAt} as well.
|
|
458
|
+
*
|
|
459
|
+
* @returns Epoch ms, or 0 when the turn has no timestamped record
|
|
460
|
+
*/
|
|
461
|
+
function antigravityTurnLastRecordAt(turn) {
|
|
462
|
+
let at = 0;
|
|
463
|
+
for (const record of turn.records) {
|
|
464
|
+
if (record.timestampMs !== null && record.timestampMs > at)
|
|
465
|
+
at = record.timestampMs;
|
|
466
|
+
}
|
|
467
|
+
return at;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Whether agy has vouched for this turn's body (Issue #2443).
|
|
471
|
+
*
|
|
472
|
+
* ## What this is separate from, and why the separation is the Issue
|
|
473
|
+
*
|
|
474
|
+
* {@link isAntigravityTurnWritable} answers "may a row be written from this
|
|
475
|
+
* turn". It has to be generous — agy writes **no record that closes a turn**, so
|
|
476
|
+
* the shape of the last thing it wrote is all there is, and an interim report
|
|
477
|
+
* ("waiting for the worker") is prose with no `tool_calls` exactly like a
|
|
478
|
+
* conclusion is. #2438 made the row that follows from that repairable. What it
|
|
479
|
+
* could not make repairable is everything a save *triggers*: a relay delivering
|
|
480
|
+
* the interim body to the session that asked for the answer cannot be taken
|
|
481
|
+
* back, and `broadcastMessage('message_updated', …)` does not rewind it.
|
|
482
|
+
*
|
|
483
|
+
* So this is the second question — "is this body final" — and it is answered
|
|
484
|
+
* from a different kind of evidence, deliberately:
|
|
485
|
+
*
|
|
486
|
+
* - **not the wording.** "waiting", "Waiting for" and their translations are a
|
|
487
|
+
* model's prose, and a rule keyed on them is wrong the first time the model
|
|
488
|
+
* is asked to answer in another language or writes a conclusion that mentions
|
|
489
|
+
* waiting.
|
|
490
|
+
* - **not a fixed quiet period.** The gaps measured on the reporting machine
|
|
491
|
+
* were 3 / 58 / 156 s from an interim candidate to the next record and 9 /
|
|
492
|
+
* 113 / 118 s from the final one, which overlap: no constant separates them.
|
|
493
|
+
* - **not `status: DONE`** (all 15 measured candidates carry it, early and
|
|
494
|
+
* final alike) **and not `truncated_fields`**, which is agy saying it
|
|
495
|
+
* shortened a field.
|
|
496
|
+
*
|
|
497
|
+
* ## The evidence that is used
|
|
498
|
+
*
|
|
499
|
+
* agy's own `Stop` hook, correlated by instant. `Stop` is agy reporting that its
|
|
500
|
+
* loop ended, and CommandMate already records when one arrived
|
|
501
|
+
* (`session/agent-event-state`'s `getLastStopEventAt`). What makes it usable
|
|
502
|
+
* despite `source.ts`'s warning that a `Stop` can be answered with
|
|
503
|
+
* `{"decision":"continue"}` is that the correlation is an ordering rather than a
|
|
504
|
+
* flag: a stop is evidence about the file **as it was when the stop arrived**.
|
|
505
|
+
*
|
|
506
|
+
* - A resumed loop appends records *after* the stop, which pushes
|
|
507
|
+
* `lastRecordAt` past `stopAt` and takes the confirmation away again. The
|
|
508
|
+
* evidence therefore withdraws itself in exactly the case the warning is
|
|
509
|
+
* about, with no `continue`-detection of its own.
|
|
510
|
+
* - A stop belonging to the *previous* turn is older than this turn's records
|
|
511
|
+
* and confirms nothing.
|
|
512
|
+
* - No stop at all — hooks not wired up, agy killed, CommandMate restarted
|
|
513
|
+
* since — is `no-stop-event`, and the caller keeps the body provisional
|
|
514
|
+
* rather than promoting it.
|
|
515
|
+
*
|
|
516
|
+
* The residual is agy's clock resolution: `created_at` is written to the second,
|
|
517
|
+
* so a record appended in the same second as the stop compares equal to it.
|
|
518
|
+
* That is a sub-second window, it is bounded by one `created_at` tick, and the
|
|
519
|
+
* direction of the error is a body confirmed one record early rather than a turn
|
|
520
|
+
* confirmed that never ended.
|
|
521
|
+
*
|
|
522
|
+
* Pure: the stop instant is a parameter, so this file keeps its no-filesystem,
|
|
523
|
+
* no-database, no-`globalThis` contract and the rule is a property a test states
|
|
524
|
+
* against values rather than against a running server.
|
|
525
|
+
*
|
|
526
|
+
* @param turn - The turn to judge
|
|
527
|
+
* @param stopAt - Epoch ms of this instance's last `Stop`, or null when none has
|
|
528
|
+
* been received
|
|
529
|
+
*/
|
|
530
|
+
function resolveAntigravityTurnCompletion(turn, stopAt) {
|
|
531
|
+
const lastRecordAt = antigravityTurnLastRecordAt(turn);
|
|
532
|
+
const base = { confirmed: false, lastRecordAt, stopAt };
|
|
533
|
+
// A turn agy is still working through has no final body to vouch for. Asked
|
|
534
|
+
// before the clock questions so that "it is still running" never reads as
|
|
535
|
+
// "its records are unstamped".
|
|
536
|
+
if (!isAntigravityTurnWritable(turn))
|
|
537
|
+
return { ...base, reason: 'turn-open' };
|
|
538
|
+
if (lastRecordAt <= 0)
|
|
539
|
+
return { ...base, reason: 'no-timestamped-record' };
|
|
540
|
+
if (stopAt === null)
|
|
541
|
+
return { ...base, reason: 'no-stop-event' };
|
|
542
|
+
// `startedAt` as well as the newest record: a turn whose records all predate
|
|
543
|
+
// its own prompt is a shape this reader has not seen, and taking the later of
|
|
544
|
+
// the two cannot make the test easier to pass.
|
|
545
|
+
if (stopAt < Math.max(lastRecordAt, turn.startedAt)) {
|
|
546
|
+
return { ...base, reason: 'stop-before-last-record' };
|
|
547
|
+
}
|
|
548
|
+
return { confirmed: true, reason: 'stop-after-last-record', lastRecordAt, stopAt };
|
|
549
|
+
}
|
|
@@ -118,9 +118,41 @@ const logger = (0, logger_1.createLogger)('lib/polling/structured-history-gate')
|
|
|
118
118
|
* can see is not a lock.
|
|
119
119
|
*/
|
|
120
120
|
const captureQueue = (globalThis.__structuredHistoryCaptureQueue ??= new Map());
|
|
121
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* The last completion each instance was announced for (Issue #2443).
|
|
123
|
+
*
|
|
124
|
+
* Keyed by the same triple as {@link captureQueue}, holding whatever
|
|
125
|
+
* `StructuredHistoryCaptureReport.completionKey` the reader minted. Its only job
|
|
126
|
+
* is to make the completion edge an *edge*: the poller re-reads a finished turn
|
|
127
|
+
* every couple of seconds, and #2443 forbids adding a path that re-delivers a
|
|
128
|
+
* body somebody already has.
|
|
129
|
+
*
|
|
130
|
+
* On `globalThis` for the reason {@link captureQueue} is, and in memory for the
|
|
131
|
+
* reason `session/agent-event-state` gives: the value describes a live session,
|
|
132
|
+
* and a restart that forgets it costs at most one extra announcement into a
|
|
133
|
+
* relay whose own stash guard already refuses a second payload.
|
|
134
|
+
*/
|
|
135
|
+
const announcedCompletions = (globalThis.__structuredHistoryAnnouncedCompletions ??= new Map());
|
|
136
|
+
/** Forget every instance's in-flight capture and announced completion. Test seam. */
|
|
122
137
|
function resetStructuredHistoryCaptureQueue() {
|
|
123
138
|
captureQueue.clear();
|
|
139
|
+
announcedCompletions.clear();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether this completion has already been announced for this instance (#2443).
|
|
143
|
+
*
|
|
144
|
+
* A reader that minted no key is always announced — the pre-#2443 behaviour, and
|
|
145
|
+
* the behaviour claude, codex and command-code keep. Records the key as a side
|
|
146
|
+
* effect when the answer is "no", because the two steps must not be separable:
|
|
147
|
+
* an announcement that forgot to record would repeat on the next poll.
|
|
148
|
+
*/
|
|
149
|
+
function claimCompletionAnnouncement(key, completionKey) {
|
|
150
|
+
if (completionKey === undefined)
|
|
151
|
+
return true;
|
|
152
|
+
if (announcedCompletions.get(key) === completionKey)
|
|
153
|
+
return false;
|
|
154
|
+
announcedCompletions.set(key, completionKey);
|
|
155
|
+
return true;
|
|
124
156
|
}
|
|
125
157
|
/** The queue key; the same triple `buildCompositeKey` spells everywhere else. */
|
|
126
158
|
function captureKeyOf(worktreeId, cliToolId, instanceId) {
|
|
@@ -296,17 +328,24 @@ async function captureStructuredHistoryTurn(worktreeId, cliToolId, instanceId, c
|
|
|
296
328
|
return false;
|
|
297
329
|
}
|
|
298
330
|
const resolvedInstanceId = instanceId ?? cliToolId;
|
|
299
|
-
|
|
331
|
+
const captureKey = captureKeyOf(worktreeId, cliToolId, resolvedInstanceId);
|
|
332
|
+
return serializePerInstance(captureKey, async () => {
|
|
300
333
|
// The reader's own report, kept local and copied out below: `report` is
|
|
301
334
|
// the caller's object and must end up holding one verdict, not whatever
|
|
302
335
|
// the last reader to touch it happened to leave there.
|
|
303
336
|
const readerReport = {};
|
|
304
337
|
try {
|
|
305
338
|
const captured = await reader.capture({ worktreeId, cliToolId, instanceId: resolvedInstanceId }, capture, readerReport);
|
|
339
|
+
// Issue #2443: absent means `settled`, which is what leaves the three
|
|
340
|
+
// readers that have a turn-closing record exactly where they were.
|
|
341
|
+
const completion = readerReport.completion ?? 'settled';
|
|
306
342
|
if (report) {
|
|
307
343
|
// A reader that says nothing is read as `unavailable` — the pre-#2436
|
|
308
344
|
// behaviour, and the safe direction: the scraper keeps the turn.
|
|
309
345
|
report.outcome = captured ? 'captured' : readerReport.outcome ?? 'unavailable';
|
|
346
|
+
report.completion = completion;
|
|
347
|
+
report.completionKey = readerReport.completionKey;
|
|
348
|
+
report.completionReason = readerReport.completionReason;
|
|
310
349
|
}
|
|
311
350
|
// Issue #2377: the moment a relay is waiting for. This is the single
|
|
312
351
|
// point BOTH triggers of a pull capture pass through — the poller's save
|
|
@@ -317,8 +356,33 @@ async function captureStructuredHistoryTurn(worktreeId, cliToolId, instanceId, c
|
|
|
317
356
|
// Announced only when the capture actually wrote something: a `false`
|
|
318
357
|
// means the scraper is still the writer for this turn, and the poller's
|
|
319
358
|
// own call below will announce it.
|
|
320
|
-
|
|
321
|
-
|
|
359
|
+
//
|
|
360
|
+
// Issue #2443 adds the second condition, and it is the whole Issue.
|
|
361
|
+
// `captured` means History holds the newest turn; it does **not** mean
|
|
362
|
+
// the agent is finished with it, because antigravity has no record that
|
|
363
|
+
// closes a turn and an interim report is saved under the same key the
|
|
364
|
+
// conclusion will land on. Announcing here would hand a relay the
|
|
365
|
+
// interim body as the answer, and `broadcastMessage('message_updated',
|
|
366
|
+
// …)` — the repair #2438 added — does not take a delivered message
|
|
367
|
+
// back. So a provisional capture announces nothing at all; the relay
|
|
368
|
+
// keeps waiting on the deadline it already has, and the settled capture
|
|
369
|
+
// that follows announces the finished body.
|
|
370
|
+
if (captured && completion === 'settled') {
|
|
371
|
+
if (claimCompletionAnnouncement(captureKey, readerReport.completionKey)) {
|
|
372
|
+
(0, relay_triggers_1.onRelayTurnCompleted)(worktreeId, cliToolId, resolvedInstanceId, true);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else if (captured) {
|
|
376
|
+
logger.info('structured-history-capture-provisional', {
|
|
377
|
+
worktreeId,
|
|
378
|
+
cliToolId,
|
|
379
|
+
instanceId: resolvedInstanceId,
|
|
380
|
+
// The reader's own word for what is missing; see
|
|
381
|
+
// `AntigravityTurnCompletionReason`. This is the line #2443 asks for
|
|
382
|
+
// — the reason left on the relay's waiting path.
|
|
383
|
+
reason: readerReport.completionReason ?? 'unknown',
|
|
384
|
+
});
|
|
385
|
+
}
|
|
322
386
|
return captured;
|
|
323
387
|
}
|
|
324
388
|
catch (error) {
|
|
@@ -42,14 +42,26 @@ exports.prepareAgentLaunch = prepareAgentLaunch;
|
|
|
42
42
|
exports.buildAgentLaunchCommandLine = buildAgentLaunchCommandLine;
|
|
43
43
|
const sources_1 = require("../../lib/hooks/sources");
|
|
44
44
|
const agent_event_state_1 = require("../../lib/session/agent-event-state");
|
|
45
|
+
const session_generation_archive_1 = require("../../lib/session/session-generation-archive");
|
|
45
46
|
const logger_1 = require("../../lib/logger");
|
|
46
47
|
const logger = (0, logger_1.createLogger)('lib/session/agent-session-lifecycle');
|
|
47
48
|
/**
|
|
48
|
-
* Open a new event generation for an agent instance that is about to start
|
|
49
|
+
* Open a new event generation for an agent instance that is about to start,
|
|
50
|
+
* and retire the previous process's chat history (Issue #2444).
|
|
49
51
|
*
|
|
50
52
|
* Safe to call for a tool that emits nothing: the fence is a timestamp, and a
|
|
51
53
|
* tool with no events simply never has any to fence.
|
|
52
54
|
*
|
|
55
|
+
* The archive rides here rather than in its own seam because this function is
|
|
56
|
+
* already the answer to "a new agent process is being created for this
|
|
57
|
+
* (worktree, instance)" — the one fact that distinguishes a replacement from a
|
|
58
|
+
* reconnect, and the fact `chat_messages.archived` needs. See
|
|
59
|
+
* `lib/session/session-generation-archive` for why observing the *death*
|
|
60
|
+
* instead would archive live conversations. Note that the boundary is this call
|
|
61
|
+
* and not the adoption mark: codex's and opencode's relaunch paths run
|
|
62
|
+
* `reconcileExistingSession`, which sets an adoption mark, so a reader of that
|
|
63
|
+
* mark would miss exactly the endings this exists for.
|
|
64
|
+
*
|
|
53
65
|
* @param target - The instance being created
|
|
54
66
|
* @param at - Epoch ms; defaults to now
|
|
55
67
|
*/
|
|
@@ -70,6 +82,24 @@ function beginAgentSession(target, at = Date.now()) {
|
|
|
70
82
|
// learn by noticing their `respond` no longer has anything to answer.
|
|
71
83
|
decisionsEvicted: after - before,
|
|
72
84
|
});
|
|
85
|
+
// Issue #2444: the rows the replaced process wrote are a previous session's
|
|
86
|
+
// history now. Inside a `try` and after the fence on purpose — this module
|
|
87
|
+
// otherwise touches nothing but memory, and a database that is missing,
|
|
88
|
+
// locked or mid-migration must cost a log line, never a session that refuses
|
|
89
|
+
// to start. It is also a no-op by construction wherever there is no database
|
|
90
|
+
// to reach (see `resolveSessionArchiveDatabase`), which is what keeps the
|
|
91
|
+
// suites that call this with tmux mocked and no DB at all unchanged.
|
|
92
|
+
try {
|
|
93
|
+
(0, session_generation_archive_1.archiveSupersededSessionMessages)(target);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
logger.warn('session-generation-archive-failed', {
|
|
97
|
+
worktreeId: target.worktreeId,
|
|
98
|
+
cliToolId: target.cliToolId,
|
|
99
|
+
instanceId: target.instanceId ?? target.cliToolId,
|
|
100
|
+
error: error instanceof Error ? error.message : String(error),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
73
103
|
}
|
|
74
104
|
/**
|
|
75
105
|
* The command that starts this agent, with whatever config it needs written
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Retire the previous process's chat history when a new one takes its place
|
|
4
|
+
* (Issue #2444).
|
|
5
|
+
*
|
|
6
|
+
* `chat_messages.archived` means "a previous session's history", and until this
|
|
7
|
+
* module the only thing that ever wrote it was
|
|
8
|
+
* `POST /api/worktrees/:id/kill-session`. That covers the one ending nobody
|
|
9
|
+
* actually gets: a session killed *through CommandMate*. A tmux server that
|
|
10
|
+
* went away, a CLI that was `/exit`ed back to its shell, a machine that
|
|
11
|
+
* rebooted — none of those pass through that route, so the dead session's rows
|
|
12
|
+
* stayed `archived = 0` and the chat surface kept showing them as the current
|
|
13
|
+
* conversation. Worse, the route refuses to help afterwards: with no live
|
|
14
|
+
* session left to kill it returns 404 *before* reaching the archive call, so
|
|
15
|
+
* the rows could not be retired by hand either.
|
|
16
|
+
*
|
|
17
|
+
* ## Why the seam is "a new process starts", not "the old one died"
|
|
18
|
+
*
|
|
19
|
+
* Observing the death is the tempting place — `current-output-builder`'s
|
|
20
|
+
* `!running` branch already knows — and it is the wrong one. `isRunning` is a
|
|
21
|
+
* `has-session` probe with a timeout in front of it and a liquid status
|
|
22
|
+
* verdict behind it; a single slow probe reads as `false` for a session that is
|
|
23
|
+
* very much alive, and archiving there would throw away a live conversation.
|
|
24
|
+
* "A new agent process is being created for this (worktree, instance)" is not a
|
|
25
|
+
* judgement call: {@link beginAgentSession} is called on exactly that fact, on
|
|
26
|
+
* every tool's creation path and on codex's / opencode's relaunch-into-the-same-pane
|
|
27
|
+
* path (#2070), and deliberately NOT on opencode's live-reuse path, where the
|
|
28
|
+
* process is the same process. The rows that belong to the process being
|
|
29
|
+
* replaced are precisely the ones to retire.
|
|
30
|
+
*
|
|
31
|
+
* ## Why it is its own module
|
|
32
|
+
*
|
|
33
|
+
* `agent-session-lifecycle` is an in-memory fence and nothing else — no
|
|
34
|
+
* database, no sockets — and every `src/lib/cli-tools/<tool>.ts` imports it.
|
|
35
|
+
* Keeping the database and the WebSocket here means that graph does not change:
|
|
36
|
+
* the lifecycle module calls one function, inside a `try`, and a failure to
|
|
37
|
+
* archive is a logged warning rather than a session that refuses to start.
|
|
38
|
+
*
|
|
39
|
+
* ## Known limitation
|
|
40
|
+
*
|
|
41
|
+
* A transcript reader that INSERTs a *new* row for the previous session after
|
|
42
|
+
* this has run writes it with `archived = 0`, so it lands in the new session's
|
|
43
|
+
* history. Updates to rows that already exist are unaffected: no writer touches
|
|
44
|
+
* `archived` on update. Measured as rare enough to leave alone — the readers
|
|
45
|
+
* run behind the same `startSession` that triggers this — and it is recorded
|
|
46
|
+
* here rather than guarded, because guarding it means a second notion of "which
|
|
47
|
+
* generation is this row from" and that is the schema #168 rejected.
|
|
48
|
+
*
|
|
49
|
+
* @module lib/session/session-generation-archive
|
|
50
|
+
*/
|
|
51
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
52
|
+
if (k2 === undefined) k2 = k;
|
|
53
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
54
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
55
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
56
|
+
}
|
|
57
|
+
Object.defineProperty(o, k2, desc);
|
|
58
|
+
}) : (function(o, m, k, k2) {
|
|
59
|
+
if (k2 === undefined) k2 = k;
|
|
60
|
+
o[k2] = m[k];
|
|
61
|
+
}));
|
|
62
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
63
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
64
|
+
}) : function(o, v) {
|
|
65
|
+
o["default"] = v;
|
|
66
|
+
});
|
|
67
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
68
|
+
var ownKeys = function(o) {
|
|
69
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
70
|
+
var ar = [];
|
|
71
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
72
|
+
return ar;
|
|
73
|
+
};
|
|
74
|
+
return ownKeys(o);
|
|
75
|
+
};
|
|
76
|
+
return function (mod) {
|
|
77
|
+
if (mod && mod.__esModule) return mod;
|
|
78
|
+
var result = {};
|
|
79
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
80
|
+
__setModuleDefault(result, mod);
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
})();
|
|
84
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
85
|
+
exports.resolveSessionArchiveDatabase = resolveSessionArchiveDatabase;
|
|
86
|
+
exports.archiveSupersededSessionMessages = archiveSupersededSessionMessages;
|
|
87
|
+
const db_instance_1 = require("../../lib/db/db-instance");
|
|
88
|
+
const chat_db_1 = require("../../lib/db/chat-db");
|
|
89
|
+
const types_1 = require("../../lib/realtime/types");
|
|
90
|
+
const logger_1 = require("../../lib/logger");
|
|
91
|
+
const logger = (0, logger_1.createLogger)('lib/session/session-generation-archive');
|
|
92
|
+
/**
|
|
93
|
+
* The database this module archives through, or `null` when there is none to
|
|
94
|
+
* archive through.
|
|
95
|
+
*
|
|
96
|
+
* `getDbInstance()` **creates** a database when the file is not there yet, and
|
|
97
|
+
* that is the one thing this call must never do from here. Every production
|
|
98
|
+
* caller arrives via an API route that has already opened the connection, so
|
|
99
|
+
* the singleton is warm and this is a map lookup. A Vitest worker is the
|
|
100
|
+
* opposite case: `beginAgentSession` is reached by a dozen suites that mock
|
|
101
|
+
* tmux and never touch a database, and opening one for them would either
|
|
102
|
+
* fabricate `<cwd>/data/cm.db` or — when the suite runs in a checkout that has
|
|
103
|
+
* one — hand those fixtures the developer's real chat history to write into.
|
|
104
|
+
*
|
|
105
|
+
* So under Vitest the answer is "no database" unless a test hands one in
|
|
106
|
+
* explicitly (see {@link archiveSupersededSessionMessages}'s `db` parameter) or
|
|
107
|
+
* mocks `@/lib/db/db-instance` **and** clears `VITEST`, which is how the
|
|
108
|
+
* integration test drives the production branch. Only `VITEST` is consulted,
|
|
109
|
+
* never `NODE_ENV`: `vitest.config.ts` `define`s `process.env.NODE_ENV` to the
|
|
110
|
+
* literal `'test'` at transform time, so a `NODE_ENV` check here would fold to
|
|
111
|
+
* a constant and no test could ever reach the other branch.
|
|
112
|
+
*/
|
|
113
|
+
function resolveSessionArchiveDatabase() {
|
|
114
|
+
if (process.env.VITEST)
|
|
115
|
+
return null;
|
|
116
|
+
return (0, db_instance_1.getDbInstance)();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Archive the active chat rows of the process being replaced.
|
|
120
|
+
*
|
|
121
|
+
* Scoped to one `(worktreeId, instanceId)` pair, which is what makes a restart
|
|
122
|
+
* of `codex` leave `codex-2`'s conversation alone — the two share a worktree and
|
|
123
|
+
* a tool id and nothing else. Already-archived rows are not touched (the SQL
|
|
124
|
+
* filters on `archived = 0`), so calling this twice is not two generations.
|
|
125
|
+
*
|
|
126
|
+
* Nothing happens when there was nothing to archive: no `recomputeLastUserMessage`
|
|
127
|
+
* (the sidebar's value cannot have changed) and no frame on the wire (a client
|
|
128
|
+
* asked to re-read identical history would just be paying for a round trip).
|
|
129
|
+
* That is also what keeps a healthy-reuse `startSession` — the path that never
|
|
130
|
+
* calls in here at all — indistinguishable from a first-ever launch.
|
|
131
|
+
*
|
|
132
|
+
* Throws whatever the database throws; the caller in `agent-session-lifecycle`
|
|
133
|
+
* catches, because failing to retire old rows must not stop a session from
|
|
134
|
+
* starting.
|
|
135
|
+
*
|
|
136
|
+
* @param target - The instance whose previous process is being replaced
|
|
137
|
+
* @param db - The database to write through; defaults to
|
|
138
|
+
* {@link resolveSessionArchiveDatabase}
|
|
139
|
+
* @returns The row count and the instance it was scoped to
|
|
140
|
+
*/
|
|
141
|
+
function archiveSupersededSessionMessages(target, db = resolveSessionArchiveDatabase()) {
|
|
142
|
+
const instanceId = target.instanceId ?? target.cliToolId;
|
|
143
|
+
if (!db)
|
|
144
|
+
return { archived: 0, instanceId };
|
|
145
|
+
const archived = (0, chat_db_1.deleteMessagesByInstance)(db, target.worktreeId, instanceId);
|
|
146
|
+
if (archived === 0)
|
|
147
|
+
return { archived: 0, instanceId };
|
|
148
|
+
// Same pairing `kill-session` uses: the sidebar's `last_user_message` is
|
|
149
|
+
// derived from the *active* rows, so archiving without recomputing leaves it
|
|
150
|
+
// quoting a conversation the surface no longer shows.
|
|
151
|
+
(0, chat_db_1.recomputeLastUserMessage)(db, target.worktreeId);
|
|
152
|
+
logger.info('session-generation-archived', {
|
|
153
|
+
worktreeId: target.worktreeId,
|
|
154
|
+
cliToolId: target.cliToolId,
|
|
155
|
+
instanceId,
|
|
156
|
+
archived,
|
|
157
|
+
});
|
|
158
|
+
broadcastMessagesInvalidated(target.worktreeId, target.cliToolId, instanceId);
|
|
159
|
+
return { archived, instanceId };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Tell every open pane for this instance to re-read its history.
|
|
163
|
+
*
|
|
164
|
+
* A scope rather than a payload, for the reason `MESSAGES_INVALIDATED_EVENT_TYPE`
|
|
165
|
+
* gives: an archive has no row to publish — `message` / `message_updated` can
|
|
166
|
+
* only ever say what a row now *looks like* — so the settled state has to come
|
|
167
|
+
* from the server. PC split panes and the phone both listen through
|
|
168
|
+
* `useSplitMessages`, which matches on (worktreeId, cliToolId, instanceId) and
|
|
169
|
+
* does not branch on `reason`.
|
|
170
|
+
*
|
|
171
|
+
* Detached, and the `ws-server` import is dynamic, for the same bargain
|
|
172
|
+
* `broadcastRecordedRow` in `current-output-builder` strikes: this module sits
|
|
173
|
+
* in the import graph of every `src/lib/cli-tools/<tool>.ts` (through
|
|
174
|
+
* `agent-session-lifecycle`), and none of them should pull the WebSocket server
|
|
175
|
+
* in just by starting a pane. The rows are already committed when this runs, so
|
|
176
|
+
* a socket write that throws cannot turn a completed archive into a failure.
|
|
177
|
+
*/
|
|
178
|
+
function broadcastMessagesInvalidated(worktreeId, cliToolId, instanceId) {
|
|
179
|
+
void Promise.resolve().then(() => __importStar(require('../../lib/ws-server'))).then(({ broadcastMessage }) => {
|
|
180
|
+
broadcastMessage(types_1.MESSAGES_INVALIDATED_EVENT_TYPE, {
|
|
181
|
+
worktreeId,
|
|
182
|
+
cliToolId,
|
|
183
|
+
instanceId,
|
|
184
|
+
reason: 'session_generation',
|
|
185
|
+
});
|
|
186
|
+
})
|
|
187
|
+
.catch((error) => {
|
|
188
|
+
logger.warn('session-generation-invalidate-broadcast-failed', {
|
|
189
|
+
worktreeId,
|
|
190
|
+
instanceId,
|
|
191
|
+
error: error instanceof Error ? error.message : String(error),
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
@@ -15,14 +15,16 @@
|
|
|
15
15
|
* @module lib/tasks/contract-message
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.REQUIRE_COMMIT_SOURCE_CONTRACT = exports.REQUIRE_COMMIT_SOURCE_CONFIG = void 0;
|
|
18
|
+
exports.BUILT_IN_GATE_ORDER = exports.REQUIRE_COMMIT_SOURCE_CONTRACT = exports.REQUIRE_COMMIT_SOURCE_CONFIG = void 0;
|
|
19
19
|
exports.resolveRequireCommit = resolveRequireCommit;
|
|
20
20
|
exports.resolveContractGateIds = resolveContractGateIds;
|
|
21
|
+
exports.runsEnvCleanGate = runsEnvCleanGate;
|
|
21
22
|
exports.contractGateDefinitions = contractGateDefinitions;
|
|
22
23
|
exports.validateContractAgainstVerifyConfig = validateContractAgainstVerifyConfig;
|
|
23
24
|
exports.resolveGateCommands = resolveGateCommands;
|
|
24
25
|
exports.composeContractMessage = composeContractMessage;
|
|
25
26
|
const verify_config_1 = require("../../lib/verification/verify-config");
|
|
27
|
+
const env_clean_gate_1 = require("../../lib/verification/env-clean-gate");
|
|
26
28
|
/**
|
|
27
29
|
* How the built-in gates read in the preamble; they run git plumbing, not shell
|
|
28
30
|
* commands.
|
|
@@ -35,6 +37,14 @@ const verify_config_1 = require("../../lib/verification/verify-config");
|
|
|
35
37
|
const WORK_EVIDENCE_ANY_CHANGE_LABEL = `${verify_config_1.WORK_EVIDENCE_GATE_ID}(commit または未 commit の変更が存在すること)`;
|
|
36
38
|
const WORK_EVIDENCE_COMMIT_LABEL = `${verify_config_1.WORK_EVIDENCE_GATE_ID}(commit が存在すること。未 commit の変更は作業証跡として数えない)`;
|
|
37
39
|
const SCOPE_LABEL = `${verify_config_1.SCOPE_GATE_ID}(変更ファイルが scope.allow の内側に収まっていること)`;
|
|
40
|
+
/**
|
|
41
|
+
* `env-clean` reads the machine, not the repository, so the preamble has to say
|
|
42
|
+
* so (#2442). Without this row the gate would run — and could fail the run —
|
|
43
|
+
* without ever having been named in the completion criterion the agent was sent,
|
|
44
|
+
* which is the same "declared and never checked" defect pointed the other way.
|
|
45
|
+
*/
|
|
46
|
+
const ENV_CLEAN_LABEL = `${verify_config_1.ENV_CLEAN_GATE_ID}(タスク開始時に在ったポート・tmux セッション・$HOME / ~/.commandmate ` +
|
|
47
|
+
'直下のエントリが、増えても減っても不合格)';
|
|
38
48
|
/** The obligation line, in the two forms the pipeline can actually enforce. */
|
|
39
49
|
const COMMIT_REQUIRED_LINE = '- 作業完了後は必ず commit すること(未 commit の作業は未完了とみなされる)';
|
|
40
50
|
const COMMIT_EXPECTED_LINE = '- 作業完了後は commit すること(ただし work-evidence は未 commit の変更も作業証跡として' +
|
|
@@ -63,6 +73,18 @@ function resolveRequireCommit(contract, config) {
|
|
|
63
73
|
sources.push(exports.REQUIRE_COMMIT_SOURCE_CONTRACT);
|
|
64
74
|
return { required: sources.length > 0, sources };
|
|
65
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* The built-in gates, in the order `gate-runner` runs them.
|
|
78
|
+
*
|
|
79
|
+
* Named once because two things have to agree with it: the resolved gate id list
|
|
80
|
+
* below and the preamble's command list. A contract that typed
|
|
81
|
+
* `gates: [lint, env-clean]` must still be told the order the run will take.
|
|
82
|
+
*/
|
|
83
|
+
exports.BUILT_IN_GATE_ORDER = [
|
|
84
|
+
verify_config_1.WORK_EVIDENCE_GATE_ID,
|
|
85
|
+
verify_config_1.SCOPE_GATE_ID,
|
|
86
|
+
verify_config_1.ENV_CLEAN_GATE_ID,
|
|
87
|
+
];
|
|
66
88
|
/**
|
|
67
89
|
* The gate ids a contract asks for, or null for "every gate".
|
|
68
90
|
*
|
|
@@ -70,24 +92,54 @@ function resolveRequireCommit(contract, config) {
|
|
|
70
92
|
* gates run. A contract that required work evidence or a clean scope while
|
|
71
93
|
* listing only `[lint, unit]` would otherwise declare rules that nothing
|
|
72
94
|
* checked: the flags would read as enforced and the gates would never run.
|
|
95
|
+
*
|
|
96
|
+
* `env-clean` joined that rule in #2442. Only the contract's own half is visible
|
|
97
|
+
* here — `options.requireEnvClean` lives in verify.yaml, which this function does
|
|
98
|
+
* not take — so callers that hold a config OR the two together;
|
|
99
|
+
* `selectGates` in gate-runner already does, and so does
|
|
100
|
+
* {@link resolveGateCommands} for the sentence the agent reads.
|
|
73
101
|
*/
|
|
74
102
|
function resolveContractGateIds(contract) {
|
|
75
103
|
const gates = contract.verify.gates;
|
|
76
104
|
if (!gates)
|
|
77
105
|
return null;
|
|
78
|
-
const
|
|
106
|
+
const required = new Map([
|
|
79
107
|
[verify_config_1.WORK_EVIDENCE_GATE_ID, contract.success.requireWorkEvidence],
|
|
80
108
|
[verify_config_1.SCOPE_GATE_ID, contract.success.requireScopeClean],
|
|
81
|
-
|
|
109
|
+
[verify_config_1.ENV_CLEAN_GATE_ID, contract.success.requireEnvClean],
|
|
110
|
+
]);
|
|
82
111
|
// Built-ins are listed first and in their execution order even when the
|
|
83
112
|
// contract already named one, so the resolved list reads as the order the run
|
|
84
113
|
// will actually take rather than the order the contract happened to type.
|
|
85
|
-
const selected =
|
|
86
|
-
|
|
87
|
-
.map(([id]) => id);
|
|
88
|
-
const rest = gates.filter((id) => !builtIns.some(([builtIn]) => builtIn === id));
|
|
114
|
+
const selected = exports.BUILT_IN_GATE_ORDER.filter((id) => required.get(id) === true || gates.includes(id));
|
|
115
|
+
const rest = gates.filter((id) => !exports.BUILT_IN_GATE_ORDER.includes(id));
|
|
89
116
|
return [...selected, ...rest];
|
|
90
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Whether a verification run for this contract will include `env-clean` (#2442).
|
|
120
|
+
*
|
|
121
|
+
* Three declarations can put the gate in a run and the baseline has to be
|
|
122
|
+
* recorded for all three, because the snapshot is taken once — at send — and
|
|
123
|
+
* cannot be reconstructed later:
|
|
124
|
+
*
|
|
125
|
+
* 1. `options.requireEnvClean` in the repository's verify.yaml,
|
|
126
|
+
* 2. `success.requireEnvClean` in the contract,
|
|
127
|
+
* 3. the contract naming `env-clean` in `verify.gates`.
|
|
128
|
+
*
|
|
129
|
+
* (3) is the one that was easy to miss. Opening the id to `verify.gates` without
|
|
130
|
+
* also asking here would have made every contract that used it report UNKNOWN
|
|
131
|
+
* forever: `selectGates` would run the gate, and `recordEnvBaseline` — reading
|
|
132
|
+
* only the OR of (1) and (2) — would never have written anything to compare
|
|
133
|
+
* against. An operator's `verify --gates env-clean` on a task created without any
|
|
134
|
+
* of the three still reports UNKNOWN, which is correct: no baseline exists, and
|
|
135
|
+
* inventing one from the state at verification time is the fail-open this gate
|
|
136
|
+
* refuses.
|
|
137
|
+
*/
|
|
138
|
+
function runsEnvCleanGate(contract, config) {
|
|
139
|
+
if ((0, env_clean_gate_1.resolveRequireEnvClean)(contract, config).required)
|
|
140
|
+
return true;
|
|
141
|
+
return resolveContractGateIds(contract)?.includes(verify_config_1.ENV_CLEAN_GATE_ID) ?? false;
|
|
142
|
+
}
|
|
91
143
|
/**
|
|
92
144
|
* The gates this contract defines itself (#1791).
|
|
93
145
|
*
|
|
@@ -146,7 +198,16 @@ function validateContractAgainstVerifyConfig(contract, config) {
|
|
|
146
198
|
"repository's own — rename the contract gate.");
|
|
147
199
|
}
|
|
148
200
|
if (gates) {
|
|
149
|
-
|
|
201
|
+
// `env-clean` joins the built-ins a contract may name (#2442). It is a
|
|
202
|
+
// reserved id, so it can never appear in `configIds` — leaving it out of this
|
|
203
|
+
// set made `verify.gates: [env-clean]` an unknown id at send, which is how
|
|
204
|
+
// the gate ended up reachable only through the repository-wide switch.
|
|
205
|
+
const known = new Set([
|
|
206
|
+
verify_config_1.WORK_EVIDENCE_GATE_ID,
|
|
207
|
+
verify_config_1.SCOPE_GATE_ID,
|
|
208
|
+
verify_config_1.ENV_CLEAN_GATE_ID,
|
|
209
|
+
...configIds,
|
|
210
|
+
]);
|
|
150
211
|
const defined = new Set(definitions.map((gate) => gate.id));
|
|
151
212
|
const unknown = gates.filter((id) => !known.has(id) && !defined.has(id));
|
|
152
213
|
if (unknown.length > 0) {
|
|
@@ -174,11 +235,16 @@ function resolveGateCommands(contract, config) {
|
|
|
174
235
|
const builtInLabels = new Map([
|
|
175
236
|
[verify_config_1.WORK_EVIDENCE_GATE_ID, workEvidenceLabel],
|
|
176
237
|
[verify_config_1.SCOPE_GATE_ID, SCOPE_LABEL],
|
|
238
|
+
// Without this row a contract naming `env-clean` resolved to `undefined` and
|
|
239
|
+
// the preamble handed the agent the literal string "undefined" as one of the
|
|
240
|
+
// commands it had to pass.
|
|
241
|
+
[verify_config_1.ENV_CLEAN_GATE_ID, ENV_CLEAN_LABEL],
|
|
177
242
|
]);
|
|
178
243
|
// Contract-defined gates run after the repository's own, so the preamble
|
|
179
244
|
// lists them in that order too — the line claims to be "the commands that
|
|
180
245
|
// will run", and an order it invents would be the first thing to drift.
|
|
181
246
|
const declared = [...config.gates, ...contractGateDefinitions(contract)];
|
|
247
|
+
const envCleanRequired = (0, env_clean_gate_1.resolveRequireEnvClean)(contract, config).required;
|
|
182
248
|
const selected = resolveContractGateIds(contract);
|
|
183
249
|
if (!selected) {
|
|
184
250
|
// An omitted gates list runs every gate, and the built-ins are still governed
|
|
@@ -186,10 +252,18 @@ function resolveGateCommands(contract, config) {
|
|
|
186
252
|
const builtIns = [workEvidenceLabel];
|
|
187
253
|
if (contract.success.requireScopeClean)
|
|
188
254
|
builtIns.push(SCOPE_LABEL);
|
|
255
|
+
if (envCleanRequired)
|
|
256
|
+
builtIns.push(ENV_CLEAN_LABEL);
|
|
189
257
|
return [...builtIns, ...declared.map((gate) => gate.command)];
|
|
190
258
|
}
|
|
259
|
+
// Re-derive the built-in prefix instead of trusting `selected`'s: the
|
|
260
|
+
// repository-wide `options.requireEnvClean` forces the gate into the run
|
|
261
|
+
// without appearing in the contract at all, and a preamble that omitted it
|
|
262
|
+
// would hand the agent a completion criterion the run does not use.
|
|
263
|
+
const builtIns = exports.BUILT_IN_GATE_ORDER.filter((id) => selected.includes(id) || (id === verify_config_1.ENV_CLEAN_GATE_ID && envCleanRequired));
|
|
264
|
+
const rest = selected.filter((id) => !exports.BUILT_IN_GATE_ORDER.includes(id));
|
|
191
265
|
const byId = new Map(declared.map((gate) => [gate.id, gate.command]));
|
|
192
|
-
return
|
|
266
|
+
return [...builtIns, ...rest].map((id) => builtInLabels.get(id) ?? byId.get(id));
|
|
193
267
|
}
|
|
194
268
|
/**
|
|
195
269
|
* Compose the message sent to the agent: contract preamble, then the goal.
|
|
@@ -76,6 +76,7 @@ const SUCCESS_KEYS = [
|
|
|
76
76
|
'requireWorkEvidence',
|
|
77
77
|
'requireScopeClean',
|
|
78
78
|
'requireCommit',
|
|
79
|
+
'requireEnvClean',
|
|
79
80
|
'autoVerifyOnStop',
|
|
80
81
|
];
|
|
81
82
|
class TaskContractError extends Error {
|
|
@@ -314,6 +315,7 @@ function validateSuccess(value, issues) {
|
|
|
314
315
|
requireWorkEvidence: true,
|
|
315
316
|
requireScopeClean: true,
|
|
316
317
|
requireCommit: false,
|
|
318
|
+
requireEnvClean: false,
|
|
317
319
|
autoVerifyOnStop: false,
|
|
318
320
|
};
|
|
319
321
|
if (value === undefined || value === null)
|
package/package.json
CHANGED