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
|
@@ -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) {
|
|
@@ -1020,7 +1020,10 @@
|
|
|
1020
1020
|
"caption": "Answer"
|
|
1021
1021
|
},
|
|
1022
1022
|
"promptResponse": {
|
|
1023
|
-
"refused": "Your answer was not sent because the dialog has changed. Please check the screen."
|
|
1023
|
+
"refused": "Your answer was not sent because the dialog has changed. Please check the screen.",
|
|
1024
|
+
"stuckHint": "If sending does not work, operate the terminal in direct input mode.",
|
|
1025
|
+
"stuckHintLink": "Switch to direct input",
|
|
1026
|
+
"unanswerable": "CommandMate cannot operate this screen. Use direct input mode instead."
|
|
1024
1027
|
},
|
|
1025
1028
|
"dismissPanelKeys": {
|
|
1026
1029
|
"toolbarLabel": "Close this screen",
|
|
@@ -1020,7 +1020,10 @@
|
|
|
1020
1020
|
"caption": "回答"
|
|
1021
1021
|
},
|
|
1022
1022
|
"promptResponse": {
|
|
1023
|
-
"refused": "ダイアログの状態が変わったため送信できませんでした。画面を確認してください。"
|
|
1023
|
+
"refused": "ダイアログの状態が変わったため送信できませんでした。画面を確認してください。",
|
|
1024
|
+
"stuckHint": "送信がうまくいかない場合は、直接入力モードで操作してください。",
|
|
1025
|
+
"stuckHintLink": "直接入力に切り替える",
|
|
1026
|
+
"unanswerable": "この画面は CommandMate から操作できません。直接入力モードで操作してください。"
|
|
1024
1027
|
},
|
|
1025
1028
|
"dismissPanelKeys": {
|
|
1026
1029
|
"toolbarLabel": "この画面を閉じる",
|
package/dist/server/server.js
CHANGED
|
@@ -409,6 +409,19 @@ app.prepare().then(() => {
|
|
|
409
409
|
catch (error) {
|
|
410
410
|
console.error('Error reconciling Skill operations:', error);
|
|
411
411
|
}
|
|
412
|
+
// Issue #2866: this server's tmux session-name namespace. Must precede the
|
|
413
|
+
// session reconcile below, which renames onto (and attributes against)
|
|
414
|
+
// names in this namespace. Fail-open in its own try/catch: without a
|
|
415
|
+
// namespace sessions keep the legacy `mcbd-{cli}-{id}` names. Dynamic
|
|
416
|
+
// import for the same reason as the reconcilers around it.
|
|
417
|
+
try {
|
|
418
|
+
const { initSessionNamespace } = await Promise.resolve().then(() => __importStar(require('./src/lib/cli-tools/session-namespace')));
|
|
419
|
+
const namespace = initSessionNamespace(db);
|
|
420
|
+
console.log(`tmux session namespace: ${namespace}`);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
console.error('Error initializing tmux session namespace:', error);
|
|
424
|
+
}
|
|
412
425
|
// Issue #1621 Phase 3/4: make live tmux sessions follow the worktree IDs
|
|
413
426
|
// that migration v54 has just renumbered. Session names are DERIVED from
|
|
414
427
|
// the ID (`mcbd-{cli}-{worktreeId}`), so a running agent would otherwise
|
|
@@ -445,6 +458,22 @@ app.prepare().then(() => {
|
|
|
445
458
|
catch (error) {
|
|
446
459
|
console.error('Error reconciling worktree sessions:', error);
|
|
447
460
|
}
|
|
461
|
+
// Issue #2866: keep serving this server's sessions that predate the
|
|
462
|
+
// namespace under their legacy names (adopted, not renamed). After the
|
|
463
|
+
// reconcile above, so an ID move has already been applied. Fail-open.
|
|
464
|
+
try {
|
|
465
|
+
const { adoptLegacySessions } = await Promise.resolve().then(() => __importStar(require('./src/lib/session/adopt-legacy-sessions')));
|
|
466
|
+
const adoptReport = await adoptLegacySessions(db);
|
|
467
|
+
if (adoptReport.adopted.length > 0) {
|
|
468
|
+
console.log(`Adopted ${adoptReport.adopted.length} legacy-named tmux session(s)`);
|
|
469
|
+
}
|
|
470
|
+
if (adoptReport.errors.length > 0) {
|
|
471
|
+
console.warn(`Legacy session adoption warnings: ${adoptReport.errors.join(', ')}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
console.error('Error adopting legacy tmux sessions:', error);
|
|
476
|
+
}
|
|
448
477
|
// Issue #1543: close verification runs that a crash left in `running`.
|
|
449
478
|
// Gate execution lives in process memory, so none of them survived the
|
|
450
479
|
// restart; leaving the rows open would keep their worktrees permanently
|
|
@@ -69,6 +69,7 @@ const auto_yes_dialog_gate_1 = require("./polling/auto-yes-dialog-gate");
|
|
|
69
69
|
const task_transition_service_1 = require("./tasks/task-transition-service");
|
|
70
70
|
const db_instance_1 = require("./db/db-instance");
|
|
71
71
|
const chat_db_1 = require("./db/chat-db");
|
|
72
|
+
const worktree_session_ownership_1 = require("./cli-tools/worktree-session-ownership");
|
|
72
73
|
const prompt_answer_sender_1 = require("./prompt-answer-sender");
|
|
73
74
|
const manager_1 = require("./cli-tools/manager");
|
|
74
75
|
const cli_patterns_1 = require("./detection/cli-patterns");
|
|
@@ -519,6 +520,20 @@ async function detectAndRespondToPrompt(worktreeId, pollerState, cliToolId, clea
|
|
|
519
520
|
const manager = manager_1.CLIToolManager.getInstance();
|
|
520
521
|
const cliTool = manager.getTool(cliToolId);
|
|
521
522
|
const sessionName = cliTool.getSessionName(worktreeId, instanceId);
|
|
523
|
+
// Issue #2865: never auto-answer a same-named session another CommandMate
|
|
524
|
+
// server created. The poller keeps running; it just does not type.
|
|
525
|
+
const ownership = await (0, worktree_session_ownership_1.checkWorktreeSessionOwnership)(worktreeId, sessionName);
|
|
526
|
+
if (ownership === null || ownership.verdict === 'foreign') {
|
|
527
|
+
logger.warn('poller:auto-yes-skipped-foreign-session', {
|
|
528
|
+
worktreeId,
|
|
529
|
+
cliToolId,
|
|
530
|
+
instanceId,
|
|
531
|
+
sessionName,
|
|
532
|
+
sessionPath: ownership?.sessionPath ?? null,
|
|
533
|
+
reason: ownership ? 'foreign' : 'worktree_not_found',
|
|
534
|
+
});
|
|
535
|
+
return 'no_answer';
|
|
536
|
+
}
|
|
522
537
|
try {
|
|
523
538
|
await (0, prompt_answer_sender_1.sendPromptAnswer)({
|
|
524
539
|
sessionName,
|
|
@@ -200,7 +200,7 @@ class AntigravityTool extends base_1.BaseCLITool {
|
|
|
200
200
|
// Check if session already exists
|
|
201
201
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
202
202
|
if (exists) {
|
|
203
|
-
await this.reconcileExistingSession(sessionName);
|
|
203
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
204
204
|
// Issue #2070: this branch used to return unconditionally. A tmux session
|
|
205
205
|
// outlives the agent that was launched into it — a quit, a self-update, a
|
|
206
206
|
// crash — and the launch was then skipped for a pane holding nothing but a
|
|
@@ -13,6 +13,7 @@ const child_process_1 = require("child_process");
|
|
|
13
13
|
const util_1 = require("util");
|
|
14
14
|
const session_name_1 = require("./session-name");
|
|
15
15
|
const tmux_1 = require("../tmux/tmux");
|
|
16
|
+
const session_ownership_1 = require("../tmux/session-ownership");
|
|
16
17
|
const composer_spec_1 = require("./composer-spec");
|
|
17
18
|
const capture_spec_1 = require("./capture-spec");
|
|
18
19
|
const agent_mode_spec_1 = require("./agent-mode-spec");
|
|
@@ -235,8 +236,16 @@ class BaseCLITool {
|
|
|
235
236
|
/**
|
|
236
237
|
* Repair geometry when reusing a tmux session that predates the current
|
|
237
238
|
* defaults, and record that this launch reused one (Issue #2429).
|
|
239
|
+
*
|
|
240
|
+
* Issue #2865: only a session created in `worktreePath` is reused. A
|
|
241
|
+
* same-named session another CommandMate server created is refused with
|
|
242
|
+
* {@link ForeignSessionError} before anything touches it, and is never
|
|
243
|
+
* recorded as adopted.
|
|
244
|
+
*
|
|
245
|
+
* @throws {ForeignSessionError} When the session's `#{session_path}` is not `worktreePath`
|
|
238
246
|
*/
|
|
239
|
-
async reconcileExistingSession(sessionName, options) {
|
|
247
|
+
async reconcileExistingSession(sessionName, worktreePath, options) {
|
|
248
|
+
await (0, session_ownership_1.assertSessionNotForeign)(sessionName, worktreePath);
|
|
240
249
|
adoptedSessions.add(sessionName);
|
|
241
250
|
await (0, tmux_1.reconcileSessionGeometry)(sessionName, options);
|
|
242
251
|
}
|
|
@@ -204,7 +204,7 @@ class CodexTool extends base_1.BaseCLITool {
|
|
|
204
204
|
// Check if session already exists
|
|
205
205
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
206
206
|
if (exists) {
|
|
207
|
-
await this.reconcileExistingSession(sessionName);
|
|
207
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
208
208
|
// Issue #2070: this branch used to return unconditionally, and that is
|
|
209
209
|
// the second half of the reported bug. codex's own "1. Update now"
|
|
210
210
|
// replaces codex with `npm install` and exits; `Ctrl+C` twice quits it; a
|
|
@@ -191,7 +191,7 @@ class CommandCodeTool extends base_1.BaseCLITool {
|
|
|
191
191
|
const sessionName = this.getSessionName(worktreeId, instanceId);
|
|
192
192
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
193
193
|
if (exists) {
|
|
194
|
-
await this.reconcileExistingSession(sessionName);
|
|
194
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
195
195
|
// Issue #2070's shape: a tmux session outlives the agent that was launched
|
|
196
196
|
// into it, and skipping the launch for a pane holding nothing but a shell
|
|
197
197
|
// prompt leaves `kill-session` by hand as the only recovery.
|
|
@@ -307,7 +307,7 @@ class CopilotTool extends base_1.BaseCLITool {
|
|
|
307
307
|
// Check if session already exists
|
|
308
308
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
309
309
|
if (exists) {
|
|
310
|
-
await this.reconcileExistingSession(sessionName);
|
|
310
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
311
311
|
// Issue #2070: this branch used to return unconditionally. A tmux session
|
|
312
312
|
// outlives the agent that was launched into it — a quit, a self-update, a
|
|
313
313
|
// crash — and the launch was then skipped for a pane holding nothing but a
|
|
@@ -72,7 +72,7 @@ class GeminiTool extends base_1.BaseCLITool {
|
|
|
72
72
|
// Check if session already exists
|
|
73
73
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
74
74
|
if (exists) {
|
|
75
|
-
await this.reconcileExistingSession(sessionName);
|
|
75
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
76
76
|
// Issue #2070: this branch used to return unconditionally. A tmux session
|
|
77
77
|
// outlives the agent that was launched into it — a quit, a self-update, a
|
|
78
78
|
// crash — and the launch was then skipped for a pane holding nothing but a
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gateway re-export for legacy session adoption (Issue #2866).
|
|
4
|
+
*
|
|
5
|
+
* `adoptLegacySessions` lives in `src/lib/session/`, which may not import
|
|
6
|
+
* `src/lib/tmux/**` directly (Issue #1922, `.eslintrc.json`
|
|
7
|
+
* `no-restricted-imports`). The CLITool layer is a sanctioned gateway, so the
|
|
8
|
+
* one session listing and the adoption table it needs are reached through here
|
|
9
|
+
* — the same arrangement as `session-ownership.ts` (Issue #2865).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.registerLegacyAlias = exports.lookupLegacyAlias = exports.dropLegacyAliasByLegacyName = exports.clearLegacyAliasesForTests = exports.listSessions = void 0;
|
|
13
|
+
var tmux_1 = require("../tmux/tmux");
|
|
14
|
+
Object.defineProperty(exports, "listSessions", { enumerable: true, get: function () { return tmux_1.listSessions; } });
|
|
15
|
+
var legacy_session_alias_1 = require("../tmux/legacy-session-alias");
|
|
16
|
+
Object.defineProperty(exports, "clearLegacyAliasesForTests", { enumerable: true, get: function () { return legacy_session_alias_1.clearLegacyAliasesForTests; } });
|
|
17
|
+
Object.defineProperty(exports, "dropLegacyAliasByLegacyName", { enumerable: true, get: function () { return legacy_session_alias_1.dropLegacyAliasByLegacyName; } });
|
|
18
|
+
Object.defineProperty(exports, "lookupLegacyAlias", { enumerable: true, get: function () { return legacy_session_alias_1.lookupLegacyAlias; } });
|
|
19
|
+
Object.defineProperty(exports, "registerLegacyAlias", { enumerable: true, get: function () { return legacy_session_alias_1.registerLegacyAlias; } });
|
|
@@ -255,7 +255,7 @@ class OpenCodeTool extends base_1.BaseCLITool {
|
|
|
255
255
|
// 200 wide, reconnected ones are 80" ships without anyone noticing —
|
|
256
256
|
// a reconnect would silently hand the detectors a geometry the creation
|
|
257
257
|
// path had been moved away from.
|
|
258
|
-
await this.reconcileExistingSession(sessionName, {
|
|
258
|
+
await this.reconcileExistingSession(sessionName, worktreePath, {
|
|
259
259
|
windowWidth: resolveOpencodePaneWidthChecked(),
|
|
260
260
|
windowHeight: tmux_pane_config_1.OPENCODE_PANE_HEIGHT,
|
|
261
261
|
});
|
|
@@ -16,18 +16,87 @@
|
|
|
16
16
|
* `import('../../lib/ws-server')` の 458ms のうち 234ms を占めていた。
|
|
17
17
|
*
|
|
18
18
|
* 規則そのものは 1 箇所に保つ — `BaseCLITool.getSessionName()` はこの関数へ委譲する。
|
|
19
|
+
*
|
|
20
|
+
* ## Issue #2866: 名前空間(ns)
|
|
21
|
+
*
|
|
22
|
+
* worktree ID はディレクトリ名から作られるので、DB が別の 2 台のサーバでも
|
|
23
|
+
* `mcbd-{cli}-{worktreeId}` が重なる。サーバ起動時に `initSessionNamespace()`
|
|
24
|
+
* (`session-namespace.ts`)が ns(16 進 8 桁)を決めると、以後の名前は
|
|
25
|
+
* `mcbd-{ns}-{cli}-{worktreeId}[-{suffix}]` になる。ns 未設定(CLI・テスト・
|
|
26
|
+
* 初期化失敗時)は従来形式のまま。ns はどの CLI ツール ID とも一致しないので、
|
|
27
|
+
* `mcbd-` の直後の区切りで新旧を見分けられる({@link parseSessionName})。
|
|
28
|
+
*
|
|
29
|
+
* このモジュールは CLI バンドル(`tsconfig.cli.json` は paths なし)にも入るので、
|
|
30
|
+
* `@/` を使わず、DB にも触らない。ns の保持だけをここで行い、DB からの読み書きは
|
|
31
|
+
* `session-namespace.ts` が受け持つ。
|
|
19
32
|
*/
|
|
20
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.SESSION_NAMESPACE_PATTERN = void 0;
|
|
35
|
+
exports.getActiveSessionNamespace = getActiveSessionNamespace;
|
|
36
|
+
exports.setActiveSessionNamespace = setActiveSessionNamespace;
|
|
37
|
+
exports.resolveNamespacedSessionName = resolveNamespacedSessionName;
|
|
21
38
|
exports.resolveSessionName = resolveSessionName;
|
|
39
|
+
exports.resolveLegacySessionName = resolveLegacySessionName;
|
|
40
|
+
exports.parseSessionName = parseSessionName;
|
|
22
41
|
const types_1 = require("./types");
|
|
23
42
|
const validation_1 = require("./validation");
|
|
43
|
+
const legacy_session_alias_1 = require("../tmux/legacy-session-alias");
|
|
44
|
+
const SESSION_NAME_PREFIX = 'mcbd-';
|
|
45
|
+
/** Shape of a session-name namespace: 8 lowercase hex digits (Issue #2866). */
|
|
46
|
+
exports.SESSION_NAMESPACE_PATTERN = /^[0-9a-f]{8}$/;
|
|
47
|
+
/** CLI tool ids, longest first, so a longer id is never read as a shorter one. */
|
|
48
|
+
const CLI_TOOL_IDS_LONGEST_FIRST = [...types_1.CLI_TOOL_IDS].sort((a, b) => b.length - a.length);
|
|
49
|
+
/**
|
|
50
|
+
* The namespace this process names its sessions with, or null (legacy names).
|
|
51
|
+
*
|
|
52
|
+
* @internal Read through `getSessionNamespace()` in `session-namespace.ts`.
|
|
53
|
+
* Kept on `globalThis` because the custom server sets it at startup while the
|
|
54
|
+
* Next route bundles — a separate module graph (Issue #2223) — read it.
|
|
55
|
+
*/
|
|
56
|
+
function getActiveSessionNamespace() {
|
|
57
|
+
return globalThis.__cmTmuxSessionNamespace ?? null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* @internal Set by `initSessionNamespace()` / reset by tests only.
|
|
61
|
+
*/
|
|
62
|
+
function setActiveSessionNamespace(namespace) {
|
|
63
|
+
if (namespace !== null && !exports.SESSION_NAMESPACE_PATTERN.test(namespace)) {
|
|
64
|
+
throw new Error(`Invalid session namespace: ${namespace}`);
|
|
65
|
+
}
|
|
66
|
+
globalThis.__cmTmuxSessionNamespace = namespace;
|
|
67
|
+
}
|
|
68
|
+
function buildSessionName(head, cliToolId, worktreeId, instanceId) {
|
|
69
|
+
const base = `${head}${cliToolId}-${worktreeId}`;
|
|
70
|
+
if (!instanceId || instanceId === cliToolId) {
|
|
71
|
+
(0, validation_1.validateSessionName)(base);
|
|
72
|
+
return base;
|
|
73
|
+
}
|
|
74
|
+
const suffix = (0, types_1.deriveSessionSuffix)(instanceId, cliToolId);
|
|
75
|
+
const sessionName = suffix ? `${base}-${suffix}` : base;
|
|
76
|
+
(0, validation_1.validateSessionName)(sessionName);
|
|
77
|
+
return sessionName;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The session name in the given namespace, ignoring legacy adoptions
|
|
81
|
+
* (Issue #2866). `namespace === null` is the legacy form.
|
|
82
|
+
*
|
|
83
|
+
* @throws Error if the resulting session name is invalid
|
|
84
|
+
*/
|
|
85
|
+
function resolveNamespacedSessionName(namespace, cliToolId, worktreeId, instanceId) {
|
|
86
|
+
const head = namespace === null ? SESSION_NAME_PREFIX : `${SESSION_NAME_PREFIX}${namespace}-`;
|
|
87
|
+
return buildSessionName(head, cliToolId, worktreeId, instanceId);
|
|
88
|
+
}
|
|
24
89
|
/**
|
|
25
90
|
* Resolve the tmux session name for a (worktree, CLI tool, instance) triple.
|
|
26
91
|
*
|
|
27
|
-
* Format (Issue #868):
|
|
28
|
-
* -
|
|
29
|
-
* `
|
|
30
|
-
*
|
|
92
|
+
* Format (Issue #868, #2866):
|
|
93
|
+
* - namespace set: `mcbd-{ns}-{cli_tool_id}-{worktree_id}[-{suffix}]` — unless a
|
|
94
|
+
* legacy session was adopted for that name (`adoptLegacySessions`), in which
|
|
95
|
+
* case the adopted legacy name is returned
|
|
96
|
+
* - namespace unset: `mcbd-{cli_tool_id}-{worktree_id}[-{suffix}]`
|
|
97
|
+
*
|
|
98
|
+
* The primary instance (`instanceId` omitted or `=== cliToolId`) carries no
|
|
99
|
+
* suffix.
|
|
31
100
|
*
|
|
32
101
|
* T2.3 (MF4-001): the result is validated to keep shell metacharacters out of
|
|
33
102
|
* the tmux command line.
|
|
@@ -40,18 +109,52 @@ const validation_1 = require("./validation");
|
|
|
40
109
|
*
|
|
41
110
|
* @example
|
|
42
111
|
* ```typescript
|
|
112
|
+
* // namespace unset
|
|
43
113
|
* resolveSessionName('claude', 'wt-1'); // 'mcbd-claude-wt-1'
|
|
44
114
|
* resolveSessionName('claude', 'wt-1', 'claude-2'); // 'mcbd-claude-wt-1-2'
|
|
115
|
+
* // namespace '0a1b2c3d'
|
|
116
|
+
* resolveSessionName('claude', 'wt-1'); // 'mcbd-0a1b2c3d-claude-wt-1'
|
|
45
117
|
* ```
|
|
46
118
|
*/
|
|
47
119
|
function resolveSessionName(cliToolId, worktreeId, instanceId) {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return
|
|
120
|
+
const namespace = getActiveSessionNamespace();
|
|
121
|
+
const name = resolveNamespacedSessionName(namespace, cliToolId, worktreeId, instanceId);
|
|
122
|
+
if (namespace === null)
|
|
123
|
+
return name;
|
|
124
|
+
return (0, legacy_session_alias_1.lookupLegacyAlias)(name) ?? name;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The legacy (pre-#2866) session name, whatever the namespace:
|
|
128
|
+
* `mcbd-{cli_tool_id}-{worktree_id}[-{suffix}]`.
|
|
129
|
+
*
|
|
130
|
+
* @throws Error if the resulting session name is invalid
|
|
131
|
+
*/
|
|
132
|
+
function resolveLegacySessionName(cliToolId, worktreeId, instanceId) {
|
|
133
|
+
return resolveNamespacedSessionName(null, cliToolId, worktreeId, instanceId);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Split a session name of either form. The worktree ID and the instance suffix
|
|
137
|
+
* are NOT separated — worktree IDs may contain `-`, so only the caller (who
|
|
138
|
+
* knows the set of worktree IDs) can tell them apart.
|
|
139
|
+
*
|
|
140
|
+
* @returns null when the name does not start with `mcbd-`, names no known CLI
|
|
141
|
+
* tool, or has nothing after the tool
|
|
142
|
+
*/
|
|
143
|
+
function parseSessionName(name) {
|
|
144
|
+
if (!name.startsWith(SESSION_NAME_PREFIX))
|
|
145
|
+
return null;
|
|
146
|
+
let body = name.slice(SESSION_NAME_PREFIX.length);
|
|
147
|
+
let namespace = null;
|
|
148
|
+
const dash = body.indexOf('-');
|
|
149
|
+
if (dash > 0 && exports.SESSION_NAMESPACE_PATTERN.test(body.slice(0, dash))) {
|
|
150
|
+
namespace = body.slice(0, dash);
|
|
151
|
+
body = body.slice(dash + 1);
|
|
52
152
|
}
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
153
|
+
const cliToolId = CLI_TOOL_IDS_LONGEST_FIRST.find((id) => body.startsWith(`${id}-`));
|
|
154
|
+
if (!cliToolId)
|
|
155
|
+
return null;
|
|
156
|
+
const rest = body.slice(cliToolId.length + 1);
|
|
157
|
+
if (rest === '')
|
|
158
|
+
return null;
|
|
159
|
+
return { namespace, cliToolId, rest };
|
|
57
160
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The tmux session-name namespace of this server (Issue #2866).
|
|
4
|
+
*
|
|
5
|
+
* Two CommandMate servers with different databases resolve the same
|
|
6
|
+
* `mcbd-{cli}-{worktreeId}` whenever their worktree directories share a name,
|
|
7
|
+
* because worktree IDs are derived from the directory name. Each server
|
|
8
|
+
* therefore mints a random namespace once, keeps it in `app_settings`
|
|
9
|
+
* (`tmux_session_namespace`), and puts it into every session name it creates:
|
|
10
|
+
* `mcbd-{ns}-{cli}-{worktreeId}[-{suffix}]` (`session-name.ts`).
|
|
11
|
+
*
|
|
12
|
+
* Initialized once at server startup, before the startup session reconcile.
|
|
13
|
+
* Until then — and in the CLI, in tests, or when initialization failed — the
|
|
14
|
+
* namespace is unset and names keep the legacy form.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.initSessionNamespace = initSessionNamespace;
|
|
18
|
+
exports.getSessionNamespace = getSessionNamespace;
|
|
19
|
+
exports.resetSessionNamespaceForTests = resetSessionNamespaceForTests;
|
|
20
|
+
const crypto_1 = require("crypto");
|
|
21
|
+
const app_settings_db_1 = require("../../lib/db/app-settings-db");
|
|
22
|
+
const logger_1 = require("../../lib/logger");
|
|
23
|
+
const session_name_1 = require("./session-name");
|
|
24
|
+
const logger = (0, logger_1.createLogger)('session-namespace');
|
|
25
|
+
/**
|
|
26
|
+
* Read the namespace from the DB, minting and saving one when it is absent or
|
|
27
|
+
* ill-formed, and make it the namespace every later session name uses.
|
|
28
|
+
*
|
|
29
|
+
* @param db - The server's database
|
|
30
|
+
* @returns The namespace now in effect
|
|
31
|
+
* @throws when the DB cannot be written; the namespace then stays unset
|
|
32
|
+
*/
|
|
33
|
+
function initSessionNamespace(db) {
|
|
34
|
+
const stored = (0, app_settings_db_1.getTmuxSessionNamespace)(db);
|
|
35
|
+
if (stored !== null && session_name_1.SESSION_NAMESPACE_PATTERN.test(stored)) {
|
|
36
|
+
(0, session_name_1.setActiveSessionNamespace)(stored);
|
|
37
|
+
return stored;
|
|
38
|
+
}
|
|
39
|
+
const namespace = (0, crypto_1.randomBytes)(4).toString('hex');
|
|
40
|
+
if (stored !== null) {
|
|
41
|
+
logger.warn('session-namespace:invalid-stored-value', { stored, replacement: namespace });
|
|
42
|
+
}
|
|
43
|
+
(0, app_settings_db_1.setTmuxSessionNamespace)(db, namespace);
|
|
44
|
+
(0, session_name_1.setActiveSessionNamespace)(namespace);
|
|
45
|
+
logger.info('session-namespace:initialized', { namespace, minted: true });
|
|
46
|
+
return namespace;
|
|
47
|
+
}
|
|
48
|
+
/** The namespace in effect, or null when not initialized. */
|
|
49
|
+
function getSessionNamespace() {
|
|
50
|
+
return (0, session_name_1.getActiveSessionNamespace)();
|
|
51
|
+
}
|
|
52
|
+
/** Test-only: back to "not initialized". */
|
|
53
|
+
function resetSessionNamespaceForTests() {
|
|
54
|
+
(0, session_name_1.setActiveSessionNamespace)(null);
|
|
55
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gateway re-export of the tmux session-ownership check (Issue #2865).
|
|
4
|
+
*
|
|
5
|
+
* Routes, pollers and the WebSocket server may not import `src/lib/tmux/**`
|
|
6
|
+
* directly (Issue #1922, `.eslintrc.json` `no-restricted-imports`); the
|
|
7
|
+
* CLITool layer is one of the sanctioned gateways, so the ownership check is
|
|
8
|
+
* reached through here. The implementation lives in
|
|
9
|
+
* `src/lib/tmux/session-ownership.ts`.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ownedSessionNameSet = exports.isSessionPathOwnedBy = exports.foreignSessionErrorBody = exports.createCachedOwnershipMatcher = exports.checkSessionOwnership = exports.assertSessionNotForeign = exports.ForeignSessionError = exports.FOREIGN_SESSION_ERROR_CODE = void 0;
|
|
13
|
+
var session_ownership_1 = require("../tmux/session-ownership");
|
|
14
|
+
Object.defineProperty(exports, "FOREIGN_SESSION_ERROR_CODE", { enumerable: true, get: function () { return session_ownership_1.FOREIGN_SESSION_ERROR_CODE; } });
|
|
15
|
+
Object.defineProperty(exports, "ForeignSessionError", { enumerable: true, get: function () { return session_ownership_1.ForeignSessionError; } });
|
|
16
|
+
Object.defineProperty(exports, "assertSessionNotForeign", { enumerable: true, get: function () { return session_ownership_1.assertSessionNotForeign; } });
|
|
17
|
+
Object.defineProperty(exports, "checkSessionOwnership", { enumerable: true, get: function () { return session_ownership_1.checkSessionOwnership; } });
|
|
18
|
+
Object.defineProperty(exports, "createCachedOwnershipMatcher", { enumerable: true, get: function () { return session_ownership_1.createCachedOwnershipMatcher; } });
|
|
19
|
+
Object.defineProperty(exports, "foreignSessionErrorBody", { enumerable: true, get: function () { return session_ownership_1.foreignSessionErrorBody; } });
|
|
20
|
+
Object.defineProperty(exports, "isSessionPathOwnedBy", { enumerable: true, get: function () { return session_ownership_1.isSessionPathOwnedBy; } });
|
|
21
|
+
Object.defineProperty(exports, "ownedSessionNameSet", { enumerable: true, get: function () { return session_ownership_1.ownedSessionNameSet; } });
|
|
@@ -63,7 +63,7 @@ class VibeLocalTool extends base_1.BaseCLITool {
|
|
|
63
63
|
const sessionName = this.getSessionName(worktreeId, instanceId);
|
|
64
64
|
const exists = await (0, tmux_1.hasSession)(sessionName);
|
|
65
65
|
if (exists) {
|
|
66
|
-
await this.reconcileExistingSession(sessionName);
|
|
66
|
+
await this.reconcileExistingSession(sessionName, worktreePath);
|
|
67
67
|
// Issue #2070: this branch used to return unconditionally. A tmux session
|
|
68
68
|
// outlives the agent that was launched into it — a quit, a self-update, a
|
|
69
69
|
// crash — and the launch was then skipped for a pane holding nothing but a
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session ownership by worktree id (Issue #2865).
|
|
4
|
+
*
|
|
5
|
+
* For callers that hold only a worktree id — the Auto-Yes poller and
|
|
6
|
+
* `sendUserMessage` (timer / relay sends) — and would
|
|
7
|
+
* otherwise have to reach into the DB and the tmux gateway separately. Kept out
|
|
8
|
+
* of `session-ownership.ts` so the plain ownership check does not drag the DB
|
|
9
|
+
* layer into every module that imports it.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.checkWorktreeSessionOwnership = checkWorktreeSessionOwnership;
|
|
13
|
+
const db_instance_1 = require("../db/db-instance");
|
|
14
|
+
const worktree_db_1 = require("../db/worktree-db");
|
|
15
|
+
const session_ownership_1 = require("../tmux/session-ownership");
|
|
16
|
+
/**
|
|
17
|
+
* Ownership of `sessionName` against the worktree row `worktreeId`. `null` when
|
|
18
|
+
* the row does not exist — the caller cannot vouch for the session and must not
|
|
19
|
+
* drive it.
|
|
20
|
+
*
|
|
21
|
+
* @param db - The handle to read the row from; defaults to the server's
|
|
22
|
+
*/
|
|
23
|
+
async function checkWorktreeSessionOwnership(worktreeId, sessionName, db = (0, db_instance_1.getDbInstance)()) {
|
|
24
|
+
const worktree = (0, worktree_db_1.getWorktreeById)(db, worktreeId);
|
|
25
|
+
if (!worktree)
|
|
26
|
+
return null;
|
|
27
|
+
return (0, session_ownership_1.checkSessionOwnership)(sessionName, worktree.path);
|
|
28
|
+
}
|
|
@@ -16,6 +16,8 @@ exports.setDefaultSelectedAgents = setDefaultSelectedAgents;
|
|
|
16
16
|
exports.clearDefaultSelectedAgents = clearDefaultSelectedAgents;
|
|
17
17
|
exports.getDefaultSurfaceMode = getDefaultSurfaceMode;
|
|
18
18
|
exports.setDefaultSurfaceMode = setDefaultSurfaceMode;
|
|
19
|
+
exports.getTmuxSessionNamespace = getTmuxSessionNamespace;
|
|
20
|
+
exports.setTmuxSessionNamespace = setTmuxSessionNamespace;
|
|
19
21
|
const selected_agents_validator_1 = require("../../lib/selected-agents-validator");
|
|
20
22
|
const ui_state_1 = require("../../types/ui-state");
|
|
21
23
|
// ============================================================================
|
|
@@ -45,6 +47,14 @@ const KEY_DEFAULT_SELECTED_AGENTS = 'default_selected_agents';
|
|
|
45
47
|
* reaches an install that never chose.
|
|
46
48
|
*/
|
|
47
49
|
const KEY_DEFAULT_SURFACE_MODE = 'default_surface_mode';
|
|
50
|
+
/**
|
|
51
|
+
* Storage key for this server's tmux session-name namespace (Issue #2866).
|
|
52
|
+
*
|
|
53
|
+
* 8 lowercase hex digits, minted once at first startup. Validated by
|
|
54
|
+
* `initSessionNamespace()` rather than here: an ill-formed row has to be seen
|
|
55
|
+
* (and warned about) before it is replaced, not silently read as "unset".
|
|
56
|
+
*/
|
|
57
|
+
const KEY_TMUX_SESSION_NAMESPACE = 'tmux_session_namespace';
|
|
48
58
|
/** How many recently used directories to remember (Issue #1517) */
|
|
49
59
|
exports.RECENT_BROWSE_PATHS_LIMIT = 5;
|
|
50
60
|
// ============================================================================
|
|
@@ -200,3 +210,22 @@ function getDefaultSurfaceMode(db) {
|
|
|
200
210
|
function setDefaultSurfaceMode(db, mode) {
|
|
201
211
|
writeScalar(db, KEY_DEFAULT_SURFACE_MODE, mode);
|
|
202
212
|
}
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// tmux session namespace (Issue #2866)
|
|
215
|
+
// ============================================================================
|
|
216
|
+
/**
|
|
217
|
+
* Get the stored tmux session-name namespace, unvalidated.
|
|
218
|
+
*
|
|
219
|
+
* @returns The raw stored value, or null when unset
|
|
220
|
+
*/
|
|
221
|
+
function getTmuxSessionNamespace(db) {
|
|
222
|
+
return readScalar(db, KEY_TMUX_SESSION_NAMESPACE);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Save the tmux session-name namespace.
|
|
226
|
+
*
|
|
227
|
+
* @param namespace - Already-validated namespace (`^[0-9a-f]{8}$`)
|
|
228
|
+
*/
|
|
229
|
+
function setTmuxSessionNamespace(db, namespace) {
|
|
230
|
+
writeScalar(db, KEY_TMUX_SESSION_NAMESPACE, namespace);
|
|
231
|
+
}
|