commandmate 0.41.0 → 0.42.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 +356 -356
- package/.next/app-path-routes-manifest.json +33 -33
- package/.next/build-manifest.json +5 -5
- package/.next/prerender-manifest.json +9 -9
- package/.next/react-loadable-manifest.json +1 -1
- 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.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.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/release-notes/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/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 +2 -2
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route.js +1 -1
- package/.next/server/app/api/relays/route.js.nft.json +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.js.nft.json +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/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]/direct-input/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/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 +103 -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 +103 -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 -103
- 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.nft.json +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_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -103
- 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.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/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 +33 -33
- package/.next/server/chunks/1068.js +1 -0
- package/.next/server/chunks/1210.js +1 -1
- package/.next/server/chunks/1501.js +5 -5
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3707.js +1 -1
- package/.next/server/chunks/3718.js +1 -0
- package/.next/server/chunks/434.js +1 -1
- package/.next/server/chunks/4443.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/5775.js +1 -0
- package/.next/server/chunks/611.js +1 -0
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/650.js +1 -1
- package/.next/server/chunks/6781.js +1 -1
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8581.js +1 -1
- package/.next/server/chunks/8583.js +1 -1
- package/.next/server/chunks/8673.js +2 -2
- package/.next/server/chunks/8728.js +3 -3
- package/.next/server/chunks/8791.js +1 -0
- package/.next/server/chunks/8800.js +1 -1
- package/.next/server/chunks/8918.js +1 -103
- package/.next/server/chunks/9130.js +2 -2
- package/.next/server/chunks/964.js +1 -1
- package/.next/server/chunks/9731.js +3 -3
- package/.next/server/chunks/9882.js +3 -3
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{1642-fb2e176aaadbd137.js → 1642-767aed8e7c61ef7f.js} +1 -1
- package/.next/static/chunks/{2407-99799e3c2ff03bae.js → 2407-faae66d204748f7b.js} +1 -1
- package/.next/static/chunks/{2619-04bc32f026a0d946.js → 2619-a305ad4810f1393a.js} +1 -1
- package/.next/static/chunks/530.578854fdd5d91542.js +1 -0
- package/.next/static/chunks/7705-2a2936551b0cf9a3.js +1 -0
- package/.next/static/chunks/8165-235859c6930f01b1.js +1 -0
- package/.next/static/chunks/app/{layout-1fb647d6df55c498.js → layout-9a715043610e4e27.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-61dd928d635db590.js +1 -0
- package/.next/static/chunks/app/worktrees/[id]/terminal/{page-373ea37b16d930c7.js → page-c601f3b3ece6557e.js} +1 -1
- package/.next/static/chunks/{webpack-7e5907979c182510.js → webpack-49ade0526854dd4e.js} +1 -1
- package/.next/static/css/{974314e796232f53.css → b3f433d52b8ed5c8.css} +1 -1
- package/.next/trace +13 -13
- package/dist/cli/commands/attach.d.ts +6 -4
- package/dist/cli/commands/attach.d.ts.map +1 -1
- package/dist/cli/commands/attach.js +36 -5
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +5 -0
- package/dist/cli/commands/ls.d.ts.map +1 -1
- package/dist/cli/commands/ls.js +19 -9
- package/dist/cli/commands/whoami.d.ts +9 -25
- package/dist/cli/commands/whoami.d.ts.map +1 -1
- package/dist/cli/commands/whoami.js +18 -42
- package/dist/cli/types/api-responses.d.ts +37 -0
- package/dist/cli/types/api-responses.d.ts.map +1 -1
- package/dist/lib/cli-tools/session-name.d.ts +72 -4
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -1
- package/dist/lib/cli-tools/session-name.js +115 -12
- package/dist/lib/detection/tools/verified-against.d.ts +11 -2
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +11 -2
- package/dist/lib/session/tmux-session-surface.d.ts +9 -7
- package/dist/lib/session/tmux-session-surface.d.ts.map +1 -1
- package/dist/lib/session/tmux-session-surface.js +15 -8
- package/dist/lib/tmux/legacy-session-alias.d.ts +43 -0
- package/dist/lib/tmux/legacy-session-alias.d.ts.map +1 -0
- package/dist/lib/tmux/legacy-session-alias.js +64 -0
- package/dist/lib/verification/verify-config.d.ts +21 -0
- package/dist/lib/verification/verify-config.d.ts.map +1 -1
- package/dist/lib/verification/verify-config.js +54 -1
- package/dist/server/locales/en/worktree.json +4 -1
- package/dist/server/locales/ja/worktree.json +4 -1
- package/dist/server/server.js +29 -0
- package/dist/server/src/lib/auto-yes-poller.js +15 -0
- package/dist/server/src/lib/cli-tools/antigravity.js +1 -1
- package/dist/server/src/lib/cli-tools/base.js +10 -1
- package/dist/server/src/lib/cli-tools/codex.js +1 -1
- package/dist/server/src/lib/cli-tools/command-code.js +1 -1
- package/dist/server/src/lib/cli-tools/copilot.js +1 -1
- package/dist/server/src/lib/cli-tools/gemini.js +1 -1
- package/dist/server/src/lib/cli-tools/legacy-session-adoption.js +19 -0
- package/dist/server/src/lib/cli-tools/opencode.js +1 -1
- package/dist/server/src/lib/cli-tools/session-name.js +115 -12
- package/dist/server/src/lib/cli-tools/session-namespace.js +55 -0
- package/dist/server/src/lib/cli-tools/session-ownership.js +21 -0
- package/dist/server/src/lib/cli-tools/vibe-local.js +1 -1
- package/dist/server/src/lib/cli-tools/worktree-session-ownership.js +28 -0
- package/dist/server/src/lib/db/app-settings-db.js +29 -0
- package/dist/server/src/lib/detection/cli-patterns.js +46 -8
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +8 -2
- package/dist/server/src/lib/detection/tools/codex/detect.js +8 -1
- package/dist/server/src/lib/detection/tools/codex/prompt.js +6 -2
- package/dist/server/src/lib/detection/tools/verified-against.js +11 -2
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +77 -2
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +77 -1
- package/dist/server/src/lib/realtime/terminal-broadcast.js +11 -0
- package/dist/server/src/lib/session/adopt-legacy-sessions.js +89 -0
- package/dist/server/src/lib/session/claude-session.js +13 -10
- package/dist/server/src/lib/session/current-output-builder.js +18 -0
- package/dist/server/src/lib/session/send-user-message.js +26 -0
- package/dist/server/src/lib/session/session-instance-targets.js +53 -0
- package/dist/server/src/lib/session/tmux-session-surface.js +15 -8
- package/dist/server/src/lib/session/worktree-session-reconcile.js +101 -56
- package/dist/server/src/lib/session-cleanup.js +33 -3
- package/dist/server/src/lib/tmux/legacy-session-alias.js +64 -0
- package/dist/server/src/lib/tmux/session-hook-scripts.js +12 -4
- package/dist/server/src/lib/tmux/session-ownership.js +174 -0
- package/dist/server/src/lib/tmux/tmux.js +13 -3
- package/dist/server/src/lib/verification/env-clean-gate.js +46 -14
- package/dist/server/src/lib/verification/gate-runner.js +1 -0
- package/dist/server/src/lib/verification/verify-config.js +54 -1
- package/dist/server/src/lib/ws-server.js +11 -0
- package/package.json +1 -1
- package/release-notes/0.41.1.json +16 -0
- package/release-notes/0.42.0.json +62 -0
- package/.next/server/chunks/3323.js +0 -1
- package/.next/server/chunks/7075.js +0 -1
- package/.next/server/chunks/9080.js +0 -1
- package/.next/static/chunks/530.e31cc754677fed0f.js +0 -1
- package/.next/static/chunks/7705-25076b57224da370.js +0 -1
- package/.next/static/chunks/8165-d3b7c8a7aa776bc7.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-f24da37453224716.js +0 -1
- /package/.next/static/{UoGuvKnR_kGftU9RHtebq → EbTDBXcXRpFNH4eom-HVv}/_buildManifest.js +0 -0
- /package/.next/static/{UoGuvKnR_kGftU9RHtebq → EbTDBXcXRpFNH4eom-HVv}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* tmux session ownership (Issue #2865)
|
|
4
|
+
*
|
|
5
|
+
* Session names (`mcbd-{cli}-{worktreeId}`) carry nothing that identifies the
|
|
6
|
+
* CommandMate server that created them, and worktree IDs are derived from the
|
|
7
|
+
* directory name — so two servers with different DBs and different worktree
|
|
8
|
+
* paths can resolve the SAME session name on the shared default tmux socket.
|
|
9
|
+
* Deciding "is it running?" by name alone then shows, types into, kills and
|
|
10
|
+
* adopts the OTHER server's session.
|
|
11
|
+
*
|
|
12
|
+
* CommandMate always creates sessions with `tmux new-session -c <worktree.path>`,
|
|
13
|
+
* so `#{session_path}` records which worktree a session belongs to. A session is
|
|
14
|
+
* "owned" only when the realpath of its `#{session_path}` equals the realpath of
|
|
15
|
+
* the worktree's path; anything else under the same name is "foreign" and is
|
|
16
|
+
* excluded from display, input, stop and reuse.
|
|
17
|
+
*
|
|
18
|
+
* A worktree whose directory has since moved therefore sees its old session as
|
|
19
|
+
* foreign. That is intentional (fail safe).
|
|
20
|
+
*/
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.ForeignSessionError = exports.FOREIGN_SESSION_ERROR_CODE = void 0;
|
|
26
|
+
exports.normalizeOwnershipPath = normalizeOwnershipPath;
|
|
27
|
+
exports.isSessionPathOwnedBy = isSessionPathOwnedBy;
|
|
28
|
+
exports.createCachedOwnershipMatcher = createCachedOwnershipMatcher;
|
|
29
|
+
exports.reportForeignSession = reportForeignSession;
|
|
30
|
+
exports.resetForeignSessionWarningsForTesting = resetForeignSessionWarningsForTesting;
|
|
31
|
+
exports.checkSessionOwnership = checkSessionOwnership;
|
|
32
|
+
exports.assertSessionNotForeign = assertSessionNotForeign;
|
|
33
|
+
exports.foreignSessionErrorBody = foreignSessionErrorBody;
|
|
34
|
+
exports.ownedSessionNameSet = ownedSessionNameSet;
|
|
35
|
+
const fs_1 = __importDefault(require("fs"));
|
|
36
|
+
const path_1 = __importDefault(require("path"));
|
|
37
|
+
const logger_1 = require("../../lib/logger");
|
|
38
|
+
const tmux_1 = require("./tmux");
|
|
39
|
+
const logger = (0, logger_1.createLogger)('session-ownership');
|
|
40
|
+
exports.FOREIGN_SESSION_ERROR_CODE = 'session_owned_by_other_server';
|
|
41
|
+
/**
|
|
42
|
+
* Thrown when a code path would adopt / drive a session another server owns.
|
|
43
|
+
*/
|
|
44
|
+
class ForeignSessionError extends Error {
|
|
45
|
+
sessionName;
|
|
46
|
+
sessionPath;
|
|
47
|
+
worktreePath;
|
|
48
|
+
code = exports.FOREIGN_SESSION_ERROR_CODE;
|
|
49
|
+
constructor(sessionName, sessionPath, worktreePath) {
|
|
50
|
+
super(`tmux session "${sessionName}" belongs to another server ` +
|
|
51
|
+
`(session_path=${sessionPath ?? 'unknown'}, worktree=${worktreePath})`);
|
|
52
|
+
this.sessionName = sessionName;
|
|
53
|
+
this.sessionPath = sessionPath;
|
|
54
|
+
this.worktreePath = worktreePath;
|
|
55
|
+
this.name = 'ForeignSessionError';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.ForeignSessionError = ForeignSessionError;
|
|
59
|
+
/**
|
|
60
|
+
* Normalize a path for ownership comparison: realpath when it resolves,
|
|
61
|
+
* otherwise `path.resolve()`; trailing `/` removed; case preserved.
|
|
62
|
+
*/
|
|
63
|
+
function normalizeOwnershipPath(p) {
|
|
64
|
+
let resolved;
|
|
65
|
+
try {
|
|
66
|
+
resolved = fs_1.default.realpathSync.native(p);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
resolved = path_1.default.resolve(p);
|
|
70
|
+
}
|
|
71
|
+
if (resolved.length > 1) {
|
|
72
|
+
resolved = resolved.replace(/\/+$/, '');
|
|
73
|
+
}
|
|
74
|
+
return resolved === '' ? '/' : resolved;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Pure comparison: is a session created in `sessionPath` owned by the worktree
|
|
78
|
+
* at `worktreePath`? `null` (tmux could not say) is never owned.
|
|
79
|
+
*
|
|
80
|
+
* @param normalize - Path normalizer; {@link createCachedOwnershipMatcher}
|
|
81
|
+
* passes a memoized one. Defaults to {@link normalizeOwnershipPath}.
|
|
82
|
+
*/
|
|
83
|
+
function isSessionPathOwnedBy(sessionPath, worktreePath, normalize = normalizeOwnershipPath) {
|
|
84
|
+
if (sessionPath === null || sessionPath === '')
|
|
85
|
+
return false;
|
|
86
|
+
return normalize(sessionPath) === normalize(worktreePath);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build an `isSessionPathOwnedBy` that memoizes realpath per input path. Meant
|
|
90
|
+
* to live for one request (e.g. the batch status listing), so a moved/created
|
|
91
|
+
* directory is picked up on the next request.
|
|
92
|
+
*/
|
|
93
|
+
function createCachedOwnershipMatcher() {
|
|
94
|
+
const cache = new Map();
|
|
95
|
+
const norm = (p) => {
|
|
96
|
+
let v = cache.get(p);
|
|
97
|
+
if (v === undefined) {
|
|
98
|
+
v = normalizeOwnershipPath(p);
|
|
99
|
+
cache.set(p, v);
|
|
100
|
+
}
|
|
101
|
+
return v;
|
|
102
|
+
};
|
|
103
|
+
return (sessionPath, worktreePath) => isSessionPathOwnedBy(sessionPath, worktreePath, norm);
|
|
104
|
+
}
|
|
105
|
+
const warnedForeignSessions = new Set();
|
|
106
|
+
/**
|
|
107
|
+
* Log `session:foreign-detected` once per session name for the process lifetime.
|
|
108
|
+
*/
|
|
109
|
+
function reportForeignSession(sessionName, sessionPath, worktreePath) {
|
|
110
|
+
if (warnedForeignSessions.has(sessionName))
|
|
111
|
+
return;
|
|
112
|
+
warnedForeignSessions.add(sessionName);
|
|
113
|
+
logger.warn('session:foreign-detected', { sessionName, sessionPath, worktreePath });
|
|
114
|
+
}
|
|
115
|
+
/** Test-only: forget which foreign sessions were already reported. */
|
|
116
|
+
function resetForeignSessionWarningsForTesting() {
|
|
117
|
+
warnedForeignSessions.clear();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Decide whether `sessionName` is absent, owned by the worktree at
|
|
121
|
+
* `worktreePath`, or foreign. A session that exists but whose
|
|
122
|
+
* `#{session_path}` cannot be read is treated as foreign (fail safe).
|
|
123
|
+
*/
|
|
124
|
+
async function checkSessionOwnership(sessionName, worktreePath) {
|
|
125
|
+
if (!(await (0, tmux_1.hasSession)(sessionName))) {
|
|
126
|
+
return { verdict: 'absent', sessionPath: null };
|
|
127
|
+
}
|
|
128
|
+
const sessionPath = await (0, tmux_1.getSessionWorkingDirectory)(sessionName);
|
|
129
|
+
if (sessionPath !== null && isSessionPathOwnedBy(sessionPath, worktreePath)) {
|
|
130
|
+
return { verdict: 'owned', sessionPath };
|
|
131
|
+
}
|
|
132
|
+
reportForeignSession(sessionName, sessionPath, worktreePath);
|
|
133
|
+
return { verdict: 'foreign', sessionPath };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Throw `ForeignSessionError` when `sessionName` is foreign; otherwise return
|
|
137
|
+
* the ownership verdict (`owned` or `absent`).
|
|
138
|
+
*/
|
|
139
|
+
async function assertSessionNotForeign(sessionName, worktreePath) {
|
|
140
|
+
const ownership = await checkSessionOwnership(sessionName, worktreePath);
|
|
141
|
+
if (ownership.verdict === 'foreign') {
|
|
142
|
+
throw new ForeignSessionError(sessionName, ownership.sessionPath, worktreePath);
|
|
143
|
+
}
|
|
144
|
+
return ownership;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* JSON body for the HTTP 409 an API route returns for a foreign session.
|
|
148
|
+
*/
|
|
149
|
+
function foreignSessionErrorBody(sessionName, sessionPath) {
|
|
150
|
+
return {
|
|
151
|
+
error: `tmux session "${sessionName}" belongs to another CommandMate server`,
|
|
152
|
+
code: exports.FOREIGN_SESSION_ERROR_CODE,
|
|
153
|
+
sessionName,
|
|
154
|
+
sessionPath,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* From one batch `listSessions()` result, the names of the sessions the worktree
|
|
159
|
+
* at `worktreePath` owns. Feed this — not the raw name set — to status detection
|
|
160
|
+
* so a same-named foreign session never reads as "running". Other worktrees'
|
|
161
|
+
* sessions drop out too, which is harmless: status detection only looks up the
|
|
162
|
+
* worktree's own session names.
|
|
163
|
+
*
|
|
164
|
+
* @param matcher - Pass one `createCachedOwnershipMatcher()` across all worktrees
|
|
165
|
+
* of a request so each realpath is resolved once.
|
|
166
|
+
*/
|
|
167
|
+
function ownedSessionNameSet(tmuxSessions, worktreePath, matcher = createCachedOwnershipMatcher()) {
|
|
168
|
+
const owned = new Set();
|
|
169
|
+
for (const session of tmuxSessions) {
|
|
170
|
+
if (matcher(session.path ?? null, worktreePath))
|
|
171
|
+
owned.add(session.name);
|
|
172
|
+
}
|
|
173
|
+
return owned;
|
|
174
|
+
}
|
|
@@ -30,6 +30,7 @@ const child_process_1 = require("child_process");
|
|
|
30
30
|
const util_1 = require("util");
|
|
31
31
|
const tmux_capture_cache_1 = require("./tmux-capture-cache");
|
|
32
32
|
const geometry_delegation_1 = require("./geometry-delegation");
|
|
33
|
+
const legacy_session_alias_1 = require("./legacy-session-alias");
|
|
33
34
|
const validation_1 = require("../../lib/cli-tools/validation");
|
|
34
35
|
const tmux_pane_config_1 = require("../../config/tmux-pane-config");
|
|
35
36
|
const logger_1 = require("../../lib/logger");
|
|
@@ -181,6 +182,9 @@ async function hasSession(sessionName) {
|
|
|
181
182
|
}
|
|
182
183
|
catch {
|
|
183
184
|
// tmux has-session returns non-zero exit code if session doesn't exist
|
|
185
|
+
// Issue #2866: an adopted legacy session that is gone no longer serves its
|
|
186
|
+
// new-format name, so the next start uses the new-format name.
|
|
187
|
+
(0, legacy_session_alias_1.dropLegacyAliasByLegacyName)(sessionName);
|
|
184
188
|
return false;
|
|
185
189
|
}
|
|
186
190
|
}
|
|
@@ -225,19 +229,23 @@ async function getSessionWorkingDirectory(sessionName) {
|
|
|
225
229
|
*/
|
|
226
230
|
async function listSessions() {
|
|
227
231
|
try {
|
|
228
|
-
|
|
232
|
+
// Issue #2865: `#{session_path}` is the LAST column and tab-separated, so a
|
|
233
|
+
// path containing `|` or spaces survives intact (everything after the third
|
|
234
|
+
// tab is the path).
|
|
235
|
+
const { stdout } = await execFileAsync('tmux', ['list-sessions', '-F', '#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_path}'], { timeout: DEFAULT_TIMEOUT });
|
|
229
236
|
if (!stdout || stdout.trim() === '') {
|
|
230
237
|
return [];
|
|
231
238
|
}
|
|
232
239
|
return stdout
|
|
233
|
-
.trim()
|
|
234
240
|
.split('\n')
|
|
241
|
+
.filter(line => line.trim() !== '')
|
|
235
242
|
.map(line => {
|
|
236
|
-
const [name, windows, attached] = line.split('
|
|
243
|
+
const [name, windows, attached, ...rest] = line.split('\t');
|
|
237
244
|
return {
|
|
238
245
|
name,
|
|
239
246
|
windows: parseInt(windows, 10) || 0,
|
|
240
247
|
attached: attached === '1',
|
|
248
|
+
path: rest.join('\t'),
|
|
241
249
|
};
|
|
242
250
|
});
|
|
243
251
|
}
|
|
@@ -628,6 +636,8 @@ async function killSession(sessionName) {
|
|
|
628
636
|
await execFileAsync('tmux', ['kill-session', '-t', exactTarget(sessionName)], {
|
|
629
637
|
timeout: DEFAULT_TIMEOUT,
|
|
630
638
|
});
|
|
639
|
+
// Issue #2866: see hasSession.
|
|
640
|
+
(0, legacy_session_alias_1.dropLegacyAliasByLegacyName)(sessionName);
|
|
631
641
|
return true;
|
|
632
642
|
}
|
|
633
643
|
catch (error) {
|
|
@@ -85,10 +85,13 @@ function resolveRequireEnvClean(contract, config) {
|
|
|
85
85
|
sources.push(exports.REQUIRE_ENV_CLEAN_SOURCE_CONTRACT);
|
|
86
86
|
return { required: sources.length > 0, sources };
|
|
87
87
|
}
|
|
88
|
-
/** CLI tool ids, longest first: `vibe-local` must not be stripped as `vibe`. */
|
|
89
|
-
const CLI_PREFIXES = [...types_1.CLI_TOOL_IDS].sort((a, b) => b.length - a.length);
|
|
90
88
|
/**
|
|
91
|
-
* Attribute an `mcbd
|
|
89
|
+
* Attribute an `mcbd-[<ns>-]<cli>-<worktreeId>[-suffix]` session name to a
|
|
90
|
+
* worktree.
|
|
91
|
+
*
|
|
92
|
+
* The namespace (Issue #2866) is not consulted: the worktree ID is what ties a
|
|
93
|
+
* session to this task, and a session this task's agent started in any
|
|
94
|
+
* server's namespace is still this task's addition.
|
|
92
95
|
*
|
|
93
96
|
* Ambiguity resolves towards `self` on purpose. Worktree ids may contain
|
|
94
97
|
* hyphens, so `mcbd-claude-foo-bar` is genuinely ambiguous between worktree
|
|
@@ -97,13 +100,10 @@ const CLI_PREFIXES = [...types_1.CLI_TOOL_IDS].sort((a, b) => b.length - a.lengt
|
|
|
97
100
|
* rather than a missed leak.
|
|
98
101
|
*/
|
|
99
102
|
function attributeSessionName(name, worktreeId) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const rest = name.slice(env_snapshot_1.MCBD_SESSION_PREFIX.length);
|
|
103
|
-
const cli = CLI_PREFIXES.find((id) => rest.startsWith(`${id}-`));
|
|
104
|
-
if (!cli)
|
|
103
|
+
const parsed = (0, session_name_1.parseSessionName)(name);
|
|
104
|
+
if (!parsed)
|
|
105
105
|
return 'unattributed';
|
|
106
|
-
const tail = rest
|
|
106
|
+
const tail = parsed.rest;
|
|
107
107
|
if (tail === worktreeId || tail.startsWith(`${worktreeId}-`))
|
|
108
108
|
return 'self';
|
|
109
109
|
return 'other';
|
|
@@ -191,8 +191,9 @@ function toChange(entry, owner) {
|
|
|
191
191
|
* as an empty set — would report every entry as added or removed, which is worse
|
|
192
192
|
* than useless, and treating it as equal would be the fail-open.
|
|
193
193
|
*/
|
|
194
|
-
function diffEnvSnapshots(baseline, final, context) {
|
|
194
|
+
function diffEnvSnapshots(baseline, final, context, options = {}) {
|
|
195
195
|
const taskSession = readTaskSession(baseline);
|
|
196
|
+
const ignoredHomeEntries = new Set(options.ignoreHomeEntries ?? []);
|
|
196
197
|
const probes = env_snapshot_1.ENV_PROBE_IDS.map((probeId) => {
|
|
197
198
|
const before = baseline.probes[probeId];
|
|
198
199
|
const after = final.probes[probeId];
|
|
@@ -205,6 +206,7 @@ function diffEnvSnapshots(baseline, final, context) {
|
|
|
205
206
|
ignoredAdded: [],
|
|
206
207
|
taskSessionAdded: [],
|
|
207
208
|
removed: [],
|
|
209
|
+
ignoredByConfig: [],
|
|
208
210
|
};
|
|
209
211
|
}
|
|
210
212
|
if (!after || after.status !== 'ok') {
|
|
@@ -216,17 +218,26 @@ function diffEnvSnapshots(baseline, final, context) {
|
|
|
216
218
|
ignoredAdded: [],
|
|
217
219
|
taskSessionAdded: [],
|
|
218
220
|
removed: [],
|
|
221
|
+
ignoredByConfig: [],
|
|
219
222
|
};
|
|
220
223
|
}
|
|
221
224
|
const beforeKeys = new Set(before.entries.map((entry) => entry.key));
|
|
222
225
|
const afterKeys = new Set(after.entries.map((entry) => entry.key));
|
|
226
|
+
// Only `home-entries`, and only by the whole name: the same string under
|
|
227
|
+
// `~/.commandmate` is a different directory and stays counted.
|
|
228
|
+
const isIgnoredByConfig = (entry) => probeId === 'home-entries' && ignoredHomeEntries.has(entry.key);
|
|
223
229
|
const added = [];
|
|
224
230
|
const ignoredAdded = [];
|
|
225
231
|
const taskSessionAdded = [];
|
|
232
|
+
const ignoredByConfig = [];
|
|
226
233
|
for (const entry of after.entries) {
|
|
227
234
|
if (beforeKeys.has(entry.key))
|
|
228
235
|
continue;
|
|
229
236
|
const owner = attributeEntry(probeId, entry, context);
|
|
237
|
+
if (isIgnoredByConfig(entry)) {
|
|
238
|
+
ignoredByConfig.push(toChange(entry, owner));
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
230
241
|
if (probeId === 'tmux-sessions' && taskSession && entry.key === taskSession) {
|
|
231
242
|
// Additions only: a task session that existed at task start and is gone
|
|
232
243
|
// falls through to `removed` below like everything else (#1624).
|
|
@@ -235,9 +246,13 @@ function diffEnvSnapshots(baseline, final, context) {
|
|
|
235
246
|
}
|
|
236
247
|
(owner === 'other' ? ignoredAdded : added).push(toChange(entry, owner));
|
|
237
248
|
}
|
|
238
|
-
const removed =
|
|
239
|
-
|
|
240
|
-
|
|
249
|
+
const removed = [];
|
|
250
|
+
for (const entry of before.entries) {
|
|
251
|
+
if (afterKeys.has(entry.key))
|
|
252
|
+
continue;
|
|
253
|
+
const change = toChange(entry, attributeEntry(probeId, entry, context));
|
|
254
|
+
(isIgnoredByConfig(entry) ? ignoredByConfig : removed).push(change);
|
|
255
|
+
}
|
|
241
256
|
return {
|
|
242
257
|
probeId,
|
|
243
258
|
status: added.length + removed.length > 0 ? 'violated' : 'clean',
|
|
@@ -246,6 +261,7 @@ function diffEnvSnapshots(baseline, final, context) {
|
|
|
246
261
|
ignoredAdded,
|
|
247
262
|
taskSessionAdded,
|
|
248
263
|
removed,
|
|
264
|
+
ignoredByConfig,
|
|
249
265
|
};
|
|
250
266
|
});
|
|
251
267
|
// A measured violation is a verdict and outranks an unmeasured probe; an
|
|
@@ -296,6 +312,18 @@ function formatTaskSessionChanges(changes) {
|
|
|
296
312
|
return ` + ${change.key}${detail} [task session, excused]`;
|
|
297
313
|
});
|
|
298
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* `home-entries` changes dropped by `options.envCleanIgnoreHomeEntries`, on one
|
|
317
|
+
* line (#2890). Listed rather than dropped for the reason the excused task
|
|
318
|
+
* session is: a verdict that silently discounted an entry would read exactly
|
|
319
|
+
* like one that never saw it.
|
|
320
|
+
*/
|
|
321
|
+
function formatIgnoredByConfig(changes) {
|
|
322
|
+
if (changes.length === 0)
|
|
323
|
+
return [];
|
|
324
|
+
const names = changes.map((change) => change.key).join(', ');
|
|
325
|
+
return [` ignored (options.envCleanIgnoreHomeEntries): ${names}`];
|
|
326
|
+
}
|
|
299
327
|
/**
|
|
300
328
|
* The header's account of what could be excused, so a report judged against a
|
|
301
329
|
* baseline written before #2472 says why the task's own session was not.
|
|
@@ -322,12 +350,14 @@ function formatEnvCleanReport(diff) {
|
|
|
322
350
|
: '';
|
|
323
351
|
lines.push(` ${probe.probeId} clean (${label})${excused}`);
|
|
324
352
|
lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
|
|
353
|
+
lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
|
|
325
354
|
continue;
|
|
326
355
|
}
|
|
327
356
|
lines.push(` ${probe.probeId} VIOLATED (${label}): +${probe.added.length} -${probe.removed.length}`);
|
|
328
357
|
lines.push(...formatChanges('+', probe.added));
|
|
329
358
|
lines.push(...formatChanges('-', probe.removed));
|
|
330
359
|
lines.push(...formatTaskSessionChanges(probe.taskSessionAdded));
|
|
360
|
+
lines.push(...formatIgnoredByConfig(probe.ignoredByConfig));
|
|
331
361
|
for (const excused of probe.ignoredAdded) {
|
|
332
362
|
lines.push(` · ${excused.key} (ignored: belongs to another worktree)`);
|
|
333
363
|
}
|
|
@@ -383,7 +413,9 @@ async function evaluateEnvClean(input) {
|
|
|
383
413
|
return done('error', `${verify_config_1.ENV_CLEAN_GATE_ID}: UNKNOWN — the current snapshot could not be taken: ` +
|
|
384
414
|
`${error instanceof Error ? error.message : String(error)}`, null);
|
|
385
415
|
}
|
|
386
|
-
const diff = diffEnvSnapshots(input.baseline, final, input
|
|
416
|
+
const diff = diffEnvSnapshots(input.baseline, final, input, {
|
|
417
|
+
ignoreHomeEntries: input.ignoreHomeEntries,
|
|
418
|
+
});
|
|
387
419
|
const header = `${verify_config_1.ENV_CLEAN_GATE_ID}: baseline=${new Date(input.baseline.capturedAt).toISOString()} ` +
|
|
388
420
|
`status=${diff.status} task-session=${describeTaskSession(diff.taskSession)}`;
|
|
389
421
|
const report = `${header}\n${formatEnvCleanReport(diff)}`;
|
|
@@ -1154,6 +1154,7 @@ cancellation) {
|
|
|
1154
1154
|
taskId: envClean.taskId,
|
|
1155
1155
|
baseline: envClean.baseline,
|
|
1156
1156
|
sources: envClean.decision.sources,
|
|
1157
|
+
ignoreHomeEntries: config.options.envCleanIgnoreHomeEntries,
|
|
1157
1158
|
}));
|
|
1158
1159
|
statuses.push(outcome.status);
|
|
1159
1160
|
if (cancellation.cancelled) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Server-only: reads from disk, so import this from API routes / CLI only.
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.VerifyConfigError = exports.MAX_RETRY_ON_FAIL = exports.MAX_GATE_MUTEX_LENGTH = exports.GATE_MUTEX_PATTERN = exports.GATE_ID_PATTERN = exports.DEFAULT_MAX_LOG_TAIL_BYTES = exports.DEFAULT_TIMEOUT_SEC = exports.VERIFY_CONFIG_RELATIVE_PATH = exports.RESERVED_GATE_IDS = exports.ENV_CLEAN_GATE_ID = exports.SCOPE_GATE_ID = exports.WORK_EVIDENCE_GATE_ID = void 0;
|
|
11
|
+
exports.VerifyConfigError = exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES = exports.MAX_RETRY_ON_FAIL = exports.MAX_GATE_MUTEX_LENGTH = exports.GATE_MUTEX_PATTERN = exports.GATE_ID_PATTERN = exports.DEFAULT_MAX_LOG_TAIL_BYTES = exports.DEFAULT_TIMEOUT_SEC = exports.VERIFY_CONFIG_RELATIVE_PATH = exports.RESERVED_GATE_IDS = exports.ENV_CLEAN_GATE_ID = exports.SCOPE_GATE_ID = exports.WORK_EVIDENCE_GATE_ID = void 0;
|
|
12
12
|
exports.defaultPlannedGateIds = defaultPlannedGateIds;
|
|
13
13
|
exports.validateGateEntries = validateGateEntries;
|
|
14
14
|
exports.loadVerifyConfig = loadVerifyConfig;
|
|
@@ -110,6 +110,11 @@ exports.MAX_GATE_MUTEX_LENGTH = 64;
|
|
|
110
110
|
* reports the machine's luck, not the work.
|
|
111
111
|
*/
|
|
112
112
|
exports.MAX_RETRY_ON_FAIL = 1;
|
|
113
|
+
/**
|
|
114
|
+
* Most names `options.envCleanIgnoreHomeEntries` may list (Issue #2890). A list
|
|
115
|
+
* this long is already a repository papering over a machine it should fix.
|
|
116
|
+
*/
|
|
117
|
+
exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES = 32;
|
|
113
118
|
const TOP_LEVEL_KEYS = ['version', 'gates', 'options'];
|
|
114
119
|
const GATE_KEYS = ['id', 'command', 'timeoutSec', 'mutex', 'retryOnFail', 'flakyIsPass'];
|
|
115
120
|
const OPTION_KEYS = [
|
|
@@ -118,6 +123,7 @@ const OPTION_KEYS = [
|
|
|
118
123
|
'maxLogTailBytes',
|
|
119
124
|
'requireCommit',
|
|
120
125
|
'requireEnvClean',
|
|
126
|
+
'envCleanIgnoreHomeEntries',
|
|
121
127
|
];
|
|
122
128
|
class VerifyConfigError extends Error {
|
|
123
129
|
issues;
|
|
@@ -316,6 +322,47 @@ function validateGates(value, issues) {
|
|
|
316
322
|
}
|
|
317
323
|
return validateGateEntries(value, 'gates', issues);
|
|
318
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Validate `options.envCleanIgnoreHomeEntries` (Issue #2890).
|
|
327
|
+
*
|
|
328
|
+
* Each item must be usable as one exact `$HOME` directory-entry name: a string,
|
|
329
|
+
* non-empty, not `.` / `..`, and free of `/` and NUL. Anything with a separator
|
|
330
|
+
* could never equal a `readdir` result, so accepting it would be a rule that
|
|
331
|
+
* silently matches nothing.
|
|
332
|
+
*
|
|
333
|
+
* @returns the names, or null when the value was invalid (issues were pushed)
|
|
334
|
+
*/
|
|
335
|
+
function validateHomeEntryNames(value, issues) {
|
|
336
|
+
const label = 'options.envCleanIgnoreHomeEntries';
|
|
337
|
+
if (!Array.isArray(value)) {
|
|
338
|
+
issues.push(`${label}: must be a list of $HOME entry names (got ${describe(value)})`);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
const before = issues.length;
|
|
342
|
+
if (value.length > exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES) {
|
|
343
|
+
issues.push(`${label}: at most ${exports.MAX_ENV_CLEAN_IGNORE_HOME_ENTRIES} entries (got ${value.length})`);
|
|
344
|
+
}
|
|
345
|
+
const names = [];
|
|
346
|
+
value.forEach((item, index) => {
|
|
347
|
+
const at = `${label}[${index}]`;
|
|
348
|
+
if (typeof item !== 'string') {
|
|
349
|
+
issues.push(`${at}: must be a string (got ${describe(item)})`);
|
|
350
|
+
}
|
|
351
|
+
else if (item === '') {
|
|
352
|
+
issues.push(`${at}: must not be empty`);
|
|
353
|
+
}
|
|
354
|
+
else if (item === '.' || item === '..') {
|
|
355
|
+
issues.push(`${at}: must be an entry name, not ${JSON.stringify(item)}`);
|
|
356
|
+
}
|
|
357
|
+
else if (item.includes('/') || item.includes('\0')) {
|
|
358
|
+
issues.push(`${at}: must be a single $HOME entry name without "/" or NUL (got ${describe(item)})`);
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
names.push(item);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
return issues.length === before ? names : null;
|
|
365
|
+
}
|
|
319
366
|
function validateOptions(value, issues) {
|
|
320
367
|
const options = {
|
|
321
368
|
baseRef: null,
|
|
@@ -323,6 +370,7 @@ function validateOptions(value, issues) {
|
|
|
323
370
|
maxLogTailBytes: exports.DEFAULT_MAX_LOG_TAIL_BYTES,
|
|
324
371
|
requireCommit: false,
|
|
325
372
|
requireEnvClean: false,
|
|
373
|
+
envCleanIgnoreHomeEntries: [],
|
|
326
374
|
};
|
|
327
375
|
// A childless `options:` key parses as null and means "all defaults".
|
|
328
376
|
if (value === undefined || value === null)
|
|
@@ -367,6 +415,11 @@ function validateOptions(value, issues) {
|
|
|
367
415
|
options.requireEnvClean = parsed;
|
|
368
416
|
}
|
|
369
417
|
}
|
|
418
|
+
if (value.envCleanIgnoreHomeEntries !== undefined) {
|
|
419
|
+
const names = validateHomeEntryNames(value.envCleanIgnoreHomeEntries, issues);
|
|
420
|
+
if (names)
|
|
421
|
+
options.envCleanIgnoreHomeEntries = names;
|
|
422
|
+
}
|
|
370
423
|
if (value.maxLogTailBytes !== undefined) {
|
|
371
424
|
const parsed = asInteger(value.maxLogTailBytes);
|
|
372
425
|
if (parsed === null) {
|
|
@@ -31,6 +31,7 @@ const db_instance_1 = require("./db/db-instance");
|
|
|
31
31
|
const db_1 = require("./db");
|
|
32
32
|
const tmux_control_mode_metrics_1 = require("./tmux/tmux-control-mode-metrics");
|
|
33
33
|
const control_mode_tmux_transport_1 = require("./tmux/control-mode-tmux-transport");
|
|
34
|
+
const session_ownership_1 = require("./cli-tools/session-ownership");
|
|
34
35
|
const tmux_control_mode_flags_1 = require("./tmux/tmux-control-mode-flags");
|
|
35
36
|
const cache_1 = require("./external-apps/cache");
|
|
36
37
|
const version_checker_1 = require("../lib/version-checker");
|
|
@@ -782,6 +783,16 @@ async function handleTerminalSubscribe(ws, message) {
|
|
|
782
783
|
clientInfo.terminalSubscription = null;
|
|
783
784
|
}
|
|
784
785
|
const sessionName = (0, session_name_1.resolveSessionName)(cliToolId, worktreeId);
|
|
786
|
+
// Issue #2865: never stream a same-named session another CommandMate server
|
|
787
|
+
// created (its `#{session_path}` is not this worktree's directory).
|
|
788
|
+
const ownership = await (0, session_ownership_1.checkSessionOwnership)(sessionName, worktree.path);
|
|
789
|
+
if (ownership.verdict === 'foreign') {
|
|
790
|
+
sendTerminalEvent(ws, {
|
|
791
|
+
type: 'terminal_error',
|
|
792
|
+
error: 'Session belongs to another CommandMate server',
|
|
793
|
+
});
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
785
796
|
const transport = (0, control_mode_tmux_transport_1.getControlModeTmuxTransport)();
|
|
786
797
|
if (transport.getSubscriberCount(sessionName) >= MAX_TERMINAL_SUBSCRIBERS_PER_SESSION) {
|
|
787
798
|
sendTerminalEvent(ws, {
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.41.1",
|
|
3
|
+
"date": "2026-09-26",
|
|
4
|
+
"highlight": {
|
|
5
|
+
"ja": "HTML ファイルのプレビューで、同じフォルダなどにある画像が表示されるようになりました。",
|
|
6
|
+
"en": "HTML file previews now show images stored alongside the file, such as in the same folder."
|
|
7
|
+
},
|
|
8
|
+
"added": [],
|
|
9
|
+
"improved": [],
|
|
10
|
+
"fixed": [
|
|
11
|
+
{
|
|
12
|
+
"ja": "HTML ファイルのプレビューで、相対パスで指定した画像が表示されない問題を直しました。",
|
|
13
|
+
"en": "Fixed images referenced by a relative path not appearing in HTML file previews."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.42.0",
|
|
3
|
+
"date": "2026-09-27",
|
|
4
|
+
"highlight": {
|
|
5
|
+
"ja": "同じマシンで複数の CommandMate を動かしても、別のサーバのエージェントの画面が見えたり操作できたりしないようになりました。codex 0.157 の新しい画面にも対応しました。",
|
|
6
|
+
"en": "Running several CommandMate servers on one machine no longer lets one server see or drive another server's agents. The new screens in codex 0.157 are also supported."
|
|
7
|
+
},
|
|
8
|
+
"added": [
|
|
9
|
+
{
|
|
10
|
+
"ja": "選択画面で送信が続けて効かないとき、直接入力モードに切り替えるリンクが表示されるようになりました。",
|
|
11
|
+
"en": "When sending on a selection screen keeps having no effect, a link to switch to direct input mode is now shown."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"ja": "検証の環境チェックで、作業と無関係なホームディレクトリの項目を名前で除外できるようになりました。",
|
|
15
|
+
"en": "The environment check in verification can now ignore unrelated items in your home directory by name."
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"improved": [
|
|
19
|
+
{
|
|
20
|
+
"ja": "エージェントのセッション名にサーバごとの名前が付くようになり、別のサーバと同じ名前のプロジェクトでもセッションを起動できるようになりました。",
|
|
21
|
+
"en": "Agent session names now include a per-server name, so sessions can start even when another server has a project with the same name."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"ja": "CLI の attach・ls・whoami・instances が新しいセッション名に対応しました。",
|
|
25
|
+
"en": "The CLI attach, ls, whoami, and instances commands now work with the new session names."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"fixed": [
|
|
29
|
+
{
|
|
30
|
+
"ja": "別のサーバが起動した同じ名前のセッションが表示され、送信や停止ができてしまう問題を直しました。",
|
|
31
|
+
"en": "Fixed sessions started by another server with the same name being shown and accepting messages or stop requests."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"ja": "codex 0.157 のモデル選択画面を選択画面として扱えず、送信しても反応しなかった問題を直しました。",
|
|
35
|
+
"en": "Fixed the codex 0.157 model picker not being recognized, so sending a choice did nothing."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"ja": "codex 0.157 のフォルダーの信頼確認画面を認識できなかった問題を直しました。",
|
|
39
|
+
"en": "Fixed the codex 0.157 folder trust screen not being recognized."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"ja": "CommandMate から答えられない画面に送信ボタンが出ていた問題を直しました。代わりに直接入力への案内が出ます。",
|
|
43
|
+
"en": "Fixed the Send button appearing on screens CommandMate cannot answer. A pointer to direct input is shown instead."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"ja": "「操作できません」の案内が表示されるまで最大で十数秒かかることがあった問題を直しました。",
|
|
47
|
+
"en": "Fixed the cannot-operate notice sometimes taking up to about fifteen seconds to appear."
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"ja": "スマホでチャット表示のリンクから開いたとき、直接入力に切り替えるとチャット表示に戻ってしまう問題を直しました。",
|
|
51
|
+
"en": "Fixed switching to direct input on a phone going back to the chat view when the page was opened from a chat view link."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"ja": "codex を複数起動すると、別の codex の返答が最初に起動した codex の会話に入ってしまう問題を直しました。",
|
|
55
|
+
"en": "Fixed replies from one codex instance being saved into the conversation of the first codex that was started."
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"ja": "承認への応答の後に、別のサーバのセッションの画面が会話履歴に取り込まれることがある問題を直しました。",
|
|
59
|
+
"en": "Fixed another server's session screen sometimes being saved into the conversation history after answering an approval."
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=3323,exports.ids=[3323],exports.modules={31517:(a,b,c)=>{c.d(b,{DL:()=>j,sD:()=>f});var d=c(2734);let e=(0,c(72626).h)("lib/hooks/stop-history-capture"),f=[150,500,2e3,5e3],g=new Set([d.c]);function h(a){return new Promise(b=>{setTimeout(b,a)})}async function i(a,b,c,d,f,g){let i=Date.now();try{for(let[j,k]of g.entries()){await h(k);let l={};if(await a.captureStructuredHistoryTurn(b.id,c,d,f,l))return e.info("stop-history-capture-deferred-captured",{worktreeId:b.id,cliToolId:c,instanceId:d,attempt:j+1,attempts:g.length,elapsedMs:Date.now()-i}),!0;e.debug("stop-history-capture-deferred-open",{worktreeId:b.id,cliToolId:c,instanceId:d,attempt:j+1,attempts:g.length,outcome:l.outcome??"unavailable",elapsedMs:Date.now()-i})}return e.info("stop-history-capture-deferred-exhausted",{worktreeId:b.id,cliToolId:c,instanceId:d,attempts:g.length,elapsedMs:Date.now()-i}),!1}catch(a){return e.warn("stop-history-capture-deferred-failed",{worktreeId:b.id,cliToolId:c,instanceId:d,error:a instanceof Error?a.message:String(a)}),!1}}async function j(a,b,d,k={}){try{let j=await Promise.all([c.e(1503),c.e(1719),c.e(9080),c.e(2119),c.e(2445),c.e(252),c.e(8800),c.e(8728),c.e(7905),c.e(9731),c.e(8918)]).then(c.bind(c,28918));if(!j.isPullTranscriptHistory(b))return{status:"unavailable"};let l={worktreePath:a.path,transcriptPathHint:null},m={};if(await j.captureStructuredHistoryTurn(a.id,b,d,l,m))return{status:"captured"};let n=()=>"not_yet_closed"===m.outcome?Promise.resolve(!0):j.hasStructuredHistoryTranscript(a.id,b,d,l);if(g.has(b)){let c=k.deferredDelaysMs??f;if(0===c.length||!await n())return{status:"unavailable"};let g=i(j,a,b,d,l,c);return e.info("stop-history-capture-deferred",{worktreeId:a.id,cliToolId:b,instanceId:d,delaysMs:c}),{status:"deferred",deferred:g}}let o=k.retryDelayMs??500;if(o<=0||!await n())return{status:"unavailable"};let p=Math.max(1,k.maxAttempts??3);for(let c=2;c<=p;c+=1){await h(o);let f={},g=await j.captureStructuredHistoryTurn(a.id,b,d,l,f);if(e.debug("stop-history-capture-retried",{worktreeId:a.id,cliToolId:b,instanceId:d,attempt:c,maxAttempts:p,captured:g,outcome:f.outcome??"unavailable"}),g)return{status:"captured"}}return{status:"unavailable"}}catch(c){return e.warn("stop-history-capture-failed",{worktreeId:a.id,cliToolId:b,instanceId:d,error:c instanceof Error?c.message:String(c)}),{status:"unavailable"}}}},52767:(a,b,c)=>{c.d(b,{r:()=>i,g:()=>h});var d=c(48524),e=c(87009),f=c(72626);let g=(0,f.h)("lib/tasks/task-transition-service");function h(a,b,c,f){let h=a.transaction(()=>{let g=(0,d.gg)(a,b);if(!g)return null;let h=g.status,i=function(a,b){switch(a){case"pending":switch(b){case"message_sent":return"running";case"send_failed":case"cancel":return"cancelled";default:return null}case"running":switch(b){case"prompt_detected":return"waiting_input";case"agent_idle":return"running";case"verify_started":return"verifying";case"send_failed":return"failed";case"cancel":return"cancelled";default:return null}case"waiting_input":switch(b){case"prompt_answered_auto":case"prompt_answered_human":case"agent_idle":return"running";case"verify_started":return"verifying";case"cancel":return"cancelled";default:return null}case"verifying":switch(b){case"verify_passed":return"succeeded";case"verify_failed":return"failed";case"verify_not_started":return"not_started";case"cancel":return"cancelled";default:return null}case"failed":case"not_started":switch(b){case"message_sent":return"running";case"verify_started":return"verifying";case"cancel":return"cancelled";default:return null}default:return null}}(h,c),j=Date.now(),k=(0,e.P)(a,{taskId:b,event:c,fromStatus:h,toStatus:i,payload:f,createdAt:j});return null===i?{task:g,fromStatus:h,toStatus:null,eventId:k}:{task:(0,d.xZ)(a,b,i,f?.runId===void 0?{}:{lastVerificationRunId:f.runId}),fromStatus:h,toStatus:i,eventId:k}})();return null===h?g.warn("task-event-unknown-task",{taskId:b,event:c}):null===h.toStatus&&g.warn("task-event-rejected",{taskId:b,event:c,fromStatus:h.fromStatus}),h}function i(a,b,c,e,f,i){try{let g=(0,d.MH)(a,b,c,e);if(!g)return null;return h(a,g.id,f,i)}catch(a){return g.warn("task-event-failed",{worktreeId:b,cliToolId:c,instanceId:e,event:f,error:a instanceof Error?a.message:String(a)}),null}}}};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=7075,exports.ids=[964,2839,5220,7075,8583],exports.modules={23197:(a,b,c)=>{c.d(b,{H1:()=>d});let d="__global__"},39687:(a,b,c)=>{c.d(b,{d:()=>q});var d=c(56791),e=c(43234),f=c(15194),g=c(95220),h=c(12462),i=c(43015),j=c(54325),k=c(72626),l=c(58707),m=c(41466);let n=(0,k.h)("session/send-user-message");function o(a){return a instanceof Error?a.message:String(a)}async function p(a,b){let c=`${a}:${b}`,d=Date.now()+5e3;for(;(0,g.getActivePollers)().includes(c);){if(Date.now()>=d)return!1;await new Promise(a=>setTimeout(a,100))}return!0}async function q(a,b){let{worktreeId:c,content:k,cliToolId:q,instanceId:r,absoluteImagePath:s,copilotModel:t}=b,u=b.messageType??"normal",v=r??q,w=e.CLIToolManager.getInstance().getTool(q),x=await (0,l.a3)(c,q,r,{ignoreStructured:b.ignoreStructuredPromptGuard});if(x.waiting)return n.info("send-refused-prompt-waiting",{worktreeId:c,cliToolId:q,reason:x.reason,blockedBy:x.blockedBy}),{ok:!1,stage:"prompt_waiting",error:(0,l.br)(c,x.blockedBy)};if(t&&"copilot"===q){try{await w.sendModelCommand(c,t,r),n.info("copilot-model-command-sent",{model:t})}catch(a){return n.error("failed-to-send-model-command:",{error:o(a)}),{ok:!1,stage:"model",error:o(a)}}await p(c,v)||n.warn("previous-turn-poller-still-running",{worktreeId:c,instanceId:v,waitedMs:5e3})}let y=new Date;try{await (0,h.o4)(a,c,q,y,r)}catch(a){n.error("failed-to-save-pending-assistant-response:",{error:o(a)})}let z=null;try{let b=(0,d.getMessages)(a,c,{limit:1,cliToolId:q,instanceId:v,matchResolvedInstance:!0});b.length>0&&"user"===b[0].role&&b[0].content===k&&(z=b[0].id)}catch(a){n.error("failed-to-detect-orphaned-messages:",{error:o(a)})}try{s?(0,f._J)(w)?await w.sendMessageWithImage(c,k,s,r):await w.sendMessage(c,(0,m.TZ)(k,s),r):await w.sendMessage(c,k,r)}catch(a){return n.error("failed-to-send-message-to:",{error:o(a)}),{ok:!1,stage:"send",error:o(a)}}let A=(0,d.createMessage)(a,{worktreeId:c,role:"user",content:k,messageType:u,timestamp:y,cliToolId:q,instanceId:r,requestId:b.requestId});try{(0,i.broadcastMessage)("message",{worktreeId:c,message:{...A,cliToolId:q,instanceId:v}})}catch(a){n.warn("user-message-broadcast-failed",{error:o(a)})}if(z)try{if((0,d.deleteMessageById)(a,z)){n.info("cleaned-up-orphaned-user");try{(0,i.broadcastMessage)(j.dz,{worktreeId:c,cliToolId:q,instanceId:v,reason:"orphan_cleanup"})}catch(a){n.warn("orphan-cleanup-broadcast-failed",{error:o(a)})}}}catch(a){n.error("failed-to-clean-up-orphaned-message:",{error:o(a)})}return(0,d.updateLastUserMessage)(a,c,k,y),(0,d.clearInProgressMessageId)(a,c,q,r),n.info("cleared-in-progress-message-for"),(0,g.startPolling)(c,q,r),{ok:!0,message:A}}},40964:(a,b,c)=>{c.d(b,{m:()=>g});var d=c(15194);let e=/^[a-zA-Z0-9_-]+$/;function f(a){if(!e.test(a))throw Error(`Invalid session name format: ${a}`)}function g(a,b,c){let e=`mcbd-${a}-${b}`;if(!c||c===a)return f(e),e;let g=(0,d.pL)(c,a),h=g?`${e}-${g}`:e;return f(h),h}},58707:(a,b,c)=>{c.d(b,{$n:()=>k,a3:()=>l,br:()=>m});var d=c(43234),e=c(31990),f=c(95595),g=c(34405),h=c(72626),i=c(30008);let j=(0,h.h)("prompt-waiting-guard"),k="PROMPT_WAITING";async function l(a,b,c,h){try{let k=d.CLIToolManager.getInstance().getTool(b);if(!await k.isRunning(a,c))return{waiting:!1};let l=await (0,e.Wh)(a,b,g._,c),m=(0,f.WC)(l,b),n=(0,i._G)({worktreeId:a,cliToolId:b,instanceId:c,scraper:{status:m.status,reason:m.reason,hasActivePrompt:m.hasActivePrompt},ignoreStructured:h?.ignoreStructured});if(!n.blocksSend)return null!==n.structuredSendBlockSuppressed&&j.info("structured-send-guard-not-applied",{worktreeId:a,cliToolId:b,instanceId:c,suppressed:n.structuredSendBlockSuppressed,promptWaitingSince:n.structured?.at??null}),{waiting:!1};return{waiting:!0,reason:n.blockReason??void 0,blockedBy:n.blockedBy??void 0}}catch(c){return j.warn("prompt-waiting-check-failed",{worktreeId:a,cliToolId:b,error:c instanceof Error?c.message:String(c)}),{waiting:!1}}}function m(a,b){let c=`${a} is waiting on a prompt. Sending now would type into the prompt's input line instead of reaching the agent, and would leave that text in place for the next answer. Answer the prompt first: \`commandmate respond ${a} <answer>\`.`;if("structured"!==b)return c;let d=Math.round(i.j0/6e4);return`${c} This dialog was reported by the agent's own hooks and is not visible to the terminal scraper, so if the pane looks idle the record has outlived its dialog: it stops blocking sends ${d} minutes after it was reported, or immediately with \`commandmate send ${a} <message> --ignore-structured-prompt\` (server-wide: ${i.F1}=off).`}},61068:(a,b,c)=>{c.d(b,{Nz:()=>u,EB:()=>v,l7:()=>x});var d=c(95220),e=c(5363),f=c(56793),g=c(85775),h=c(72626),i=c(43234),j=c(79892);let k=(0,h.h)("global-session-poller"),l=new Map,m=new Map;var n=c(93997),o=c(15194),p=c(23197),q=c(77093),r=c(82325);let s=(0,h.h)("session-cleanup");async function t(a,b){let c={worktreeId:a,sessionsKilled:[],sessionErrors:[],pollersStopped:[],pollerErrors:[]};for(let e of((0,n.pc)(),o.XH)){try{await b(a,e)&&(c.sessionsKilled.push(e),s.info("session:killed",{worktreeId:a,cliToolId:e}))}catch(d){let b=`${e}: ${(0,q.u1)(d)}`;c.sessionErrors.push(b),s.warn("session:kill-failed",{worktreeId:a,cliToolId:e,error:d instanceof Error?d.message:String(d)})}try{(0,d.stopPolling)(a,e),c.pollersStopped.push(`response-poller:${e}`)}catch(d){let b=`response-poller:${e}: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("response-poller:stop-failed",{worktreeId:a,cliToolId:e,error:d instanceof Error?d.message:String(d)})}}try{(0,e._C)(a),c.pollersStopped.push("auto-yes-poller")}catch(d){let b=`auto-yes-poller: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("auto-yes-poller:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,e.LP)(a),c.pollersStopped.push("auto-yes-state")}catch(d){let b=`auto-yes-state: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("auto-yes-state:delete-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,f.Yg)(a),c.pollersStopped.push("schedule-manager")}catch(d){let b=`schedule-manager: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("schedule-manager:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}try{(0,g.Tm)(a),c.pollersStopped.push("timer-manager")}catch(d){let b=`timer-manager: ${(0,q.u1)(d)}`;c.pollerErrors.push(b),s.warn("timer-manager:stop-failed",{worktreeId:a,error:d instanceof Error?d.message:String(d)})}return c}async function u(a,b){let c=await Promise.allSettled(a.map(a=>t(a,b))),d=[],e=[];for(let b=0;b<c.length;b++){let f=c[b],g=a[b];if("fulfilled"===f.status){let a=f.value;for(let b of(d.push(a),a.sessionErrors))e.push(`Session kill error (${g}): ${b}`);for(let b of a.pollerErrors)e.push(`Poller stop error (${g}): ${b}`)}else e.push(`Cleanup failed (${g}): ${(0,q.u1)(f.reason)}`)}return{results:d,warnings:e}}async function v(a,b){try{let c=i.CLIToolManager.getInstance().getTool(b);if(!await c.isRunning(a))return!1;let e=`${a}:${b}`;(0,d.clearPromptHashCache)(e);let f=c.getSessionName(a);return(0,j.fY)(f)}catch{return!1}}async function w(){for(let a of l.keys()){let b=l.get(a);b&&clearTimeout(b)}l.clear(),m.clear(),k.info("poll:all-stopped");let a=0,b=i.CLIToolManager.getInstance();for(let c of o.XH)try{let d=b.getTool(c).getSessionName(p.H1);await (0,j.N)(d)&&await (0,j.fY)(d)&&(a++,s.info("global-session:killed",{cliToolId:c,sessionName:d}))}catch(a){s.warn("global-session:kill-failed",{cliToolId:c,error:(0,q.u1)(a)})}return a}async function x(a,b){let c=(0,r.L0)(a,b);try{await w()}catch(a){s.warn("sync:global-cleanup-failed",{error:(0,q.u1)(a)})}let d=[];if(c.deletedIds.length>0)try{let a=await u(c.deletedIds,v);a.warnings.length>0&&(s.warn("sync:cleanup-warnings",{warnings:a.warnings}),d=[`${a.warnings.length} session cleanup warning(s) occurred`])}catch(a){s.error("sync:cleanup-failed",{error:(0,q.u1)(a)}),d=["Session cleanup encountered an error"]}return{syncResult:c,cleanupWarnings:d}}},82325:(a,b,c)=>{c.d(b,{Hz:()=>o,L0:()=>r,Mg:()=>s,YM:()=>p,Yp:()=>q});var d=c(79646),e=c(28354),f=c(29021),g=c.n(f),h=c(33873),i=c.n(h),j=c(23718),k=c(56791),l=c(72626),m=c(64185);let n=(0,l.h)("worktrees");function o(){let a=process.env.WORKTREE_REPOS;return a&&a.trim()?a.split(",").map(a=>a.trim()).filter(a=>a.length>0):[]}async function p(a){let b=(0,e.promisify)(d.exec);if(function(a){if(!a)return!1;try{return g().lstatSync(a),!1}catch(b){let a=b.code;return"ENOENT"===a||"ENOTDIR"===a}}(a))return n.warn("repository:scan-skipped-missing-dir",{repoPath:a}),[];try{let{stdout:c}=await b("git worktree list",{cwd:a}),d=function(a){if(!a||""===a.trim())return[];let b=a.trim().split("\n"),c=[];for(let a of b){let b=a.trim();if(!b)continue;let d=b.match(/^(.+?)\s+([a-z0-9]+)\s+(?:\[(.+?)\]|\(detached HEAD\))/);if(d){let[,a,b,e]=d;c.push({path:a.trim(),branch:e||`detached-${b}`,commit:b})}}return c}(c),e=i().resolve(a),f=i().basename(e);return(0,m.oZ)(e),d.map(a=>{let b=i().resolve(a.path);return{id:(0,j.ko)(b),name:a.branch,branch:a.branch,path:b,repositoryPath:e,repositoryName:f}}).filter(a=>["/etc","/root","/sys","/proc","/dev","/boot","/bin","/sbin","/usr/bin","/usr/sbin"].some(b=>a.path.startsWith(b))?(n.warn("worktree:unsafe-path-skipped",{path:a.path}),!1):!(a.path.includes("\0")||a.path.includes(".."))||(n.warn("worktree:malicious-path-skipped",{path:a.path}),!1))}catch(c){let a=c instanceof Error?c.message:String(c),b=c.code;if(a?.includes("not a git repository")||128===b)return[];throw c}}async function q(a){let b=await Promise.allSettled(a.map(async a=>{n.info("repository:scan-start",{repoPath:a});let b=await p(a);return n.info("repository:scan-complete",{repoPath:a,worktreeCount:b.length}),b})),c=[];for(let d=0;d<b.length;d++){let e=b[d];"fulfilled"===e.status?c.push(...e.value):n.error("repository:scan-failed",{repoPath:a[d],error:e.reason instanceof Error?e.reason.message:String(e.reason)})}return c}function r(a,b){if(0===b.length)return{deletedIds:[],upsertedCount:0};let c=[],d=0,e=new Map;for(let a of b){let b=a.repositoryPath||"";e.has(b)||e.set(b,[]),e.get(b).push(a)}let f=new Set([...(0,k.getAllWorktreeIds)(a),...(0,k.getAliasedWorktreeIds)(a)]),g=new Map((0,k.getAllWorktreePathIds)(a).map(a=>[i().resolve(a.path),a.id])),h=new Map,l=new Map;for(let[a,b]of g)h.set(a,new Set([b])),l.set(b,a);for(let b of(0,k.getAllWorktreeAliases)(a)){let a=l.get(b.worktreeId);a&&h.get(a)?.add(b.oldId)}let m=new Set(b.map(a=>i().resolve(a.path)));for(let[b,o]of e){if(!b)continue;let e=(0,k.getWorktreesByRepository)(a,b).filter(a=>!m.has(i().resolve(a.path))).map(a=>a.id);if(e.length>0){let b=(0,k.deleteWorktreesByIds)(a,e);for(let a of(c.push(...e),e)){f.delete(a);let b=l.get(a);void 0!==b&&(g.delete(b),h.delete(b))}n.info("worktree:cleanup",{deletedCount:b.deletedCount})}for(let b of o){let c=i().resolve(b.path),e=g.get(c),m=b.id,n=e??(m&&!f.has(m)?m:function(a,b,c){if(!c||0===c.size)return(0,j.ko)(a,b);let d=new Set(b);for(let a of c)d.delete(a);return(0,j.ko)(a,d)}(c,f,h.get(c)));f.add(n),g.set(c,n),l.set(n,c),(0,k.upsertWorktree)(a,{...b,id:n,name:b.branch??b.name}),d++}}return{deletedIds:c,upsertedCount:d}}function s(a,b){let c=new Set(b.map(a=>a.repositoryPath).filter(a=>!!a)),d=[];for(let b of(0,k.getRepositories)(a)){let e=b.path;if(!e||c.has(e)||function(a){if(!a)return!1;try{return g().existsSync(a)&&g().existsSync(i().join(a,".git"))}catch{return!0}}(e))continue;let f=(0,k.getWorktreesByRepository)(a,e).map(a=>a.id);if(0===f.length)continue;let h=(0,k.deleteWorktreesByIds)(a,f);d.push(...f),n.info("worktree:stale-repo-pruned",{repoPath:e,deletedCount:h.deletedCount})}return d}},85775:(a,b,c)=>{c.d(b,{Tm:()=>o,x4:()=>m,xJ:()=>n});var d=c(34129),e=c(43234),f=c(88807),g=c(72626),h=c(87374),i=c(39687);let j=(0,g.h)("timer-manager");function k(){return globalThis.__timerManagerState||(globalThis.__timerManagerState={timers:new Map,timerWorktrees:new Map,initialized:!1}),globalThis.__timerManagerState}async function l(a){let b=k(),c=(0,f.getDbInstance)();try{let b=(0,d.kx)(c,a);if(!b||"pending"!==b.status)return;let f=e.CLIToolManager.getInstance().getTool(b.cliToolId),g=b.instanceId;if(!await f.isRunning(b.worktreeId,g)){j.warn("timer:no-session",{timerId:a,worktreeId:b.worktreeId,instanceId:g}),(0,d.j2)(c,a,h.HR.NO_SESSION);return}(0,d.j2)(c,a,"sending");let k=await (0,i.d)(c,{worktreeId:b.worktreeId,content:b.message,cliToolId:b.cliToolId,instanceId:g});if(!k.ok){let b=`[${k.stage}] ${k.error}`;(0,d.j2)(c,a,"failed",void 0,b),j.error("timer:send-failed",{timerId:a,stage:k.stage,error:k.error});return}(0,d.j2)(c,a,"sent",Date.now()),j.info("timer:sent",{timerId:a,worktreeId:b.worktreeId})}catch(e){let b=e instanceof Error?e.message:String(e);try{(0,d.j2)(c,a,"failed",void 0,b)}catch{}j.error("timer:send-failed",{timerId:a,error:b})}finally{b.timers.delete(a),b.timerWorktrees.delete(a)}}function m(a,b,c){let d=k(),e=setTimeout(()=>{l(a)},c);d.timers.set(a,e),d.timerWorktrees.set(a,b)}function n(a){let b=k(),c=b.timers.get(a);c&&(clearTimeout(c),b.timers.delete(a),b.timerWorktrees.delete(a));let e=(0,f.getDbInstance)();(0,d.Ud)(e,a)}function o(a){let b=k(),c=(0,f.getDbInstance)();for(let[c,d]of b.timerWorktrees)if(d===a){let a=b.timers.get(c);a&&clearTimeout(a),b.timers.delete(c),b.timerWorktrees.delete(c)}(0,d.$$)(c,a)}},95220:(a,b,c)=>{c.r(b),c.d(b,{accumulateTuiContent:()=>g.IZ,cleanClaudeResponse:()=>f.NN,cleanCopilotResponse:()=>f.LH,cleanGeminiResponse:()=>f.IS,cleanOpenCodeResponse:()=>f.aW,clearPromptHashCache:()=>h.iX,clearTuiAccumulator:()=>g.q1,extractCopilotContentLines:()=>g.o0,extractTuiContentLines:()=>g.K0,findOverlapIndex:()=>g.vQ,getAccumulatedContent:()=>g.Uz,getActivePollers:()=>d.KQ,initTuiAccumulator:()=>g.tb,isDuplicatePrompt:()=>h.gv,isOpenCodeComplete:()=>e.bE,migrateResponsePollerWorktreeIds:()=>d.sR,normalizeCopilotLine:()=>g.IW,normalizePromptForDedup:()=>h.zm,renamePromptHashCacheKey:()=>h.i2,resolveExtractionStartIndex:()=>e.QM,startPolling:()=>d.g8,stopAllPolling:()=>d.fq,stopPolling:()=>d.Et,truncateMessage:()=>f.Sj});var d=c(45146),e=c(60),f=c(82450),g=c(13033),h=c(72457)}};
|