commandmate 0.30.1 → 0.31.0
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 +164 -164
- package/.next/app-path-routes-manifest.json +28 -28
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- 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_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 +3 -3
- 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 +4 -4
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_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 +1 -1
- 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/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.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.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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.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.js +4 -3
- 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.js +4 -3
- 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 +2 -2
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_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.js +2 -2
- package/.next/server/app/chat/page.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +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.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +2 -2
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +2 -2
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +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.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +28 -28
- package/.next/server/chunks/1058.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1262.js +1 -1
- package/.next/server/chunks/1886.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2328.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/261.js +1 -1
- package/.next/server/chunks/3123.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3480.js +5 -4
- package/.next/server/chunks/4299.js +1 -1
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/4443.js +1 -5
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5043.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/552.js +2 -2
- package/.next/server/chunks/6072.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/663.js +4 -3
- package/.next/server/chunks/6894.js +2 -2
- package/.next/server/chunks/7187.js +1 -0
- package/.next/server/chunks/7472.js +1 -1
- package/.next/server/chunks/{880.js → 7859.js} +6 -6
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8800.js +2 -2
- package/.next/server/chunks/8918.js +7 -0
- package/.next/server/chunks/9123.js +2 -2
- package/.next/server/chunks/9130.js +4 -4
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/9696.js +2 -2
- package/.next/server/chunks/9798.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
- package/.next/static/chunks/4718-de1224c9e8a6e7fc.js +1 -0
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
- package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
- package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
- package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
- package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
- package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
- package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
- package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
- package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
- package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
- package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
- package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-97205088520255a5.js +1 -0
- package/.next/static/css/5c13ea243dfdcb66.css +1 -0
- package/.next/trace +13 -13
- package/README.md +37 -11
- package/dist/cli/commands/attach.d.ts +50 -0
- package/dist/cli/commands/attach.d.ts.map +1 -0
- package/dist/cli/commands/attach.js +204 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +114 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +23 -2
- package/dist/cli/commands/ls.d.ts.map +1 -1
- package/dist/cli/commands/ls.js +41 -1
- package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
- package/dist/cli/config/cli-dependencies.js +34 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +5 -0
- package/dist/cli/types/index.d.ts +36 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/config/tmux-pane-config.d.ts +153 -0
- package/dist/config/tmux-pane-config.d.ts.map +1 -0
- package/dist/config/tmux-pane-config.js +172 -0
- package/dist/lib/cli-tools/session-name.d.ts +44 -0
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
- package/dist/lib/cli-tools/session-name.js +57 -0
- package/dist/lib/cli-tools/types.d.ts +1 -1
- package/dist/lib/cli-tools/types.d.ts.map +1 -1
- package/dist/lib/cli-tools/types.js +6 -1
- package/dist/lib/cli-tools/validation.d.ts +34 -0
- package/dist/lib/cli-tools/validation.d.ts.map +1 -0
- package/dist/lib/cli-tools/validation.js +41 -0
- package/dist/lib/detection/status-reason.d.ts +18 -0
- package/dist/lib/detection/status-reason.d.ts.map +1 -1
- package/dist/lib/detection/status-reason.js +18 -0
- package/dist/lib/detection/tools/verified-against.d.ts +57 -7
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +59 -8
- package/dist/lib/detection/version-probes.d.ts +26 -5
- package/dist/lib/detection/version-probes.d.ts.map +1 -1
- package/dist/lib/detection/version-probes.js +28 -6
- package/dist/lib/session/tmux-session-surface.d.ts +369 -0
- package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
- package/dist/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/config/cli-tool-timing-config.js +12 -1
- package/dist/server/src/config/detection-evidence-config.js +5 -0
- package/dist/server/src/config/schedule-config.js +28 -1
- package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
- package/dist/server/src/lib/cli-tools/base.js +13 -8
- package/dist/server/src/lib/cli-tools/claude.js +20 -0
- package/dist/server/src/lib/cli-tools/codex.js +205 -61
- package/dist/server/src/lib/cli-tools/command-code.js +349 -0
- package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
- package/dist/server/src/lib/cli-tools/copilot.js +2 -2
- package/dist/server/src/lib/cli-tools/gemini.js +2 -2
- package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
- package/dist/server/src/lib/cli-tools/index.js +4 -1
- package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
- package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
- package/dist/server/src/lib/cli-tools/manager.js +2 -0
- package/dist/server/src/lib/cli-tools/opencode.js +2 -2
- package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
- package/dist/server/src/lib/cli-tools/types.js +6 -1
- package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
- package/dist/server/src/lib/cmate-parser.js +6 -0
- package/dist/server/src/lib/detection/cli-patterns.js +441 -8
- package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
- package/dist/server/src/lib/detection/selection-shape.js +341 -0
- package/dist/server/src/lib/detection/sgr-background.js +210 -0
- package/dist/server/src/lib/detection/status-detector.js +6 -0
- package/dist/server/src/lib/detection/status-reason.js +18 -0
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
- package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
- package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
- package/dist/server/src/lib/detection/tools/registry.js +6 -4
- package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
- package/dist/server/src/lib/detection/version-probes.js +28 -6
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +101 -21
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +39 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +245 -21
- package/dist/server/src/lib/hooks/sources/claude/transcript.js +175 -13
- package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
- package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
- package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
- package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
- package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
- package/dist/server/src/lib/hooks/sources/index.js +3 -1
- package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
- package/dist/server/src/lib/hooks/sources/registry.js +4 -0
- package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
- package/dist/server/src/lib/hooks/stop-history-capture.js +58 -25
- package/dist/server/src/lib/job-executor.js +12 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
- package/dist/server/src/lib/polling/response-checker.js +112 -7
- package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
- package/dist/server/src/lib/realtime/types.js +15 -5
- package/dist/server/src/lib/response-cleaner.js +24 -1
- package/dist/server/src/lib/response-extractor.js +11 -0
- package/dist/server/src/lib/session/claude-executor.js +223 -4
- package/dist/server/src/lib/session/cli-session.js +52 -0
- package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
- package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
- package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
- package/dist/server/src/lib/tmux/read-mode.js +44 -2
- package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
- package/dist/server/src/lib/tmux/session-hooks.js +122 -0
- package/dist/server/src/lib/tmux/session-status-options.js +213 -0
- package/dist/server/src/lib/tmux/tmux.js +79 -2
- package/dist/server/src/lib/version-checker.js +110 -0
- package/dist/server/src/lib/ws-server.js +16 -10
- package/dist/server/src/types/agent-transcript.js +73 -1
- package/dist/server/src/types/terminal-keys.js +131 -3
- package/dist/types/terminal-keys.d.ts +100 -3
- package/dist/types/terminal-keys.d.ts.map +1 -1
- package/dist/types/terminal-keys.js +131 -3
- package/package.json +1 -1
- package/.next/server/chunks/3099.js +0 -5
- package/.next/server/chunks/7824.js +0 -1
- package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
- package/.next/static/chunks/6381-dbf04a99647f6018.js +0 -1
- package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-aac399392ec8c273.js +0 -1
- package/.next/static/css/23f9c40ecc458c77.css +0 -1
- /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_buildManifest.js +0 -0
- /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_ssgManifest.js +0 -0
|
@@ -400,12 +400,22 @@ async function captureCodexTranscriptTurn(target, capture = {}) {
|
|
|
400
400
|
anchored: pending.anchored,
|
|
401
401
|
});
|
|
402
402
|
}
|
|
403
|
+
// Every prompt row first, then every reply (Issue #2273). The two passes are
|
|
404
|
+
// what let a reply be dated at its turn's END without overtaking the NEXT
|
|
405
|
+
// turn's prompt: a queued `/send` row is written while this turn is still
|
|
406
|
+
// running, so its instant is only knowable once that row has been recorded.
|
|
407
|
+
// With one turn pending — the ordinary case — this is the single call it
|
|
408
|
+
// always was.
|
|
409
|
+
const userRows = [];
|
|
410
|
+
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
411
|
+
const previousStartedAt = index === 0 ? pending.previousStartedAt : pending.turns[index - 1].startedAt;
|
|
412
|
+
userRows.push(await recordCodexUserTurns(target, pending.turns[index], previousStartedAt));
|
|
413
|
+
}
|
|
414
|
+
const lastRecordAt = lastCodexRecordAt(parsed.records);
|
|
403
415
|
let captured = false;
|
|
404
416
|
for (let index = 0; index < pending.turns.length; index += 1) {
|
|
405
417
|
const turn = pending.turns[index];
|
|
406
|
-
|
|
407
|
-
const lastUserRow = await recordCodexUserTurns(target, turn, previousStartedAt);
|
|
408
|
-
captured = await writeCodexTurn(target, turn, (0, transcript_1.renderCodexTurn)(turn), resolveAssistantTimestampMs(turn, lastUserRow), path);
|
|
418
|
+
captured = await writeCodexTurn(target, turn, (0, transcript_1.renderCodexTurn)(turn), resolveAssistantTimestampMs(turn, userRows[index], lastRecordAt.get(turn.turnId) ?? 0, nextTurnOpensAt(pending.turns, userRows, index)), path);
|
|
409
419
|
}
|
|
410
420
|
return captured;
|
|
411
421
|
}
|
|
@@ -544,20 +554,79 @@ async function recordCodexUserTurns(target, turn, previousStartedAt = 0) {
|
|
|
544
554
|
/**
|
|
545
555
|
* When the assistant row for this turn is dated.
|
|
546
556
|
*
|
|
547
|
-
* The turn's
|
|
548
|
-
*
|
|
557
|
+
* **The turn's LAST record, not its first (Issue #2273).** #2197 dated the reply
|
|
558
|
+
* by the first record bearing the `turn_id` so that a row written a poll late
|
|
559
|
+
* still sorted where the conversation put it, and #2196 moved it one millisecond
|
|
560
|
+
* past the last prompt so that `groupMessagesIntoPairs` — which orders by
|
|
561
|
+
* timestamp and nothing else — could never return the answer above the question.
|
|
562
|
+
* Both properties survive: `earliest` is a floor this never goes under, and for
|
|
563
|
+
* codex it is the floor that matters most, because a turn can carry SEVERAL
|
|
564
|
+
* prompts (measured at more than one on 23 of 326 archived turns) and the reply
|
|
565
|
+
* has to sort past all of them.
|
|
566
|
+
*
|
|
567
|
+
* What neither accounted for is the row that lands BETWEEN the prompt and the
|
|
568
|
+
* reply. A tool approval is written when the dialog appears, seconds into the
|
|
569
|
+
* turn, and the chat surface orders its rows by timestamp — so a reply dated at
|
|
570
|
+
* the turn's start draws ABOVE an approval that really happened before it. The
|
|
571
|
+
* turn's last record — for codex, the `task_complete` that closes it — is the
|
|
572
|
+
* moment the turn ended, so everything it produced on the way sorts before it.
|
|
573
|
+
*
|
|
574
|
+
* `nextTurnOpensAt` is the ceiling. The next turn's prompt row may be a `/send`
|
|
575
|
+
* row written while THIS turn was still running — a queued prompt — and a reply
|
|
576
|
+
* that overtook it would be paired with the wrong question.
|
|
577
|
+
*
|
|
578
|
+
* @param lastRecordAt - Epoch ms of the turn's last record, or 0 when unknown
|
|
579
|
+
* @param nextTurnOpensAt - Epoch ms of the next turn's user row, or null when
|
|
580
|
+
* this is the newest turn in the window
|
|
581
|
+
*/
|
|
582
|
+
function resolveAssistantTimestampMs(turn, userRow, lastRecordAt = 0, nextTurnOpensAt = null) {
|
|
583
|
+
const earliest = userRow.timestampMs === null
|
|
584
|
+
? turn.startedAt
|
|
585
|
+
: Math.max(turn.startedAt, userRow.timestampMs + 1);
|
|
586
|
+
const latest = nextTurnOpensAt === null ? Number.POSITIVE_INFINITY : nextTurnOpensAt - 1;
|
|
587
|
+
return Math.max(earliest, Math.min(lastRecordAt, latest));
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* When each turn's last record was written (Issue #2273).
|
|
591
|
+
*
|
|
592
|
+
* Keyed by `turn_id` and walked over the same records {@link buildCodexTurns}
|
|
593
|
+
* walks, with the same `response_item` exclusion — that stream is codex's
|
|
594
|
+
* duplicate of the same events and counting it would be counting each record
|
|
595
|
+
* twice. It is a second pass rather than a field on the accumulator because
|
|
596
|
+
* `./transcript` is not this Issue's to change.
|
|
597
|
+
*
|
|
598
|
+
* Every record of the turn counts, `task_complete` included: that one IS the
|
|
599
|
+
* turn's end and is exactly the instant the reply should be dated by.
|
|
549
600
|
*
|
|
550
|
-
*
|
|
551
|
-
* `groupMessagesIntoPairs` orders by timestamp and nothing else — a tie there is
|
|
552
|
-
* decided by whichever row the database returned first, and the losing
|
|
553
|
-
* arrangement (assistant, then user) is exactly the `orphan` pair #2196 exists
|
|
554
|
-
* to remove. So the reply is moved to the first millisecond after the last
|
|
555
|
-
* prompt: the smallest change that makes the order a property of the data.
|
|
601
|
+
* @returns `turn_id` → epoch ms; absent for a turn with no timestamped record
|
|
556
602
|
*/
|
|
557
|
-
function
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
603
|
+
function lastCodexRecordAt(records) {
|
|
604
|
+
const at = new Map();
|
|
605
|
+
for (const record of records) {
|
|
606
|
+
if (record.type === 'response_item')
|
|
607
|
+
continue;
|
|
608
|
+
const turnId = record.turnId;
|
|
609
|
+
if (!turnId || record.timestampMs === null)
|
|
610
|
+
continue;
|
|
611
|
+
if (record.timestampMs > (at.get(turnId) ?? 0))
|
|
612
|
+
at.set(turnId, record.timestampMs);
|
|
613
|
+
}
|
|
614
|
+
return at;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* The instant the next pending turn's prompt row carries, or null (Issue #2273).
|
|
618
|
+
*
|
|
619
|
+
* The user row's own timestamp when there is one, because that is what History
|
|
620
|
+
* sorts on and it can be EARLIER than the turn's start — an adopted `/send` row
|
|
621
|
+
* was written when CommandMate handed the text to the pane, which for a queued
|
|
622
|
+
* prompt is while the previous turn was still running. The turn's start is the
|
|
623
|
+
* fallback for a turn that produced no row at all.
|
|
624
|
+
*/
|
|
625
|
+
function nextTurnOpensAt(turns, userRows, index) {
|
|
626
|
+
const next = turns[index + 1];
|
|
627
|
+
if (!next)
|
|
628
|
+
return null;
|
|
629
|
+
return userRows[index + 1]?.timestampMs ?? next.startedAt;
|
|
561
630
|
}
|
|
562
631
|
/**
|
|
563
632
|
* Write one rendered turn, unless it is already there.
|
|
@@ -27,12 +27,26 @@
|
|
|
27
27
|
* launch line, so `codex` and `codex-2` in one worktree report as
|
|
28
28
|
* themselves. Verified live — a session launched with
|
|
29
29
|
* `CM_AGENT_INSTANCE_ID=codex-2` posted `instanceId: "codex-2"`.
|
|
30
|
-
* 4. **Hooks do not run until
|
|
30
|
+
* 4. **Hooks do not run until they are trusted.** Trust is recorded in the
|
|
31
31
|
* user's own `~/.codex/config.toml` as
|
|
32
32
|
* `[hooks.state."<file>:<event>:0:0"] trusted_hash`, and an untrusted hook
|
|
33
|
-
* is skipped in complete silence (#1757 P4).
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* is skipped in complete silence (#1757 P4). Issue #1760 declined that
|
|
34
|
+
* dialog on every launch; Issue #2315 measured what that cost — the decline
|
|
35
|
+
* is not remembered, so the dialog returned forever and the hooks never ran
|
|
36
|
+
* — and now answers it with *trust* for a worktree that ships no
|
|
37
|
+
* `.codex/hooks.json` of its own. codex writes the hash; this server only
|
|
38
|
+
* presses the key. See {@link shouldTrustCodexHooks} for the security
|
|
39
|
+
* argument, {@link isCodexHookTrustBypassEnabled} for the flag that is
|
|
40
|
+
* still off, and `docs/design/agent-event-source-interface.md`.
|
|
41
|
+
*
|
|
42
|
+
* ## What keeps the trust once it is granted (Issue #2315)
|
|
43
|
+
*
|
|
44
|
+
* codex keys trust by the hash of the handler, so the generated file has to be
|
|
45
|
+
* byte-identical whoever wrote it. It was not: the hook command named
|
|
46
|
+
* `process.cwd()/scripts/hooks/cmate-agent-event.sh`, so each of the machine's
|
|
47
|
+
* worktree servers rewrote the one shared file with its own checkout and undid
|
|
48
|
+
* the last one's grant. `./relay-install` is the fix — the command now names a
|
|
49
|
+
* copy under `$CODEX_HOME`, and the file is a function of `$CODEX_HOME` alone.
|
|
36
50
|
*
|
|
37
51
|
* ## Why `$CODEX_HOME/hooks.json` and not `<worktree>/.codex/hooks.json`
|
|
38
52
|
*
|
|
@@ -54,10 +68,13 @@
|
|
|
54
68
|
* @module lib/hooks/sources/codex/hooks-config
|
|
55
69
|
*/
|
|
56
70
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.CODEX_SUPPORTED_EVENTS = exports.CODEX_PERMISSION_REQUEST_EVENT = exports.CODEX_REGISTERED_EVENTS = exports.CODEX_SESSION_END_TIMEOUT_SECONDS = exports.CODEX_HOOK_TRUST_BYPASS_FLAG = exports.CODEX_HOOK_TRUST_ENV_VAR = exports.CODEX_PERMISSION_URL_ENV_VAR = exports.CODEX_EVENT_URL_ENV_VAR = exports.CODEX_INSTANCE_ID_ENV_VAR = exports.CODEX_WORKTREE_ID_ENV_VAR = exports.CODEX_TOOL_ENV_VAR = exports.CODEX_HOME_ENV_VAR = exports.CODEX_HOOK_MARKER = void 0;
|
|
71
|
+
exports.CODEX_HOOK_TRUST_POLICY_DEFAULT = exports.CODEX_SUPPORTED_EVENTS = exports.CODEX_PERMISSION_REQUEST_EVENT = exports.CODEX_REGISTERED_EVENTS = exports.CODEX_SESSION_END_TIMEOUT_SECONDS = exports.CODEX_HOOK_TRUST_BYPASS_FLAG = exports.CODEX_HOOK_TRUST_ENV_VAR = exports.CODEX_PERMISSION_URL_ENV_VAR = exports.CODEX_EVENT_URL_ENV_VAR = exports.CODEX_INSTANCE_ID_ENV_VAR = exports.CODEX_WORKTREE_ID_ENV_VAR = exports.CODEX_TOOL_ENV_VAR = exports.CODEX_HOME_ENV_VAR = exports.CODEX_HOOK_MARKER = void 0;
|
|
72
|
+
exports.resolveCodexHookTrustPolicy = resolveCodexHookTrustPolicy;
|
|
58
73
|
exports.isCodexHookTrustBypassEnabled = isCodexHookTrustBypassEnabled;
|
|
74
|
+
exports.shouldTrustCodexHooks = shouldTrustCodexHooks;
|
|
59
75
|
exports.getCodexHome = getCodexHome;
|
|
60
76
|
exports.getCodexHooksPath = getCodexHooksPath;
|
|
77
|
+
exports.resolveCodexRelayCommandPath = resolveCodexRelayCommandPath;
|
|
61
78
|
exports.buildCodexEventHookCommand = buildCodexEventHookCommand;
|
|
62
79
|
exports.buildCodexPermissionHookCommand = buildCodexPermissionHookCommand;
|
|
63
80
|
exports.buildCodexHookSettings = buildCodexHookSettings;
|
|
@@ -74,6 +91,7 @@ const hook_settings_generator_1 = require("../../../../lib/hooks/hook-settings-g
|
|
|
74
91
|
const logger_1 = require("../../../../lib/logger");
|
|
75
92
|
const path_validator_1 = require("../../../../lib/security/path-validator");
|
|
76
93
|
const event_mapper_1 = require("../event-mapper");
|
|
94
|
+
const relay_install_1 = require("./relay-install");
|
|
77
95
|
const tool_id_1 = require("./tool-id");
|
|
78
96
|
const logger = (0, logger_1.createLogger)('lib/hooks/sources/codex/hooks-config');
|
|
79
97
|
/** Loopback: the agent runs on the machine the server runs on. */
|
|
@@ -107,7 +125,12 @@ exports.CODEX_INSTANCE_ID_ENV_VAR = 'CM_AGENT_INSTANCE_ID';
|
|
|
107
125
|
exports.CODEX_EVENT_URL_ENV_VAR = 'CM_HOOK_URL';
|
|
108
126
|
/** Auto-Yes v2 receiver URL, with the correlation keys already in its query. */
|
|
109
127
|
exports.CODEX_PERMISSION_URL_ENV_VAR = 'CM_PERMISSION_HOOK_URL';
|
|
110
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* How this server answers codex's hook trust question.
|
|
130
|
+
*
|
|
131
|
+
* See {@link resolveCodexHookTrustPolicy} for what each value does; anything
|
|
132
|
+
* else, including unset, is {@link CODEX_HOOK_TRUST_POLICY_DEFAULT}.
|
|
133
|
+
*/
|
|
111
134
|
exports.CODEX_HOOK_TRUST_ENV_VAR = 'CM_CODEX_HOOK_TRUST';
|
|
112
135
|
/** codex's own flag for running unreviewed hooks, for one invocation. */
|
|
113
136
|
exports.CODEX_HOOK_TRUST_BYPASS_FLAG = '--dangerously-bypass-hook-trust';
|
|
@@ -150,6 +173,15 @@ exports.CODEX_REGISTERED_EVENTS = {
|
|
|
150
173
|
exports.CODEX_PERMISSION_REQUEST_EVENT = 'PermissionRequest';
|
|
151
174
|
/** The four words a codex session can actually produce, given the config above. */
|
|
152
175
|
exports.CODEX_SUPPORTED_EVENTS = Object.values(exports.CODEX_REGISTERED_EVENTS);
|
|
176
|
+
/** What an unset or unrecognised {@link CODEX_HOOK_TRUST_ENV_VAR} means. */
|
|
177
|
+
exports.CODEX_HOOK_TRUST_POLICY_DEFAULT = 'auto';
|
|
178
|
+
/** Read {@link CODEX_HOOK_TRUST_ENV_VAR}, defaulting anything unrecognised. */
|
|
179
|
+
function resolveCodexHookTrustPolicy() {
|
|
180
|
+
const raw = process.env[exports.CODEX_HOOK_TRUST_ENV_VAR];
|
|
181
|
+
if (raw === 'bypass' || raw === 'never' || raw === 'auto')
|
|
182
|
+
return raw;
|
|
183
|
+
return exports.CODEX_HOOK_TRUST_POLICY_DEFAULT;
|
|
184
|
+
}
|
|
153
185
|
/**
|
|
154
186
|
* Whether to launch codex with {@link CODEX_HOOK_TRUST_BYPASS_FLAG}.
|
|
155
187
|
*
|
|
@@ -161,19 +193,72 @@ exports.CODEX_SUPPORTED_EVENTS = Object.values(exports.CODEX_REGISTERED_EVENTS);
|
|
|
161
193
|
* `.codex/hooks.json`, with no dialog, defeating the exact mechanism codex
|
|
162
194
|
* built to prevent it. A structured `Stop` event is not worth that.
|
|
163
195
|
*
|
|
164
|
-
* So the default posture is: CommandMate writes the config and never grants the
|
|
165
|
-
* trust. The human grants it once, through codex's own review screen, which is
|
|
166
|
-
* also the only thing that may write `~/.codex/config.toml` — a file this
|
|
167
|
-
* server never touches (it holds, among other things, the `notify` entry a
|
|
168
|
-
* user's Computer Use integration depends on). Until then the hooks are inert,
|
|
169
|
-
* the screen scraper keeps doing what it did before this Issue, and
|
|
170
|
-
* `cli-tools/codex` dismisses the review dialog so a session still starts.
|
|
171
|
-
*
|
|
172
196
|
* `CM_CODEX_HOOK_TRUST=bypass` exists for headless and CI operators who have
|
|
173
|
-
* weighed that trade for themselves.
|
|
197
|
+
* weighed that trade for themselves. It is NOT what {@link shouldTrustCodexHooks}
|
|
198
|
+
* does — that answers one dialog, about hooks it has checked the provenance of.
|
|
174
199
|
*/
|
|
175
200
|
function isCodexHookTrustBypassEnabled() {
|
|
176
|
-
return
|
|
201
|
+
return resolveCodexHookTrustPolicy() === 'bypass';
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Whether the server may answer codex's review dialog with *trust* for a
|
|
205
|
+
* session about to start in `worktreePath` (Issue #2315).
|
|
206
|
+
*
|
|
207
|
+
* ## Why this reverses Issue #1760's answer
|
|
208
|
+
*
|
|
209
|
+
* #1760 declined the dialog on the operator's behalf — option 3, *Continue
|
|
210
|
+
* without trusting* — because granting trust writes `[hooks.state…]` into their
|
|
211
|
+
* own `~/.codex/config.toml`. Two years of that measured badly, and the Issue
|
|
212
|
+
* this function exists for is the bill:
|
|
213
|
+
*
|
|
214
|
+
* - **Declining is not remembered.** codex records a *grant*; there is no
|
|
215
|
+
* "asked and refused" state. So the dialog came back on every single launch,
|
|
216
|
+
* which is what made `waitForReady`'s one-shot handling the only thing
|
|
217
|
+
* standing between a session and a pane parked three screens deep.
|
|
218
|
+
* - **The hooks never ran.** CommandMate writes `hooks.json` in order to
|
|
219
|
+
* receive `session_start` / `stop` — the structured events the whole of
|
|
220
|
+
* #1760 exists for. Declining every launch meant the default installation
|
|
221
|
+
* got the dialog and none of the benefit; the means and the end pointed in
|
|
222
|
+
* opposite directions.
|
|
223
|
+
*
|
|
224
|
+
* ## Why this is not `--dangerously-bypass-hook-trust` by another name
|
|
225
|
+
*
|
|
226
|
+
* The objection #1760 raised is real and this function answers it rather than
|
|
227
|
+
* dropping it: a hostile repository can ship `.codex/hooks.json`, codex reads
|
|
228
|
+
* it from `<cwd>`, and *Trust all and continue* would trust that too. So the
|
|
229
|
+
* grant is withheld from exactly that case — a worktree carrying its own
|
|
230
|
+
* `.codex/hooks.json` gets the pre-#2315 decline-and-escape path, and the human
|
|
231
|
+
* answers its dialog themselves.
|
|
232
|
+
*
|
|
233
|
+
* What remains trustable is `$CODEX_HOME/hooks.json`: the operator's own file,
|
|
234
|
+
* holding the operator's own hooks plus the ones this server wrote and marked.
|
|
235
|
+
* Trusting a file the human already owns is a materially different act from
|
|
236
|
+
* trusting one that arrived with a `git clone`.
|
|
237
|
+
*
|
|
238
|
+
* The grant is still a write to `~/.codex/config.toml`, which this server
|
|
239
|
+
* otherwise never touches — it is a documented consequence of the default, not
|
|
240
|
+
* a hidden one, and `CM_CODEX_HOOK_TRUST=never` restores the old behaviour.
|
|
241
|
+
*
|
|
242
|
+
* @param worktreePath - Working directory of the session about to start
|
|
243
|
+
* @returns True when the dialog may be answered with trust
|
|
244
|
+
*/
|
|
245
|
+
function shouldTrustCodexHooks(worktreePath) {
|
|
246
|
+
if (resolveCodexHookTrustPolicy() === 'never')
|
|
247
|
+
return false;
|
|
248
|
+
try {
|
|
249
|
+
// codex reads `<cwd>/.codex/hooks.json` as well as the home one, and a
|
|
250
|
+
// review that includes a hook from the repository is a review this server
|
|
251
|
+
// must not answer.
|
|
252
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(worktreePath, '.codex', 'hooks.json'))) {
|
|
253
|
+
logger.info('codex-hooks-trust-withheld-repo-hooks', { worktreePath });
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// An unreadable worktree is not one to grant trust for.
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
return true;
|
|
177
262
|
}
|
|
178
263
|
/**
|
|
179
264
|
* `$CODEX_HOME`, or `~/.codex`.
|
|
@@ -205,6 +290,25 @@ function getCodexHooksPath(options = {}) {
|
|
|
205
290
|
function fallbackUrlExpression(path, query) {
|
|
206
291
|
return `http://${CODEX_HOOK_HOST}:\${CM_PORT:-3000}${path}${query}`;
|
|
207
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* The relay path `hooks.json` may name — never a checkout (Issue #2315).
|
|
295
|
+
*
|
|
296
|
+
* `resolveRelayScriptPath()` answers with `process.cwd()/scripts/hooks/…`, which
|
|
297
|
+
* is the checkout of whichever server wrote the file. On a machine running
|
|
298
|
+
* several worktree servers against one `$CODEX_HOME/hooks.json` that value is
|
|
299
|
+
* the only part of the generated file that moves, and every time it moves codex
|
|
300
|
+
* throws away the trust the human granted and opens on
|
|
301
|
+
* `Modified since last trusted - review required`. See `./relay-install`.
|
|
302
|
+
*
|
|
303
|
+
* So the auto path is the INSTALLED copy, which is a function of `$CODEX_HOME`
|
|
304
|
+
* alone. An explicit `relayScriptPath` (including `null`) is still honoured
|
|
305
|
+
* verbatim — that is how the suites drive the two command shapes.
|
|
306
|
+
*/
|
|
307
|
+
function resolveCodexRelayCommandPath(options = {}) {
|
|
308
|
+
if (options.relayScriptPath !== undefined)
|
|
309
|
+
return options.relayScriptPath;
|
|
310
|
+
return (0, relay_install_1.getInstalledCodexRelayPath)(getCodexHome(options));
|
|
311
|
+
}
|
|
208
312
|
/**
|
|
209
313
|
* The command for one lifecycle event.
|
|
210
314
|
*
|
|
@@ -215,7 +319,7 @@ function fallbackUrlExpression(path, query) {
|
|
|
215
319
|
*/
|
|
216
320
|
function buildCodexEventHookCommand(event, options = {}) {
|
|
217
321
|
const marker = ` # ${exports.CODEX_HOOK_MARKER}`;
|
|
218
|
-
const relay = options
|
|
322
|
+
const relay = resolveCodexRelayCommandPath(options);
|
|
219
323
|
if (relay) {
|
|
220
324
|
return ([
|
|
221
325
|
(0, hook_settings_generator_1.shellQuote)(relay),
|
|
@@ -371,6 +475,15 @@ function mergeCodexHookSettings(existing, generated) {
|
|
|
371
475
|
*/
|
|
372
476
|
function writeCodexHookSettings(options = {}) {
|
|
373
477
|
const settingsPath = getCodexHooksPath(options);
|
|
478
|
+
// Issue #2315: put the relay where the generated file can name it without
|
|
479
|
+
// naming a checkout, BEFORE the content is built — `buildCodexHookSettings`
|
|
480
|
+
// only reads what is installed, so an install that had not happened yet would
|
|
481
|
+
// emit the inline `curl` shape and give the shared file a third form to drift
|
|
482
|
+
// between. Best-effort by construction: the installer never throws, and a
|
|
483
|
+
// machine where it cannot write simply keeps whatever copy is already there.
|
|
484
|
+
if (options.relayScriptPath === undefined) {
|
|
485
|
+
(0, relay_install_1.installCodexRelayScript)(getCodexHome(options), (0, hook_settings_generator_1.resolveRelayScriptPath)());
|
|
486
|
+
}
|
|
374
487
|
let existing = null;
|
|
375
488
|
let previous = null;
|
|
376
489
|
if ((0, fs_1.existsSync)(settingsPath)) {
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The one path `$CODEX_HOME/hooks.json` is allowed to name (Issue #2315).
|
|
4
|
+
*
|
|
5
|
+
* ## The bug this module exists for
|
|
6
|
+
*
|
|
7
|
+
* `hooks-config` writes ONE file — `$CODEX_HOME/hooks.json` — shared by every
|
|
8
|
+
* codex session on the machine, and its whole design rests on that file being
|
|
9
|
+
* byte-identical whoever wrote it: codex keys hook trust by the hash of the
|
|
10
|
+
* handler, so a file whose bytes move puts the review dialog back in front of
|
|
11
|
+
* the next launch. `writeCodexHookSettings` already refuses to rewrite matching
|
|
12
|
+
* content, and `buildCodexHookSettings` already keeps the port, the worktree and
|
|
13
|
+
* the instance out of the file.
|
|
14
|
+
*
|
|
15
|
+
* One value got through anyway, and it is the one that moves most: the absolute
|
|
16
|
+
* path of the relay script, which `resolveRelayScriptPath()` resolves against
|
|
17
|
+
* `process.cwd()` — the checkout of the server that happened to write the file.
|
|
18
|
+
* Measured on the reporting machine on 2026-09-04, with 22 worktrees registered
|
|
19
|
+
* and several dev servers running:
|
|
20
|
+
*
|
|
21
|
+
* ```
|
|
22
|
+
* $ grep -o "'[^']*cmate-agent-event.sh'" ~/.codex/hooks.json
|
|
23
|
+
* '/Users/…/MyCodeBranchDesk/scripts/hooks/cmate-agent-event.sh'
|
|
24
|
+
* $ pwd # a worktree server, which would rewrite it as its own
|
|
25
|
+
* /Users/…/commandmate-issue-2315
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* So each server rewrites the shared file with its own checkout, every rewrite
|
|
29
|
+
* invalidates the hash the human trusted, and the next codex opens on
|
|
30
|
+
* `Trust Modified since last trusted - review required`. The servers eat each
|
|
31
|
+
* other's trust, forever, which is the "度々" in the Issue.
|
|
32
|
+
*
|
|
33
|
+
* ## The fix
|
|
34
|
+
*
|
|
35
|
+
* Put the script where every server agrees it is: beside the hooks file it is
|
|
36
|
+
* named from, under `$CODEX_HOME/commandmate/`. Each server copies its shipped
|
|
37
|
+
* relay there (a no-op when the bytes already match) and `hooks.json` names the
|
|
38
|
+
* installed copy, so the generated file no longer contains a checkout at all —
|
|
39
|
+
* it is a function of `$CODEX_HOME` alone, which is the same directory codex
|
|
40
|
+
* reads the hooks from by construction.
|
|
41
|
+
*
|
|
42
|
+
* A server whose own copy of the script is unreachable — a global install whose
|
|
43
|
+
* `process.cwd()` is the user's shell directory — installs nothing and uses the
|
|
44
|
+
* copy that is already there, rather than falling back to the inline `curl`
|
|
45
|
+
* form and rewriting the file into a third shape.
|
|
46
|
+
*
|
|
47
|
+
* Copying the SCRIPT rather than hashing it is deliberate. codex trusts a
|
|
48
|
+
* command *string*; it cannot see what that string executes, so two servers on
|
|
49
|
+
* different versions of the script still share one trusted `hooks.json`. The
|
|
50
|
+
* newest server to start wins the script content, which is the same rule the
|
|
51
|
+
* hooks file itself has always had.
|
|
52
|
+
*
|
|
53
|
+
* @module lib/hooks/sources/codex/relay-install
|
|
54
|
+
*/
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.CODEX_RELAY_INSTALL_BASENAME = exports.CODEX_RELAY_INSTALL_DIRNAME = void 0;
|
|
57
|
+
exports.getCodexRelayInstallPath = getCodexRelayInstallPath;
|
|
58
|
+
exports.getInstalledCodexRelayPath = getInstalledCodexRelayPath;
|
|
59
|
+
exports.installCodexRelayScript = installCodexRelayScript;
|
|
60
|
+
const fs_1 = require("fs");
|
|
61
|
+
const path_1 = require("path");
|
|
62
|
+
const logger_1 = require("../../../../lib/logger");
|
|
63
|
+
const logger = (0, logger_1.createLogger)('lib/hooks/sources/codex/relay-install');
|
|
64
|
+
/**
|
|
65
|
+
* Subdirectory of `$CODEX_HOME` this server owns.
|
|
66
|
+
*
|
|
67
|
+
* Namespaced rather than dropped beside `hooks.json` because the directory is
|
|
68
|
+
* the operator's: everything CommandMate puts there is under one name they can
|
|
69
|
+
* delete in one command, and nothing it writes can collide with a file codex
|
|
70
|
+
* itself introduces later.
|
|
71
|
+
*/
|
|
72
|
+
exports.CODEX_RELAY_INSTALL_DIRNAME = 'commandmate';
|
|
73
|
+
/** Basename kept identical to the shipped script, so the two are recognisably one file. */
|
|
74
|
+
exports.CODEX_RELAY_INSTALL_BASENAME = 'cmate-agent-event.sh';
|
|
75
|
+
/** Where {@link installCodexRelayScript} puts the relay, for a given codex home. */
|
|
76
|
+
function getCodexRelayInstallPath(codexHome) {
|
|
77
|
+
return (0, path_1.join)(codexHome, exports.CODEX_RELAY_INSTALL_DIRNAME, exports.CODEX_RELAY_INSTALL_BASENAME);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The installed relay, or null when nothing has installed one yet.
|
|
81
|
+
*
|
|
82
|
+
* Read-only, so the command builders stay free of side effects: the install
|
|
83
|
+
* itself is done once by {@link installCodexRelayScript}, from the one function
|
|
84
|
+
* that was going to touch the disk anyway.
|
|
85
|
+
*/
|
|
86
|
+
function getInstalledCodexRelayPath(codexHome) {
|
|
87
|
+
const target = getCodexRelayInstallPath(codexHome);
|
|
88
|
+
return (0, fs_1.existsSync)(target) ? target : null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Copy the shipped relay to the stable path, and answer where codex should look.
|
|
92
|
+
*
|
|
93
|
+
* Never throws and never fails a launch: hooks are an enhancement to a session
|
|
94
|
+
* that has to start regardless, so every error path here degrades to "use
|
|
95
|
+
* whatever copy is already installed", and then to "no relay", which
|
|
96
|
+
* `buildCodexEventHookCommand` answers with its inline `curl`.
|
|
97
|
+
*
|
|
98
|
+
* Idempotent: the file is opened for writing only when the bytes differ, so the
|
|
99
|
+
* ordinary launch does not touch it. The write itself goes through a temporary
|
|
100
|
+
* file and a rename, because the file being replaced is one a *running* codex
|
|
101
|
+
* session may be executing at that moment — truncating it in place would hand
|
|
102
|
+
* that session half a script.
|
|
103
|
+
*
|
|
104
|
+
* @param codexHome - The directory `hooks.json` lives in
|
|
105
|
+
* @param sourcePath - The shipped script, or null when this process cannot find its own
|
|
106
|
+
* @returns The path to name in `hooks.json`, or null when there is none
|
|
107
|
+
*/
|
|
108
|
+
function installCodexRelayScript(codexHome, sourcePath) {
|
|
109
|
+
const target = getCodexRelayInstallPath(codexHome);
|
|
110
|
+
if (sourcePath && sourcePath !== target) {
|
|
111
|
+
try {
|
|
112
|
+
const desired = (0, fs_1.readFileSync)(sourcePath, 'utf8');
|
|
113
|
+
const current = (0, fs_1.existsSync)(target) ? (0, fs_1.readFileSync)(target, 'utf8') : null;
|
|
114
|
+
if (current !== desired) {
|
|
115
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(target), { recursive: true, mode: 0o700 });
|
|
116
|
+
// `.tmp` beside the target so the rename cannot cross a filesystem.
|
|
117
|
+
const staging = `${target}.tmp`;
|
|
118
|
+
try {
|
|
119
|
+
(0, fs_1.writeFileSync)(staging, desired, { mode: 0o700 });
|
|
120
|
+
(0, fs_1.renameSync)(staging, target);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
try {
|
|
124
|
+
(0, fs_1.unlinkSync)(staging);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Nothing to clean up, or nothing that can be.
|
|
128
|
+
}
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
logger.info('codex-relay-installed', { target });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
// An install that failed is not a launch that failed. If a previous
|
|
136
|
+
// server already put a copy there, that copy is still the right path to
|
|
137
|
+
// name — and naming it is what keeps this file byte-identical.
|
|
138
|
+
logger.warn('codex-relay-install-failed', {
|
|
139
|
+
target,
|
|
140
|
+
error: error instanceof Error ? error.message : String(error),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return (0, fs_1.existsSync)(target) ? target : null;
|
|
145
|
+
}
|