commandmate 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +164 -164
- package/.next/app-path-routes-manifest.json +28 -28
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +9 -9
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js +1 -1
- package/.next/server/app/api/assistant/conversation/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/conversation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js +1 -1
- package/.next/server/app/api/assistant/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js +1 -1
- package/.next/server/app/api/assistant/messages/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/session/route.js +1 -1
- package/.next/server/app/api/assistant/session/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/start/route.js +3 -3
- package/.next/server/app/api/assistant/start/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/start/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/terminal/route.js +4 -4
- package/.next/server/app/api/assistant/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js +1 -1
- package/.next/server/app/api/assistant/tools/route.js.nft.json +1 -1
- package/.next/server/app/api/assistant/tools/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js.nft.json +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js +1 -1
- package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js +1 -1
- package/.next/server/app/api/repositories/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route.js +1 -1
- package/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js +1 -1
- package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js +1 -1
- package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js +1 -1
- package/.next/server/app/api/settings/default-agents/route.js.nft.json +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route.js +4 -3
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route.js +4 -3
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js +2 -2
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route.js.nft.json +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/chat/page.js +2 -2
- package/.next/server/app/chat/page.js.nft.json +1 -1
- package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page.js +2 -2
- package/.next/server/app/more/page.js.nft.json +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page.js +2 -2
- package/.next/server/app/repositories/page.js.nft.json +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page.js +1 -1
- package/.next/server/app/review/page.js.nft.json +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page.js +1 -1
- package/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page.js +2 -2
- package/.next/server/app/skills/[skillId]/page.js.nft.json +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page.js +2 -2
- package/.next/server/app/skills/installed/page.js.nft.json +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page.js +1 -1
- package/.next/server/app/skills/page.js.nft.json +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +10 -10
- package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +28 -28
- package/.next/server/chunks/1058.js +1 -1
- package/.next/server/chunks/1068.js +1 -1
- package/.next/server/chunks/1262.js +1 -1
- package/.next/server/chunks/1886.js +3 -3
- package/.next/server/chunks/1990.js +103 -0
- package/.next/server/chunks/2119.js +1 -1
- package/.next/server/chunks/2328.js +1 -1
- package/.next/server/chunks/2404.js +1 -1
- package/.next/server/chunks/2445.js +1 -1
- package/.next/server/chunks/261.js +1 -1
- package/.next/server/chunks/3123.js +1 -1
- package/.next/server/chunks/3241.js +1 -1
- package/.next/server/chunks/3480.js +5 -4
- package/.next/server/chunks/4299.js +1 -1
- package/.next/server/chunks/4393.js +1 -1
- package/.next/server/chunks/4443.js +1 -5
- package/.next/server/chunks/5017.js +1 -1
- package/.next/server/chunks/5043.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/552.js +2 -2
- package/.next/server/chunks/6072.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/663.js +4 -3
- package/.next/server/chunks/6894.js +2 -2
- package/.next/server/chunks/7187.js +1 -0
- package/.next/server/chunks/7472.js +1 -1
- package/.next/server/chunks/{880.js → 7859.js} +6 -6
- package/.next/server/chunks/7905.js +1 -1
- package/.next/server/chunks/8800.js +2 -2
- package/.next/server/chunks/8918.js +7 -0
- package/.next/server/chunks/9123.js +2 -2
- package/.next/server/chunks/9130.js +4 -4
- package/.next/server/chunks/9627.js +1 -1
- package/.next/server/chunks/9696.js +2 -2
- package/.next/server/chunks/9798.js +1 -1
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/1783-11c9b4d8a52ebd91.js +1 -0
- package/.next/static/chunks/4718-de1224c9e8a6e7fc.js +1 -0
- package/.next/static/chunks/6022-2fa0b5a82d4ce7b6.js +1 -0
- package/.next/static/chunks/{5229-6c89475b61bd2c8b.js → 6170-951b9f5fe6b4b3b5.js} +1 -1
- package/.next/static/chunks/app/chat/{page-9aa2011410895b0d.js → page-37d7615d17d7e2a0.js} +1 -1
- package/.next/static/chunks/app/layout-4c2f21e3f653ee4c.js +1 -0
- package/.next/static/chunks/app/more/{page-333bba1c8bbc9c11.js → page-353a3924e6d7968e.js} +1 -1
- package/.next/static/chunks/app/{page-214f7ffa13a0cf10.js → page-c2bf871d953a1d6f.js} +1 -1
- package/.next/static/chunks/app/repositories/{page-4951cac905e50224.js → page-7d0f26df0537254c.js} +1 -1
- package/.next/static/chunks/app/review/{page-a0899b2d285318c3.js → page-e3f141b2829973e9.js} +1 -1
- package/.next/static/chunks/app/sessions/{page-fb36145ec732092a.js → page-53f188ed9ca49e5f.js} +1 -1
- package/.next/static/chunks/app/skills/[skillId]/{page-9099e26b60442873.js → page-80569b720aea59cc.js} +1 -1
- package/.next/static/chunks/app/skills/installed/{page-182e32368696d824.js → page-dbd2690ad72da95b.js} +1 -1
- package/.next/static/chunks/app/skills/{page-d3fdc88239ebe0ab.js → page-dacd36f9c11aa7da.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/page-97205088520255a5.js +1 -0
- package/.next/static/css/5c13ea243dfdcb66.css +1 -0
- package/.next/trace +13 -13
- package/README.md +37 -11
- package/dist/cli/commands/attach.d.ts +50 -0
- package/dist/cli/commands/attach.d.ts.map +1 -0
- package/dist/cli/commands/attach.js +204 -0
- package/dist/cli/commands/capture.d.ts.map +1 -1
- package/dist/cli/commands/capture.js +114 -0
- package/dist/cli/commands/instances.d.ts.map +1 -1
- package/dist/cli/commands/instances.js +23 -2
- package/dist/cli/commands/ls.d.ts.map +1 -1
- package/dist/cli/commands/ls.js +41 -1
- package/dist/cli/config/cli-dependencies.d.ts.map +1 -1
- package/dist/cli/config/cli-dependencies.js +34 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +5 -0
- package/dist/cli/types/index.d.ts +36 -0
- package/dist/cli/types/index.d.ts.map +1 -1
- package/dist/config/tmux-pane-config.d.ts +153 -0
- package/dist/config/tmux-pane-config.d.ts.map +1 -0
- package/dist/config/tmux-pane-config.js +172 -0
- package/dist/lib/cli-tools/session-name.d.ts +44 -0
- package/dist/lib/cli-tools/session-name.d.ts.map +1 -0
- package/dist/lib/cli-tools/session-name.js +57 -0
- package/dist/lib/cli-tools/types.d.ts +1 -1
- package/dist/lib/cli-tools/types.d.ts.map +1 -1
- package/dist/lib/cli-tools/types.js +6 -1
- package/dist/lib/cli-tools/validation.d.ts +34 -0
- package/dist/lib/cli-tools/validation.d.ts.map +1 -0
- package/dist/lib/cli-tools/validation.js +41 -0
- package/dist/lib/detection/status-reason.d.ts +18 -0
- package/dist/lib/detection/status-reason.d.ts.map +1 -1
- package/dist/lib/detection/status-reason.js +18 -0
- package/dist/lib/detection/tools/verified-against.d.ts +57 -7
- package/dist/lib/detection/tools/verified-against.d.ts.map +1 -1
- package/dist/lib/detection/tools/verified-against.js +59 -8
- package/dist/lib/detection/version-probes.d.ts +26 -5
- package/dist/lib/detection/version-probes.d.ts.map +1 -1
- package/dist/lib/detection/version-probes.js +28 -6
- package/dist/lib/session/tmux-session-surface.d.ts +369 -0
- package/dist/lib/session/tmux-session-surface.d.ts.map +1 -0
- package/dist/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/config/cli-tool-timing-config.js +12 -1
- package/dist/server/src/config/detection-evidence-config.js +5 -0
- package/dist/server/src/config/schedule-config.js +28 -1
- package/dist/server/src/lib/cli-tools/antigravity.js +2 -2
- package/dist/server/src/lib/cli-tools/base.js +13 -8
- package/dist/server/src/lib/cli-tools/claude.js +20 -0
- package/dist/server/src/lib/cli-tools/codex.js +205 -61
- package/dist/server/src/lib/cli-tools/command-code.js +349 -0
- package/dist/server/src/lib/cli-tools/composer-spec.js +6 -0
- package/dist/server/src/lib/cli-tools/copilot.js +2 -2
- package/dist/server/src/lib/cli-tools/gemini.js +2 -2
- package/dist/server/src/lib/cli-tools/graceful-exit.js +16 -1
- package/dist/server/src/lib/cli-tools/index.js +4 -1
- package/dist/server/src/lib/cli-tools/install-hints.js +131 -0
- package/dist/server/src/lib/cli-tools/liveness-spec.js +18 -0
- package/dist/server/src/lib/cli-tools/manager.js +2 -0
- package/dist/server/src/lib/cli-tools/opencode.js +2 -2
- package/dist/server/src/lib/cli-tools/start-availability.js +18 -11
- package/dist/server/src/lib/cli-tools/types.js +6 -1
- package/dist/server/src/lib/cli-tools/vibe-local.js +2 -2
- package/dist/server/src/lib/cmate-parser.js +6 -0
- package/dist/server/src/lib/detection/cli-patterns.js +441 -8
- package/dist/server/src/lib/detection/opencode-modal-overlay.js +66 -100
- package/dist/server/src/lib/detection/selection-shape.js +341 -0
- package/dist/server/src/lib/detection/sgr-background.js +210 -0
- package/dist/server/src/lib/detection/status-detector.js +6 -0
- package/dist/server/src/lib/detection/status-reason.js +18 -0
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +38 -15
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +392 -0
- package/dist/server/src/lib/detection/tools/codex/detect.js +83 -2
- package/dist/server/src/lib/detection/tools/command-code/detect.js +159 -0
- package/dist/server/src/lib/detection/tools/registry.js +6 -4
- package/dist/server/src/lib/detection/tools/verified-against.js +59 -8
- package/dist/server/src/lib/detection/version-probes.js +28 -6
- package/dist/server/src/lib/hooks/sources/antigravity/history.js +101 -21
- package/dist/server/src/lib/hooks/sources/antigravity/transcript.js +39 -0
- package/dist/server/src/lib/hooks/sources/claude/history.js +245 -21
- package/dist/server/src/lib/hooks/sources/claude/transcript.js +175 -13
- package/dist/server/src/lib/hooks/sources/codex/history.js +84 -15
- package/dist/server/src/lib/hooks/sources/codex/hooks-config.js +130 -17
- package/dist/server/src/lib/hooks/sources/codex/relay-install.js +145 -0
- package/dist/server/src/lib/hooks/sources/command-code/history.js +865 -0
- package/dist/server/src/lib/hooks/sources/command-code/hooks-config.js +390 -0
- package/dist/server/src/lib/hooks/sources/command-code/source.js +290 -0
- package/dist/server/src/lib/hooks/sources/command-code/tool-id.js +18 -0
- package/dist/server/src/lib/hooks/sources/command-code/transcript.js +604 -0
- package/dist/server/src/lib/hooks/sources/index.js +3 -1
- package/dist/server/src/lib/hooks/sources/opencode/history.js +57 -3
- package/dist/server/src/lib/hooks/sources/opencode/transcript.js +24 -28
- package/dist/server/src/lib/hooks/sources/registry.js +4 -0
- package/dist/server/src/lib/hooks/sources/turn-body.js +77 -19
- package/dist/server/src/lib/hooks/stop-history-capture.js +58 -25
- package/dist/server/src/lib/job-executor.js +12 -0
- package/dist/server/src/lib/polling/auto-yes-dialog-gate.js +6 -0
- package/dist/server/src/lib/polling/response-checker.js +112 -7
- package/dist/server/src/lib/polling/structured-history-gate.js +15 -8
- package/dist/server/src/lib/realtime/types.js +15 -5
- package/dist/server/src/lib/response-cleaner.js +24 -1
- package/dist/server/src/lib/response-extractor.js +11 -0
- package/dist/server/src/lib/session/claude-executor.js +223 -4
- package/dist/server/src/lib/session/cli-session.js +52 -0
- package/dist/server/src/lib/session/tmux-session-surface.js +525 -0
- package/dist/server/src/lib/skills/compatibility-matrix.js +117 -1
- package/dist/server/src/lib/tmux/geometry-delegation.js +143 -0
- package/dist/server/src/lib/tmux/read-mode-pager.js +76 -10
- package/dist/server/src/lib/tmux/read-mode.js +44 -2
- package/dist/server/src/lib/tmux/session-hook-scripts.js +249 -0
- package/dist/server/src/lib/tmux/session-hooks.js +122 -0
- package/dist/server/src/lib/tmux/session-status-options.js +213 -0
- package/dist/server/src/lib/tmux/tmux.js +79 -2
- package/dist/server/src/lib/version-checker.js +110 -0
- package/dist/server/src/lib/ws-server.js +16 -10
- package/dist/server/src/types/agent-transcript.js +73 -1
- package/dist/server/src/types/terminal-keys.js +131 -3
- package/dist/types/terminal-keys.d.ts +100 -3
- package/dist/types/terminal-keys.d.ts.map +1 -1
- package/dist/types/terminal-keys.js +131 -3
- package/package.json +1 -1
- package/.next/server/chunks/3099.js +0 -5
- package/.next/server/chunks/7824.js +0 -1
- package/.next/static/chunks/3916-0e929d089282dc5d.js +0 -1
- package/.next/static/chunks/6022-7a7d1760fc9814c7.js +0 -1
- package/.next/static/chunks/6381-dbf04a99647f6018.js +0 -1
- package/.next/static/chunks/app/layout-6a26ea22d5cf03dc.js +0 -1
- package/.next/static/chunks/app/worktrees/[id]/page-aac399392ec8c273.js +0 -1
- package/.next/static/css/23f9c40ecc458c77.css +0 -1
- /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_buildManifest.js +0 -0
- /package/.next/static/{pcpB4K6KreMzu2qbhvuRY → nXW4dPkpE_9xUf_9ySRff}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The shell scripts session-scoped tmux hooks run (Issue #2317, Phases C and D).
|
|
4
|
+
*
|
|
5
|
+
* ## Why the text is embedded rather than shipped as a file
|
|
6
|
+
*
|
|
7
|
+
* The same reason `read-mode-pager.ts` gives for `cm-read-pane.sh`:
|
|
8
|
+
* `package.json`'s `files` list does not publish `scripts/`, and an `npx`
|
|
9
|
+
* install lives in a cache npm may garbage-collect out from under a hook that
|
|
10
|
+
* outlives the process which installed it. Embedding the text and materializing
|
|
11
|
+
* it into `~/.commandmate/bin/` gives every hook one absolute path that is
|
|
12
|
+
* stable across global / local / npx installs.
|
|
13
|
+
*
|
|
14
|
+
* ## Why the hooks call scripts instead of doing the work inline
|
|
15
|
+
*
|
|
16
|
+
* Measured on tmux 3.5a (Issue #2317 技術検証): a hook body of the shape
|
|
17
|
+
* `if-shell -F '#{…}' '<command>'` is accepted by `set-hook` and then never
|
|
18
|
+
* fires — silently, with no error anywhere. A
|
|
19
|
+
* `run-shell -b '<script> #{session_name} #{client_control_mode}'` DOES fire.
|
|
20
|
+
* So the formats are handed to a script and every branch is taken in `sh`.
|
|
21
|
+
*
|
|
22
|
+
* The hook environment is the tmux SERVER's, which carries `TMUX` — so the bare
|
|
23
|
+
* `tmux` these scripts call reaches the same server that fired the hook, private
|
|
24
|
+
* socket included. That is verified, not assumed: the whole live probe for this
|
|
25
|
+
* Issue ran under `tmux -L cm2317` and the scripts reached that server.
|
|
26
|
+
*
|
|
27
|
+
* ## Both scripts refuse to touch a session that is not CommandMate's
|
|
28
|
+
*
|
|
29
|
+
* A hook is session-scoped, so in principle it can only fire on the session it
|
|
30
|
+
* was installed on. The `mcbd-` guard is still there because these scripts are
|
|
31
|
+
* also runnable by hand and because a session can be renamed.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.AUTO_POPUP_SCRIPT = exports.LIVE_DELEGATE_SCRIPT = exports.LIVE_RESTORE_SCRIPT = exports.AUTO_POPUP_SCRIPT_FILENAME = exports.LIVE_DELEGATE_SCRIPT_FILENAME = exports.LIVE_RESTORE_SCRIPT_FILENAME = void 0;
|
|
35
|
+
exports.getScriptDir = getScriptDir;
|
|
36
|
+
exports.getScriptPath = getScriptPath;
|
|
37
|
+
exports.materializeScript = materializeScript;
|
|
38
|
+
exports.materializeLiveRestoreScript = materializeLiveRestoreScript;
|
|
39
|
+
exports.materializeLiveDelegateScript = materializeLiveDelegateScript;
|
|
40
|
+
exports.materializeAutoPopupScript = materializeAutoPopupScript;
|
|
41
|
+
const fs_1 = require("fs");
|
|
42
|
+
const os_1 = require("os");
|
|
43
|
+
const path_1 = require("path");
|
|
44
|
+
const tmux_pane_config_1 = require("../../config/tmux-pane-config");
|
|
45
|
+
const tmux_session_surface_1 = require("../session/tmux-session-surface");
|
|
46
|
+
const read_mode_pager_1 = require("./read-mode-pager");
|
|
47
|
+
/** Basename of the Phase D geometry-restore script. */
|
|
48
|
+
exports.LIVE_RESTORE_SCRIPT_FILENAME = 'cm-live-restore.sh';
|
|
49
|
+
/** Basename of the Phase D geometry-delegation script. */
|
|
50
|
+
exports.LIVE_DELEGATE_SCRIPT_FILENAME = 'cm-live-delegate.sh';
|
|
51
|
+
/** Basename of the Phase C auto-popup script. */
|
|
52
|
+
exports.AUTO_POPUP_SCRIPT_FILENAME = 'cm-auto-popup.sh';
|
|
53
|
+
/**
|
|
54
|
+
* Restore a session's pinned canvas once no human client is attached.
|
|
55
|
+
*
|
|
56
|
+
* NOT a hook body — tmux 3.5a never fires a session-scoped `client-detached`
|
|
57
|
+
* (see the measurement table in `live-attach.ts`). Two things run this sequence:
|
|
58
|
+
* `commandmate attach --live` when `attach-session` returns, and the server's
|
|
59
|
+
* status poll (`reconcileDelegatedGeometry`) for every case where the CLI never
|
|
60
|
+
* got to — it was killed, the terminal window was closed, or the detach happened
|
|
61
|
+
* from a client this process never saw. This script is the third, manual, path:
|
|
62
|
+
* the escape hatch for a session left delegated while no server is running.
|
|
63
|
+
*
|
|
64
|
+
* The control-mode test is the whole reason the client count is not simply
|
|
65
|
+
* `#{session_attached}`: CommandMate's own transport attaches as a `tmux -C`
|
|
66
|
+
* client and never leaves, so a session with the human gone still reports
|
|
67
|
+
* `session_attached=1`. `client_control_mode` is `1` for those and `0` for a
|
|
68
|
+
* terminal, so the restore waits for the HUMAN count to reach zero
|
|
69
|
+
* (Issue #2317 受入条件 Phase D 4).
|
|
70
|
+
*/
|
|
71
|
+
exports.LIVE_RESTORE_SCRIPT = `#!/bin/sh
|
|
72
|
+
# CommandMate live-attach restore (Issue #2317) — generated file, edits are overwritten.
|
|
73
|
+
#
|
|
74
|
+
# sh ~/.commandmate/bin/${exports.LIVE_RESTORE_SCRIPT_FILENAME} <session> [control_mode] [width] [height]
|
|
75
|
+
#
|
|
76
|
+
# Pins the session's window back to CommandMate's canvas once no human client is
|
|
77
|
+
# attached to it any more. Safe to run when nothing is delegated: it then simply
|
|
78
|
+
# re-applies the geometry the session already has.
|
|
79
|
+
set -u
|
|
80
|
+
|
|
81
|
+
SESSION="\${1:-}"
|
|
82
|
+
CONTROL_MODE="\${2:-0}"
|
|
83
|
+
WIDTH="\${3:-${tmux_pane_config_1.TUI_PANE_WIDTH}}"
|
|
84
|
+
HEIGHT="\${4:-${tmux_pane_config_1.TUI_PANE_HEIGHT}}"
|
|
85
|
+
|
|
86
|
+
case "$SESSION" in
|
|
87
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}*) ;;
|
|
88
|
+
*) exit 0 ;;
|
|
89
|
+
esac
|
|
90
|
+
|
|
91
|
+
# A control-mode client detaching is CommandMate's own transport reconnecting,
|
|
92
|
+
# not the human leaving. Doing the restore here would fight the human's attach.
|
|
93
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Anyone left who is NOT a control client? Then the geometry is still theirs.
|
|
98
|
+
HUMANS=$(tmux list-clients -t "=$SESSION:" -F '#{client_control_mode}' 2>/dev/null \\
|
|
99
|
+
| grep -c -v '^1$') || HUMANS=0
|
|
100
|
+
if [ "\${HUMANS:-0}" -gt 0 ]; then
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
tmux set-window-option -t "=$SESSION:" window-size manual 2>/dev/null || exit 0
|
|
105
|
+
tmux resize-window -t "=$SESSION:" -x "$WIDTH" -y "$HEIGHT" 2>/dev/null || true
|
|
106
|
+
tmux set-option -u -t "=$SESSION:" @cm_delegated 2>/dev/null || true
|
|
107
|
+
`;
|
|
108
|
+
/**
|
|
109
|
+
* Hand a session's geometry to the terminal that just attached.
|
|
110
|
+
*
|
|
111
|
+
* The opt-in half of Phase D: `commandmate attach --live` performs these two
|
|
112
|
+
* writes itself, and this script is what makes a HAND-ROLLED `tmux attach`
|
|
113
|
+
* behave the same way when the operator asked for it with
|
|
114
|
+
* `CM_LIVE_ATTACH_HOOK=on`.
|
|
115
|
+
*
|
|
116
|
+
* claude-only by session-name prefix, and that is not a shortcut. The session
|
|
117
|
+
* name is `mcbd-<tool>-<worktree>`, no other CLI tool id begins with `claude`,
|
|
118
|
+
* and the script has nothing but the name to go on — a hook fires with tmux
|
|
119
|
+
* formats, not with CommandMate's roster. Widening it means widening
|
|
120
|
+
* `LIVE_ATTACH_TOOLS` too, and that needs the per-tool re-measurement
|
|
121
|
+
* Issue #2317 puts out of scope.
|
|
122
|
+
*/
|
|
123
|
+
exports.LIVE_DELEGATE_SCRIPT = `#!/bin/sh
|
|
124
|
+
# CommandMate live-attach delegate (Issue #2317) — generated file, edits are overwritten.
|
|
125
|
+
#
|
|
126
|
+
# sh ~/.commandmate/bin/${exports.LIVE_DELEGATE_SCRIPT_FILENAME} <session> <control_mode> [client]
|
|
127
|
+
#
|
|
128
|
+
# Hands the session's window from CommandMate's pinned canvas to the terminal
|
|
129
|
+
# that just attached, so an alternate-screen agent re-lays-out and its transcript
|
|
130
|
+
# becomes readable. Installed as a session-scoped \`client-attached[0]\` hook only
|
|
131
|
+
# when CM_LIVE_ATTACH_HOOK=on; \`commandmate attach --live\` does the same two
|
|
132
|
+
# writes itself and needs no hook.
|
|
133
|
+
#
|
|
134
|
+
# The window is put back by whoever notices the human is gone first: the CLI on
|
|
135
|
+
# return from attach-session, or the server's status poll. This script never
|
|
136
|
+
# restores — the attach edge is the only edge tmux 3.5a lets a session-scoped
|
|
137
|
+
# hook see.
|
|
138
|
+
set -u
|
|
139
|
+
|
|
140
|
+
SESSION="\${1:-}"
|
|
141
|
+
CONTROL_MODE="\${2:-0}"
|
|
142
|
+
|
|
143
|
+
case "$SESSION" in
|
|
144
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}claude-*) ;;
|
|
145
|
+
*) exit 0 ;;
|
|
146
|
+
esac
|
|
147
|
+
|
|
148
|
+
# A control-mode client is CommandMate's own transport. Handing it the geometry
|
|
149
|
+
# would resize the canvas to whatever that connection negotiated, which is the
|
|
150
|
+
# #1163 regression this whole feature is built to avoid.
|
|
151
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
152
|
+
exit 0
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
# Raised BEFORE the size change, so a status poll landing between the two sees
|
|
156
|
+
# "delegated, still pinned" rather than "not delegated, 44 rows".
|
|
157
|
+
tmux set-option -t "=$SESSION:" @cm_delegated 1 2>/dev/null || exit 0
|
|
158
|
+
tmux set-window-option -t "=$SESSION:" window-size latest 2>/dev/null || true
|
|
159
|
+
`;
|
|
160
|
+
/**
|
|
161
|
+
* Open the following transcript popup when a human attaches (Phase C, opt-in).
|
|
162
|
+
*
|
|
163
|
+
* Default off, and it has to be: the popup owns the keyboard until `q` is
|
|
164
|
+
* pressed, so opening it unasked would make every attach start by taking input
|
|
165
|
+
* away from the composer. `CM_READ_MODE_AUTO_POPUP=on` is the opt-in, and even
|
|
166
|
+
* then the control-mode test below keeps it from firing for CommandMate's own
|
|
167
|
+
* transport — a popup opened on a control client would be a popup nobody can
|
|
168
|
+
* see and nobody can close.
|
|
169
|
+
*/
|
|
170
|
+
exports.AUTO_POPUP_SCRIPT = `#!/bin/sh
|
|
171
|
+
# CommandMate auto read popup (Issue #2317) — generated file, edits are overwritten.
|
|
172
|
+
#
|
|
173
|
+
# sh ~/.commandmate/bin/${exports.AUTO_POPUP_SCRIPT_FILENAME} <session> <control_mode> <client>
|
|
174
|
+
#
|
|
175
|
+
# Opens the following transcript popup for a human client attaching to a
|
|
176
|
+
# CommandMate session. Never opens for a control-mode client.
|
|
177
|
+
set -u
|
|
178
|
+
|
|
179
|
+
SESSION="\${1:-}"
|
|
180
|
+
CONTROL_MODE="\${2:-0}"
|
|
181
|
+
CLIENT="\${3:-}"
|
|
182
|
+
|
|
183
|
+
case "$SESSION" in
|
|
184
|
+
${tmux_session_surface_1.MCBD_SESSION_PREFIX}*) ;;
|
|
185
|
+
*) exit 0 ;;
|
|
186
|
+
esac
|
|
187
|
+
|
|
188
|
+
if [ "$CONTROL_MODE" = "1" ]; then
|
|
189
|
+
exit 0
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
PAGER_SCRIPT="$HOME/.commandmate/bin/${read_mode_pager_1.PAGER_SCRIPT_FILENAME}"
|
|
193
|
+
[ -x "$PAGER_SCRIPT" ] || exit 0
|
|
194
|
+
|
|
195
|
+
if [ -n "$CLIENT" ]; then
|
|
196
|
+
tmux display-popup -c "$CLIENT" -w 90% -h 85% -E "sh \\"$PAGER_SCRIPT\\" --follow \\"$SESSION\\"" 2>/dev/null || true
|
|
197
|
+
else
|
|
198
|
+
tmux display-popup -w 90% -h 85% -E "sh \\"$PAGER_SCRIPT\\" --follow \\"$SESSION\\"" 2>/dev/null || true
|
|
199
|
+
fi
|
|
200
|
+
`;
|
|
201
|
+
/** Directory every materialized CommandMate script lives in. */
|
|
202
|
+
function getScriptDir() {
|
|
203
|
+
return (0, path_1.join)((0, os_1.homedir)(), '.commandmate', 'bin');
|
|
204
|
+
}
|
|
205
|
+
/** Absolute path of a materialized script. */
|
|
206
|
+
function getScriptPath(filename) {
|
|
207
|
+
return (0, path_1.join)(getScriptDir(), filename);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Write a script to `~/.commandmate/bin/<filename>` if its content changed.
|
|
211
|
+
*
|
|
212
|
+
* Idempotent by content comparison so a restart does not churn the file's mtime,
|
|
213
|
+
* and re-executable after a `chmod` accident because the mode is re-applied —
|
|
214
|
+
* the same contract `materializePagerScript()` has had since #1623.
|
|
215
|
+
*
|
|
216
|
+
* @param filename - Basename to write
|
|
217
|
+
* @param content - Full script text
|
|
218
|
+
* @returns The absolute path written
|
|
219
|
+
*/
|
|
220
|
+
function materializeScript(filename, content) {
|
|
221
|
+
const scriptPath = getScriptPath(filename);
|
|
222
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(scriptPath), { recursive: true });
|
|
223
|
+
let current;
|
|
224
|
+
if ((0, fs_1.existsSync)(scriptPath)) {
|
|
225
|
+
try {
|
|
226
|
+
current = (0, fs_1.readFileSync)(scriptPath, 'utf-8');
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
current = undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (current !== content) {
|
|
233
|
+
(0, fs_1.writeFileSync)(scriptPath, content, { mode: 0o755 });
|
|
234
|
+
}
|
|
235
|
+
(0, fs_1.chmodSync)(scriptPath, 0o755);
|
|
236
|
+
return scriptPath;
|
|
237
|
+
}
|
|
238
|
+
/** Materialize the Phase D restore script and return its absolute path. */
|
|
239
|
+
function materializeLiveRestoreScript() {
|
|
240
|
+
return materializeScript(exports.LIVE_RESTORE_SCRIPT_FILENAME, exports.LIVE_RESTORE_SCRIPT);
|
|
241
|
+
}
|
|
242
|
+
/** Materialize the Phase D delegate script and return its absolute path. */
|
|
243
|
+
function materializeLiveDelegateScript() {
|
|
244
|
+
return materializeScript(exports.LIVE_DELEGATE_SCRIPT_FILENAME, exports.LIVE_DELEGATE_SCRIPT);
|
|
245
|
+
}
|
|
246
|
+
/** Materialize the Phase C auto-popup script and return its absolute path. */
|
|
247
|
+
function materializeAutoPopupScript() {
|
|
248
|
+
return materializeScript(exports.AUTO_POPUP_SCRIPT_FILENAME, exports.AUTO_POPUP_SCRIPT);
|
|
249
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Server side of Issue #2317's session-scoped hooks and geometry hand-back.
|
|
4
|
+
*
|
|
5
|
+
* Two jobs, both keyed off one session name:
|
|
6
|
+
*
|
|
7
|
+
* - {@link ensureSessionHooks} reconciles the two OPT-IN `client-attached`
|
|
8
|
+
* hooks (Phase C's auto popup, Phase D's delegate-on-hand-attach) with what
|
|
9
|
+
* the environment asks for. Like #1623's key binding it CONVERGES: turning an
|
|
10
|
+
* option off removes the hook a previous run installed, rather than merely
|
|
11
|
+
* not installing it again.
|
|
12
|
+
* - {@link reconcileDelegatedGeometry} is the safety net the Issue asked a
|
|
13
|
+
* `client-detached` hook to be. tmux 3.5a does not fire that hook
|
|
14
|
+
* session-scoped (measured — see the table in `live-attach.ts`), so the
|
|
15
|
+
* restore runs from the status poll instead: every couple of seconds, for
|
|
16
|
+
* every session, "is this delegated while no human is looking at it?".
|
|
17
|
+
*
|
|
18
|
+
* Nothing here throws. All of it hangs off the status poll and off session
|
|
19
|
+
* creation, and neither may be failed by a convenience feature.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ensureSessionHooks = ensureSessionHooks;
|
|
23
|
+
exports.reconcileDelegatedGeometry = reconcileDelegatedGeometry;
|
|
24
|
+
exports.forgetSessionHooks = forgetSessionHooks;
|
|
25
|
+
const child_process_1 = require("child_process");
|
|
26
|
+
const util_1 = require("util");
|
|
27
|
+
const tmux_session_surface_1 = require("../session/tmux-session-surface");
|
|
28
|
+
const session_hook_scripts_1 = require("./session-hook-scripts");
|
|
29
|
+
const geometry_delegation_1 = require("./geometry-delegation");
|
|
30
|
+
const logger_1 = require("../logger");
|
|
31
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
32
|
+
const logger = (0, logger_1.createLogger)('tmux-session-hooks');
|
|
33
|
+
/** tmux calls here are interactive-latency, not long-running. */
|
|
34
|
+
const TMUX_TIMEOUT = 5000;
|
|
35
|
+
const ensured = globalThis.__cmEnsuredSessionHooks ?? (globalThis.__cmEnsuredSessionHooks = new Set());
|
|
36
|
+
/**
|
|
37
|
+
* Reconcile a session's opt-in `client-attached` hooks with the environment.
|
|
38
|
+
*
|
|
39
|
+
* Runs once per session per process; call it freely. Both hooks are removed when
|
|
40
|
+
* their option is off, so `CM_READ_MODE_AUTO_POPUP=on` followed by a restart
|
|
41
|
+
* without it leaves no hook behind.
|
|
42
|
+
*
|
|
43
|
+
* @param sessionName - Target session
|
|
44
|
+
*/
|
|
45
|
+
async function ensureSessionHooks(sessionName) {
|
|
46
|
+
if (!(0, tmux_session_surface_1.isCommandMateSession)(sessionName))
|
|
47
|
+
return;
|
|
48
|
+
if (ensured.has(sessionName))
|
|
49
|
+
return;
|
|
50
|
+
ensured.add(sessionName);
|
|
51
|
+
try {
|
|
52
|
+
if ((0, tmux_session_surface_1.isLiveAttachHookEnabled)() && (0, tmux_session_surface_1.isLiveAttachEligibleSession)(sessionName)) {
|
|
53
|
+
// The restore script rides along with the delegate one: a user whose
|
|
54
|
+
// server is down needs the manual way back, and materializing it here is
|
|
55
|
+
// the only moment we know the delegate path is in use at all.
|
|
56
|
+
(0, session_hook_scripts_1.materializeLiveRestoreScript)();
|
|
57
|
+
const args = (0, tmux_session_surface_1.buildInstallDelegateHookArgs)(sessionName, (0, session_hook_scripts_1.materializeLiveDelegateScript)());
|
|
58
|
+
if (args)
|
|
59
|
+
await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildRemoveDelegateHookArgs)(sessionName), {
|
|
63
|
+
timeout: TMUX_TIMEOUT,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if ((0, tmux_session_surface_1.isAutoPopupEnabled)()) {
|
|
67
|
+
const args = (0, tmux_session_surface_1.buildInstallAutoPopupHookArgs)(sessionName, (0, session_hook_scripts_1.materializeAutoPopupScript)());
|
|
68
|
+
if (args)
|
|
69
|
+
await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildRemoveAutoPopupHookArgs)(sessionName), {
|
|
73
|
+
timeout: TMUX_TIMEOUT,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
logger.debug('session-hooks:reconcile-failed', {
|
|
79
|
+
sessionName,
|
|
80
|
+
error: error instanceof Error ? error.message : String(error),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Take a delegated session's geometry back when no human is attached.
|
|
86
|
+
*
|
|
87
|
+
* The Phase D safety net. Restores unconditionally once the two conditions hold,
|
|
88
|
+
* because the sequence is idempotent — a session already at `manual` 200x1000
|
|
89
|
+
* with no `@cm_delegated` is left byte-identical by it.
|
|
90
|
+
*
|
|
91
|
+
* Also self-healing for a flag left behind by a CLI that was killed: the flag
|
|
92
|
+
* alone never keeps a window unpinned, because this runs whenever nobody is
|
|
93
|
+
* looking.
|
|
94
|
+
*
|
|
95
|
+
* @param sessionName - Target session
|
|
96
|
+
* @returns true when the geometry was handed back by this call
|
|
97
|
+
*/
|
|
98
|
+
async function reconcileDelegatedGeometry(sessionName) {
|
|
99
|
+
try {
|
|
100
|
+
if (!(await (0, geometry_delegation_1.isGeometryDelegated)(sessionName)))
|
|
101
|
+
return false;
|
|
102
|
+
if (await (0, geometry_delegation_1.hasHumanClientAttached)(sessionName))
|
|
103
|
+
return false;
|
|
104
|
+
for (const args of (0, tmux_session_surface_1.buildRestoreGeometryCommands)(sessionName)) {
|
|
105
|
+
await execFileAsync('tmux', args, { timeout: TMUX_TIMEOUT });
|
|
106
|
+
}
|
|
107
|
+
logger.info('session-hooks:geometry-restored', { sessionName });
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
logger.debug('session-hooks:geometry-restore-failed', {
|
|
112
|
+
sessionName,
|
|
113
|
+
error: error instanceof Error ? error.message : String(error),
|
|
114
|
+
});
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Forget a session's hook bookkeeping — call when it is known to be gone. */
|
|
119
|
+
function forgetSessionHooks(sessionName) {
|
|
120
|
+
ensured.delete(sessionName);
|
|
121
|
+
(0, geometry_delegation_1.forgetGeometryDelegation)(sessionName);
|
|
122
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase B of Issue #2317: publish the session's state ONTO the tmux session.
|
|
4
|
+
*
|
|
5
|
+
* Before this module, `running` / `waiting` / `ready` / `idle` existed only
|
|
6
|
+
* inside CommandMate. `tmux ls` showed a name and a window count, an attached
|
|
7
|
+
* status line showed tmux's stock clock, and an operator who wanted to know what
|
|
8
|
+
* an agent was doing had to open the web UI or run `commandmate ls`. Two writes
|
|
9
|
+
* per transition fix that:
|
|
10
|
+
*
|
|
11
|
+
* - **user options** (`@cm_status` and friends) — readable without attaching:
|
|
12
|
+
* `tmux ls -F '#{session_name} #{@cm_status}'`;
|
|
13
|
+
* - **a session-scoped `status-right`** — readable while attached, rendered
|
|
14
|
+
* from those same options so the line updates without being rewritten.
|
|
15
|
+
*
|
|
16
|
+
* ## Everything here is session-scoped, and that is the point
|
|
17
|
+
*
|
|
18
|
+
* `set-option -t <session>` writes the SESSION's option table. The tmux server's
|
|
19
|
+
* global table — which every session on the machine inherits, including ones
|
|
20
|
+
* CommandMate knows nothing about — is never touched, and
|
|
21
|
+
* `tests/unit/tmux/session-status-options-2317.test.ts` asserts that by
|
|
22
|
+
* inspecting the argv of every call this module makes. #1623's `bind-key` is the
|
|
23
|
+
* one global mutation CommandMate makes and it is not made here.
|
|
24
|
+
*
|
|
25
|
+
* ## Writes happen on TRANSITION, not on every poll
|
|
26
|
+
*
|
|
27
|
+
* `GET /api/worktrees` probes every tool of every worktree every couple of
|
|
28
|
+
* seconds. Setting five options on each of those polls would be a few hundred
|
|
29
|
+
* `execFile` round-trips a minute for a value that changes a few times an hour,
|
|
30
|
+
* so {@link publishSessionStatus} keeps the last published tuple per session and
|
|
31
|
+
* returns without touching tmux when nothing moved. The memo is keyed by session
|
|
32
|
+
* name and dropped by {@link forgetSessionStatus} when the session goes away.
|
|
33
|
+
*
|
|
34
|
+
* ## The opt-out converges, without a startup hook
|
|
35
|
+
*
|
|
36
|
+
* `CM_TMUX_STATUS=off` does not merely stop writing: the first status poll after
|
|
37
|
+
* the restart REMOVES the `@cm_*` options and the CommandMate `status-right`
|
|
38
|
+
* from each session it visits, once per session. That is the same "an opt-out
|
|
39
|
+
* that uninstalls" contract #1623 gave `CM_READ_MODE`, and it is done from the
|
|
40
|
+
* poll rather than from a startup sweep for two reasons — the poll already knows
|
|
41
|
+
* which sessions exist (a sweep would have to ask tmux again), and it keeps this
|
|
42
|
+
* feature from needing a wire into `server.ts`, whose startup path is
|
|
43
|
+
* deliberately a single dynamic import per module graph.
|
|
44
|
+
*
|
|
45
|
+
* ## Nothing here may ever throw
|
|
46
|
+
*
|
|
47
|
+
* This is a convenience surface hanging off the status poll. A tmux hiccup must
|
|
48
|
+
* not be able to fail the poll that the sidebar, `commandmate ls` and the header
|
|
49
|
+
* chip all read, so every entry point swallows its errors and logs at debug.
|
|
50
|
+
*/
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.publishSessionStatus = publishSessionStatus;
|
|
53
|
+
exports.ensureSessionStatusLine = ensureSessionStatusLine;
|
|
54
|
+
exports.clearSessionStatus = clearSessionStatus;
|
|
55
|
+
exports.forgetSessionStatus = forgetSessionStatus;
|
|
56
|
+
exports.publishedSessionCount = publishedSessionCount;
|
|
57
|
+
const child_process_1 = require("child_process");
|
|
58
|
+
const util_1 = require("util");
|
|
59
|
+
const tmux_session_surface_1 = require("../session/tmux-session-surface");
|
|
60
|
+
const logger_1 = require("../logger");
|
|
61
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
62
|
+
const logger = (0, logger_1.createLogger)('tmux-session-status');
|
|
63
|
+
/** tmux calls here are interactive-latency, not long-running. */
|
|
64
|
+
const TMUX_TIMEOUT = 5000;
|
|
65
|
+
const published = globalThis.__cmPublishedTmuxStatus ??
|
|
66
|
+
(globalThis.__cmPublishedTmuxStatus = new Map());
|
|
67
|
+
/** Sessions this process has already uninstalled the surface from. */
|
|
68
|
+
const cleared = globalThis.__cmClearedTmuxStatus ?? (globalThis.__cmClearedTmuxStatus = new Set());
|
|
69
|
+
/**
|
|
70
|
+
* Write one session's state onto its tmux session, if it changed.
|
|
71
|
+
*
|
|
72
|
+
* @param publication - Session identity plus the status word to publish
|
|
73
|
+
* @returns What was done, for tests and for the caller's logging
|
|
74
|
+
*/
|
|
75
|
+
async function publishSessionStatus(publication) {
|
|
76
|
+
const { sessionName, worktreeId, cliToolId, instanceId, status } = publication;
|
|
77
|
+
if (!(0, tmux_session_surface_1.isTmuxStatusEnabled)()) {
|
|
78
|
+
// The uninstall path. Once per session per process: `clearSessionStatus`
|
|
79
|
+
// issues six `execFile` calls, and repeating them on every poll of a server
|
|
80
|
+
// that has the surface turned off would be the cost the feature was turned
|
|
81
|
+
// off to avoid.
|
|
82
|
+
if (!cleared.has(sessionName)) {
|
|
83
|
+
cleared.add(sessionName);
|
|
84
|
+
await clearSessionStatus(sessionName);
|
|
85
|
+
}
|
|
86
|
+
return 'disabled';
|
|
87
|
+
}
|
|
88
|
+
const previous = published.get(sessionName);
|
|
89
|
+
if (previous &&
|
|
90
|
+
previous.status === status &&
|
|
91
|
+
previous.worktreeId === worktreeId &&
|
|
92
|
+
previous.cliToolId === cliToolId &&
|
|
93
|
+
previous.instanceId === instanceId) {
|
|
94
|
+
return 'unchanged';
|
|
95
|
+
}
|
|
96
|
+
const updated = (publication.now ?? new Date()).toISOString();
|
|
97
|
+
const writes = [
|
|
98
|
+
[tmux_session_surface_1.CM_STATUS_OPTION, status],
|
|
99
|
+
[tmux_session_surface_1.CM_WORKTREE_OPTION, worktreeId],
|
|
100
|
+
[tmux_session_surface_1.CM_TOOL_OPTION, cliToolId],
|
|
101
|
+
[tmux_session_surface_1.CM_INSTANCE_OPTION, instanceId],
|
|
102
|
+
[tmux_session_surface_1.CM_UPDATED_OPTION, updated],
|
|
103
|
+
];
|
|
104
|
+
try {
|
|
105
|
+
for (const [option, value] of writes) {
|
|
106
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildSetSessionOptionArgs)(sessionName, option, value), {
|
|
107
|
+
timeout: TMUX_TIMEOUT,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
published.set(sessionName, { status, worktreeId, cliToolId, instanceId });
|
|
111
|
+
// The line renders FROM the options above, so it is installed after them —
|
|
112
|
+
// a status-right referencing `#{@cm_status}` on a session that has none
|
|
113
|
+
// paints an empty pair of brackets until the first write lands.
|
|
114
|
+
await ensureSessionStatusLine(sessionName);
|
|
115
|
+
return 'written';
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// A session that was killed between the poll and this write is the ordinary
|
|
119
|
+
// case, not an incident. Drop the memo so the next live session under the
|
|
120
|
+
// same name republishes rather than being deduped against a dead one.
|
|
121
|
+
published.delete(sessionName);
|
|
122
|
+
logger.debug('session-status:write-failed', {
|
|
123
|
+
sessionName,
|
|
124
|
+
error: error instanceof Error ? error.message : String(error),
|
|
125
|
+
});
|
|
126
|
+
return 'error';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Install the session-scoped `status-right`, unless the session already has one.
|
|
131
|
+
*
|
|
132
|
+
* "Already has one" means a SESSION-scoped value, which is exactly what
|
|
133
|
+
* `show-options -t <session> status-right` reports: measured on tmux 3.5a, a
|
|
134
|
+
* session that never set it answers with empty stdout (the global value is not
|
|
135
|
+
* echoed), and one that did answers `status-right "…"`. So a user who
|
|
136
|
+
* customised this session in `.tmux.conf` — or who set it by hand — keeps their
|
|
137
|
+
* line, and everyone else gets CommandMate's.
|
|
138
|
+
*
|
|
139
|
+
* Idempotent: once installed, the value contains {@link CM_STATUS_RIGHT_FORMAT}
|
|
140
|
+
* and is recognised as ours, so a restart re-installs nothing.
|
|
141
|
+
*
|
|
142
|
+
* @param sessionName - Target session
|
|
143
|
+
* @returns true when the line is CommandMate's after this call
|
|
144
|
+
*/
|
|
145
|
+
async function ensureSessionStatusLine(sessionName) {
|
|
146
|
+
try {
|
|
147
|
+
const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildShowSessionOptionArgs)(sessionName, 'status-right'), { timeout: TMUX_TIMEOUT });
|
|
148
|
+
const existing = stdout.trim();
|
|
149
|
+
if (existing !== '' && !existing.includes(tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT)) {
|
|
150
|
+
logger.debug('session-status:status-right-user-owned', { sessionName, existing });
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (existing === '') {
|
|
154
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildSetStatusRightArgs)(sessionName, tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT), { timeout: TMUX_TIMEOUT });
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
logger.debug('session-status:status-right-failed', {
|
|
160
|
+
sessionName,
|
|
161
|
+
error: error instanceof Error ? error.message : String(error),
|
|
162
|
+
});
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Remove every `@cm_*` option and the session-scoped `status-right` we own.
|
|
168
|
+
*
|
|
169
|
+
* The `status-right` is only removed when it is still ours — a user who rebound
|
|
170
|
+
* it after us owns it now, and clobbering that would be the same rudeness
|
|
171
|
+
* {@link ensureSessionStatusLine} exists to avoid.
|
|
172
|
+
*
|
|
173
|
+
* @param sessionName - Target session
|
|
174
|
+
*/
|
|
175
|
+
async function clearSessionStatus(sessionName) {
|
|
176
|
+
published.delete(sessionName);
|
|
177
|
+
for (const option of tmux_session_surface_1.CM_SESSION_OPTIONS) {
|
|
178
|
+
try {
|
|
179
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildUnsetSessionOptionArgs)(sessionName, option), {
|
|
180
|
+
timeout: TMUX_TIMEOUT,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Unsetting an option that was never set exits non-zero on some builds.
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const { stdout } = await execFileAsync('tmux', (0, tmux_session_surface_1.buildShowSessionOptionArgs)(sessionName, 'status-right'), { timeout: TMUX_TIMEOUT });
|
|
189
|
+
if (stdout.includes(tmux_session_surface_1.CM_STATUS_RIGHT_FORMAT)) {
|
|
190
|
+
await execFileAsync('tmux', (0, tmux_session_surface_1.buildUnsetStatusRightArgs)(sessionName), {
|
|
191
|
+
timeout: TMUX_TIMEOUT,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Same reasoning as above: nothing here may fail a caller.
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Forget a session's published state without touching tmux.
|
|
201
|
+
*
|
|
202
|
+
* Called when a session is known to be gone. The next session created under the
|
|
203
|
+
* same name then publishes from scratch instead of being deduped against the
|
|
204
|
+
* dead one's last status.
|
|
205
|
+
*/
|
|
206
|
+
function forgetSessionStatus(sessionName) {
|
|
207
|
+
published.delete(sessionName);
|
|
208
|
+
cleared.delete(sessionName);
|
|
209
|
+
}
|
|
210
|
+
/** Test seam: how many sessions currently have a memoised publication. */
|
|
211
|
+
function publishedSessionCount() {
|
|
212
|
+
return published.size;
|
|
213
|
+
}
|