borgmcp 1.1.14 → 2.0.1
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/CONTRIBUTING.md +15 -0
- package/LICENSE +201 -33
- package/NOTICE +2 -0
- package/README.md +86 -37
- package/SECURITY.md +7 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +63 -1
- package/dist/agent-runtime.js.map +1 -0
- package/dist/assimilate-cmd.d.ts +96 -17
- package/dist/assimilate-cmd.d.ts.map +1 -0
- package/dist/assimilate-cmd.js +1396 -48
- package/dist/assimilate-cmd.js.map +1 -0
- package/dist/assimilate-deps.d.ts.map +1 -0
- package/dist/assimilate-deps.js +384 -3
- package/dist/assimilate-deps.js.map +1 -0
- package/dist/assimilate-guard.d.ts +5 -7
- package/dist/assimilate-guard.d.ts.map +1 -0
- package/dist/assimilate-guard.js +60 -2
- package/dist/assimilate-guard.js.map +1 -0
- package/dist/assimilate-welcome.d.ts +1 -1
- package/dist/assimilate-welcome.d.ts.map +1 -0
- package/dist/assimilate-welcome.js +32 -2
- package/dist/assimilate-welcome.js.map +1 -0
- package/dist/auth-env.d.ts +7 -50
- package/dist/auth-env.d.ts.map +1 -0
- package/dist/auth-env.js +22 -1
- package/dist/auth-env.js.map +1 -0
- package/dist/backends/launch-all-pastelist.d.ts.map +1 -0
- package/dist/backends/launch-all-pastelist.js +11 -4
- package/dist/backends/launch-all-pastelist.js.map +1 -0
- package/dist/backends/launch-all-tmux.d.ts.map +1 -0
- package/dist/backends/launch-all-tmux.js +49 -1
- package/dist/backends/launch-all-tmux.js.map +1 -0
- package/dist/backends/launch-all-windows.d.ts.map +1 -0
- package/dist/backends/launch-all-windows.js +86 -12
- package/dist/backends/launch-all-windows.js.map +1 -0
- package/dist/bare-launch-menu.d.ts.map +1 -0
- package/dist/bare-launch-menu.js +83 -6
- package/dist/bare-launch-menu.js.map +1 -0
- package/dist/claude-launch-args.d.ts.map +1 -0
- package/dist/claude-launch-args.js +34 -1
- package/dist/claude-launch-args.js.map +1 -0
- package/dist/claude.d.ts.map +1 -0
- package/dist/claude.js +486 -14
- package/dist/claude.js.map +1 -0
- package/dist/cleanup-cmd.d.ts +5 -5
- package/dist/cleanup-cmd.d.ts.map +1 -0
- package/dist/cleanup-cmd.js +453 -14
- package/dist/cleanup-cmd.js.map +1 -0
- package/dist/clear-rewake-core.d.ts.map +1 -0
- package/dist/clear-rewake-core.js +23 -2
- package/dist/clear-rewake-core.js.map +1 -0
- package/dist/clear-rewake.d.ts.map +1 -0
- package/dist/clear-rewake.js +19 -1
- package/dist/clear-rewake.js.map +1 -0
- package/dist/cli-help.d.ts +5 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +104 -56
- package/dist/cli-help.js.map +1 -0
- package/dist/cli-platform.d.ts.map +1 -0
- package/dist/cli-platform.js +106 -4
- package/dist/cli-platform.js.map +1 -0
- package/dist/cli-tool-approval.d.ts +84 -0
- package/dist/cli-tool-approval.d.ts.map +1 -0
- package/dist/cli-tool-approval.js +583 -0
- package/dist/cli-tool-approval.js.map +1 -0
- package/dist/codex-app-server.d.ts.map +1 -0
- package/dist/codex-app-server.js +228 -4
- package/dist/codex-app-server.js.map +1 -0
- package/dist/codex-app-wake.d.ts.map +1 -0
- package/dist/codex-app-wake.js +432 -2
- package/dist/codex-app-wake.js.map +1 -0
- package/dist/codex-launch.d.ts.map +1 -0
- package/dist/codex-launch.js +102 -2
- package/dist/codex-launch.js.map +1 -0
- package/dist/codex-remote.d.ts +6 -1
- package/dist/codex-remote.d.ts.map +1 -0
- package/dist/codex-remote.js +394 -1
- package/dist/codex-remote.js.map +1 -0
- package/dist/codex-wake-resolve.d.ts.map +1 -0
- package/dist/codex-wake-resolve.js +127 -1
- package/dist/codex-wake-resolve.js.map +1 -0
- package/dist/config-utils.d.ts +2 -2
- package/dist/config-utils.d.ts.map +1 -0
- package/dist/config-utils.js +766 -3
- package/dist/config-utils.js.map +1 -0
- package/dist/config.d.ts +98 -61
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +426 -1
- package/dist/config.js.map +1 -0
- package/dist/console-prefix.d.ts.map +1 -0
- package/dist/console-prefix.js +96 -1
- package/dist/console-prefix.js.map +1 -0
- package/dist/cube-name.d.ts.map +1 -0
- package/dist/cube-name.js +67 -1
- package/dist/cube-name.js.map +1 -0
- package/dist/cubes.d.ts +126 -18
- package/dist/cubes.d.ts.map +1 -0
- package/dist/cubes.js +412 -4
- package/dist/cubes.js.map +1 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +71 -1
- package/dist/debug.js.map +1 -0
- package/dist/direct-log.d.ts.map +1 -0
- package/dist/direct-log.js +11 -1
- package/dist/direct-log.js.map +1 -0
- package/dist/docs-sections.d.ts +11 -10
- package/dist/docs-sections.d.ts.map +1 -0
- package/dist/docs-sections.js +113 -3
- package/dist/docs-sections.js.map +1 -0
- package/dist/drone-lifecycle.d.ts +5 -21
- package/dist/drone-lifecycle.d.ts.map +1 -0
- package/dist/drone-lifecycle.js +57 -8
- package/dist/drone-lifecycle.js.map +1 -0
- package/dist/drone-management.d.ts +29 -0
- package/dist/drone-management.d.ts.map +1 -0
- package/dist/drone-management.js +109 -0
- package/dist/drone-management.js.map +1 -0
- package/dist/ensure-mcp-config.d.ts.map +1 -0
- package/dist/ensure-mcp-config.js +36 -1
- package/dist/ensure-mcp-config.js.map +1 -0
- package/dist/evict-drone.d.ts +10 -2
- package/dist/evict-drone.d.ts.map +1 -0
- package/dist/evict-drone.js +60 -1
- package/dist/evict-drone.js.map +1 -0
- package/dist/gc-orphan-inboxes.d.ts.map +1 -0
- package/dist/gc-orphan-inboxes.js +177 -1
- package/dist/gc-orphan-inboxes.js.map +1 -0
- package/dist/inbox-monitor.d.ts +1 -1
- package/dist/inbox-monitor.d.ts.map +1 -0
- package/dist/inbox-monitor.js +856 -3
- package/dist/inbox-monitor.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1034 -37
- package/dist/index.js.map +1 -0
- package/dist/launch-all-cmd.d.ts.map +1 -0
- package/dist/launch-all-cmd.js +377 -37
- package/dist/launch-all-cmd.js.map +1 -0
- package/dist/launch-all-command.d.ts.map +1 -0
- package/dist/launch-all-command.js +24 -1
- package/dist/launch-all-command.js.map +1 -0
- package/dist/launch-all-deps.d.ts +3 -8
- package/dist/launch-all-deps.d.ts.map +1 -0
- package/dist/launch-all-deps.js +99 -1
- package/dist/launch-all-deps.js.map +1 -0
- package/dist/launch-all-discovery.d.ts +1 -0
- package/dist/launch-all-discovery.d.ts.map +1 -0
- package/dist/launch-all-discovery.js +90 -4
- package/dist/launch-all-discovery.js.map +1 -0
- package/dist/launch-all-locks.d.ts.map +1 -0
- package/dist/launch-all-locks.js +54 -1
- package/dist/launch-all-locks.js.map +1 -0
- package/dist/launch-gate.d.ts +2 -2
- package/dist/launch-gate.d.ts.map +1 -0
- package/dist/launch-gate.js +73 -1
- package/dist/launch-gate.js.map +1 -0
- package/dist/lifecycle-log-guard.d.ts.map +1 -0
- package/dist/lifecycle-log-guard.js +93 -2
- package/dist/lifecycle-log-guard.js.map +1 -0
- package/dist/list-roles-render.d.ts.map +1 -0
- package/dist/list-roles-render.js +40 -6
- package/dist/list-roles-render.js.map +1 -0
- package/dist/local-log-routing.d.ts +19 -0
- package/dist/local-log-routing.d.ts.map +1 -0
- package/dist/local-log-routing.js +67 -0
- package/dist/local-log-routing.js.map +1 -0
- package/dist/local-manage-tool-result.d.ts +8 -0
- package/dist/local-manage-tool-result.d.ts.map +1 -0
- package/dist/local-manage-tool-result.js +10 -0
- package/dist/local-manage-tool-result.js.map +1 -0
- package/dist/local-server-cursor.d.ts +34 -0
- package/dist/local-server-cursor.d.ts.map +1 -0
- package/dist/local-server-cursor.js +151 -0
- package/dist/local-server-cursor.js.map +1 -0
- package/dist/log-audit.d.ts.map +1 -0
- package/dist/log-audit.js +194 -3
- package/dist/log-audit.js.map +1 -0
- package/dist/log-stream.d.ts +31 -18
- package/dist/log-stream.d.ts.map +1 -0
- package/dist/log-stream.js +1214 -12
- package/dist/log-stream.js.map +1 -0
- package/dist/model-presets.d.ts.map +1 -0
- package/dist/model-presets.js +19 -1
- package/dist/model-presets.js.map +1 -0
- package/dist/name-validator.d.ts.map +1 -0
- package/dist/name-validator.js +22 -1
- package/dist/name-validator.js.map +1 -0
- package/dist/opencode-drone.d.ts.map +1 -0
- package/dist/opencode-drone.js +438 -4
- package/dist/opencode-drone.js.map +1 -0
- package/dist/opencode-plugin.d.ts +1 -1
- package/dist/opencode-plugin.d.ts.map +1 -0
- package/dist/opencode-plugin.js +29 -4
- package/dist/opencode-plugin.js.map +1 -0
- package/dist/parse-assimilate-args.d.ts +1 -1
- package/dist/parse-assimilate-args.d.ts.map +1 -0
- package/dist/parse-assimilate-args.js +125 -1
- package/dist/parse-assimilate-args.js.map +1 -0
- package/dist/parse-launch-all-args.d.ts.map +1 -0
- package/dist/parse-launch-all-args.js +70 -1
- package/dist/parse-launch-all-args.js.map +1 -0
- package/dist/postinstall-banner.d.ts.map +1 -0
- package/dist/postinstall-banner.js +27 -2
- package/dist/postinstall-banner.js.map +1 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +32 -5
- package/dist/postinstall.js.map +1 -0
- package/dist/readiness-probe.d.ts.map +1 -0
- package/dist/readiness-probe.js +9 -1
- package/dist/readiness-probe.js.map +1 -0
- package/dist/regen-format.d.ts.map +1 -0
- package/dist/regen-format.js +545 -13
- package/dist/regen-format.js.map +1 -0
- package/dist/regen.d.ts.map +1 -0
- package/dist/regen.js +141 -5
- package/dist/regen.js.map +1 -0
- package/dist/remote-client.d.ts +65 -175
- package/dist/remote-client.d.ts.map +1 -0
- package/dist/remote-client.js +942 -1
- package/dist/remote-client.js.map +1 -0
- package/dist/reset-local-seat-cmd.d.ts +50 -0
- package/dist/reset-local-seat-cmd.d.ts.map +1 -0
- package/dist/reset-local-seat-cmd.js +169 -0
- package/dist/reset-local-seat-cmd.js.map +1 -0
- package/dist/role-match.d.ts.map +1 -0
- package/dist/role-match.js +23 -1
- package/dist/role-match.js.map +1 -0
- package/dist/role-resolver.d.ts.map +1 -0
- package/dist/role-resolver.js +60 -1
- package/dist/role-resolver.js.map +1 -0
- package/dist/roster-render.d.ts.map +1 -0
- package/dist/roster-render.js +121 -3
- package/dist/roster-render.js.map +1 -0
- package/dist/seat-probe.d.ts +32 -13
- package/dist/seat-probe.d.ts.map +1 -0
- package/dist/seat-probe.js +78 -1
- package/dist/seat-probe.js.map +1 -0
- package/dist/seat-store.d.ts +76 -0
- package/dist/seat-store.d.ts.map +1 -0
- package/dist/seat-store.js +309 -0
- package/dist/seat-store.js.map +1 -0
- package/dist/seats.d.ts +303 -0
- package/dist/seats.d.ts.map +1 -0
- package/dist/seats.js +551 -0
- package/dist/seats.js.map +1 -0
- package/dist/self-path.d.ts +27 -0
- package/dist/self-path.d.ts.map +1 -0
- package/dist/self-path.js +43 -0
- package/dist/self-path.js.map +1 -0
- package/dist/server-endpoint.d.ts +9 -0
- package/dist/server-endpoint.d.ts.map +1 -0
- package/dist/server-endpoint.js +38 -0
- package/dist/server-endpoint.js.map +1 -0
- package/dist/server-errors.d.ts +50 -0
- package/dist/server-errors.d.ts.map +1 -0
- package/dist/server-errors.js +79 -0
- package/dist/server-errors.js.map +1 -0
- package/dist/server-handshake.d.ts +197 -0
- package/dist/server-handshake.d.ts.map +1 -0
- package/dist/server-handshake.js +505 -0
- package/dist/server-handshake.js.map +1 -0
- package/dist/server-response.d.ts +3 -0
- package/dist/server-response.d.ts.map +1 -0
- package/dist/server-response.js +67 -0
- package/dist/server-response.js.map +1 -0
- package/dist/server-trust.d.ts +14 -0
- package/dist/server-trust.d.ts.map +1 -0
- package/dist/server-trust.js +225 -0
- package/dist/server-trust.js.map +1 -0
- package/dist/setup-confirm.d.ts +3 -3
- package/dist/setup-confirm.d.ts.map +1 -0
- package/dist/setup-confirm.js +126 -2
- package/dist/setup-confirm.js.map +1 -0
- package/dist/setup.d.ts +5 -3
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +169 -46
- package/dist/setup.js.map +1 -0
- package/dist/shell-escape.d.ts.map +1 -0
- package/dist/shell-escape.js +22 -1
- package/dist/shell-escape.js.map +1 -0
- package/dist/spawn.d.ts +2 -2
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +29 -10
- package/dist/spawn.js.map +1 -0
- package/dist/startup-services.d.ts +0 -1
- package/dist/startup-services.d.ts.map +1 -0
- package/dist/startup-services.js +26 -1
- package/dist/startup-services.js.map +1 -0
- package/dist/stream-owner.d.ts +6 -2
- package/dist/stream-owner.d.ts.map +1 -0
- package/dist/stream-owner.js +547 -2
- package/dist/stream-owner.js.map +1 -0
- package/dist/stream-status.d.ts +1 -1
- package/dist/stream-status.d.ts.map +1 -0
- package/dist/stream-status.js +268 -3
- package/dist/stream-status.js.map +1 -0
- package/dist/sync-roles-render.d.ts.map +1 -0
- package/dist/sync-roles-render.js +118 -3
- package/dist/sync-roles-render.js.map +1 -0
- package/dist/sync.d.ts +1 -1
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +286 -22
- package/dist/sync.js.map +1 -0
- package/dist/terminal-title.d.ts.map +1 -0
- package/dist/terminal-title.js +68 -1
- package/dist/terminal-title.js.map +1 -0
- package/dist/token-store.d.ts +17 -111
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +81 -1
- package/dist/token-store.js.map +1 -0
- package/dist/tool-manifest.d.ts +4 -8
- package/dist/tool-manifest.d.ts.map +1 -0
- package/dist/tool-manifest.js +554 -1
- package/dist/tool-manifest.js.map +1 -0
- package/dist/tool-scope.d.ts +8 -12
- package/dist/tool-scope.d.ts.map +1 -0
- package/dist/tool-scope.js +97 -1
- package/dist/tool-scope.js.map +1 -0
- package/dist/types.d.ts +1 -5
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/unknown-subcommand.d.ts +1 -1
- package/dist/unknown-subcommand.d.ts.map +1 -0
- package/dist/unknown-subcommand.js +37 -1
- package/dist/unknown-subcommand.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +78 -2
- package/dist/version.js.map +1 -0
- package/dist/working-repo.d.ts.map +1 -0
- package/dist/working-repo.js +81 -1
- package/dist/working-repo.js.map +1 -0
- package/dist/worktree-lifecycle.d.ts.map +1 -0
- package/dist/worktree-lifecycle.js +205 -2
- package/dist/worktree-lifecycle.js.map +1 -0
- package/docs/EXTRACTION_PROVENANCE.md +40 -0
- package/docs/LOCAL_SERVER.md +103 -0
- package/docs/RELEASING.md +120 -0
- package/package.json +52 -34
- package/src/agent-runtime.ts +69 -0
- package/src/assimilate-cmd.ts +1864 -0
- package/src/assimilate-deps.ts +444 -0
- package/src/assimilate-guard.ts +84 -0
- package/src/assimilate-welcome.ts +39 -0
- package/src/auth-env.ts +21 -0
- package/src/backends/launch-all-pastelist.ts +18 -0
- package/src/backends/launch-all-tmux.ts +75 -0
- package/src/backends/launch-all-windows.ts +110 -0
- package/src/bare-launch-menu.ts +148 -0
- package/src/claude-launch-args.ts +35 -0
- package/src/claude.ts +561 -0
- package/src/cleanup-cmd.ts +581 -0
- package/src/clear-rewake-core.ts +34 -0
- package/src/clear-rewake.ts +18 -0
- package/src/cli-help.ts +116 -0
- package/src/cli-platform.ts +127 -0
- package/src/cli-tool-approval.ts +716 -0
- package/src/codex-app-server.ts +238 -0
- package/src/codex-app-wake.ts +512 -0
- package/src/codex-launch.ts +140 -0
- package/src/codex-remote.ts +500 -0
- package/src/codex-wake-resolve.ts +155 -0
- package/src/config-utils.ts +811 -0
- package/src/config.ts +595 -0
- package/src/console-prefix.ts +99 -0
- package/src/cube-name.ts +69 -0
- package/src/cubes.ts +583 -0
- package/src/debug.ts +73 -0
- package/src/direct-log.ts +9 -0
- package/src/docs-sections.ts +129 -0
- package/src/drone-lifecycle.ts +62 -0
- package/src/drone-management.ts +162 -0
- package/src/ensure-mcp-config.ts +54 -0
- package/src/evict-drone.ts +82 -0
- package/src/gc-orphan-inboxes.ts +229 -0
- package/src/inbox-monitor.ts +1005 -0
- package/src/index.ts +1201 -0
- package/src/launch-all-cmd.ts +450 -0
- package/src/launch-all-command.ts +30 -0
- package/src/launch-all-deps.ts +188 -0
- package/src/launch-all-discovery.ts +118 -0
- package/src/launch-all-locks.ts +74 -0
- package/src/launch-gate.ts +80 -0
- package/src/lifecycle-log-guard.ts +144 -0
- package/src/list-roles-render.ts +52 -0
- package/src/local-log-routing.ts +106 -0
- package/src/local-manage-tool-result.ts +10 -0
- package/src/local-server-cursor.ts +188 -0
- package/src/log-audit.ts +207 -0
- package/src/log-stream.ts +1505 -0
- package/src/model-presets.ts +22 -0
- package/src/name-validator.ts +23 -0
- package/src/opencode-drone.ts +528 -0
- package/src/opencode-plugin.ts +38 -0
- package/src/parse-assimilate-args.ts +125 -0
- package/src/parse-launch-all-args.ts +100 -0
- package/src/postinstall-banner.ts +37 -0
- package/src/postinstall.ts +36 -0
- package/src/readiness-probe.ts +12 -0
- package/src/regen-format.ts +651 -0
- package/src/regen.ts +150 -0
- package/src/remote-client.ts +1379 -0
- package/src/reset-local-seat-cmd.ts +227 -0
- package/src/role-match.ts +29 -0
- package/src/role-resolver.ts +93 -0
- package/src/roster-render.ts +196 -0
- package/src/seat-probe.ts +115 -0
- package/src/seat-store.ts +333 -0
- package/src/seats.ts +741 -0
- package/src/self-path.ts +51 -0
- package/src/server-endpoint.ts +38 -0
- package/src/server-errors.ts +93 -0
- package/src/server-handshake.ts +783 -0
- package/src/server-response.ts +76 -0
- package/src/server-trust.ts +245 -0
- package/src/setup-confirm.ts +171 -0
- package/src/setup.ts +186 -0
- package/src/shell-escape.ts +22 -0
- package/src/spawn.ts +31 -0
- package/src/startup-services.ts +36 -0
- package/src/stream-owner.ts +686 -0
- package/src/stream-status.ts +337 -0
- package/src/sync-roles-render.ts +163 -0
- package/src/sync.ts +363 -0
- package/src/terminal-title.ts +76 -0
- package/src/token-store.ts +102 -0
- package/src/tool-manifest.ts +610 -0
- package/src/tool-scope.ts +110 -0
- package/src/types.ts +5 -0
- package/src/unknown-subcommand.ts +35 -0
- package/src/version.ts +82 -0
- package/src/working-repo.ts +99 -0
- package/src/worktree-lifecycle.ts +254 -0
- package/dist/auth-recovery.d.ts +0 -33
- package/dist/auth-recovery.js +0 -1
- package/dist/auth.d.ts +0 -103
- package/dist/auth.js +0 -39
- package/dist/device-auth.d.ts +0 -75
- package/dist/device-auth.js +0 -1
- package/dist/drone-address.d.ts +0 -26
- package/dist/drone-address.js +0 -1
- package/dist/get-started.d.ts +0 -20
- package/dist/get-started.js +0 -2
- package/dist/health-beat.d.ts +0 -134
- package/dist/health-beat.js +0 -1
- package/dist/role-section.d.ts +0 -110
- package/dist/role-section.js +0 -8
- package/dist/setup-action.d.ts +0 -20
- package/dist/setup-action.js +0 -1
- package/dist/stale-version-check.d.ts +0 -40
- package/dist/stale-version-check.js +0 -1
- package/dist/subscription-retry.d.ts +0 -40
- package/dist/subscription-retry.js +0 -1
- package/dist/templates.d.ts +0 -107
- package/dist/templates.js +0 -359
- package/dist/token-crypto.d.ts +0 -50
- package/dist/token-crypto.js +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// gh#556 Part 2 — windows backend (explicit `--mode windows` only, spec §4.2).
|
|
2
|
+
// Opens each worktree as a new terminal window/tab. macOS: iTerm/Terminal via
|
|
3
|
+
// osascript. Linux: $BORG_TERMINAL / $TERMINAL / probed emulator. No shared
|
|
4
|
+
// session, so no post-launch attach. Hard-fails if no compatible terminal found.
|
|
5
|
+
|
|
6
|
+
import type { DroneCandidate } from '../launch-all-discovery.js';
|
|
7
|
+
import type { LaunchAllDeps } from '../launch-all-deps.js';
|
|
8
|
+
import { buildLaunchCommand } from '../launch-all-command.js';
|
|
9
|
+
import { writeLockMarker } from '../launch-all-locks.js';
|
|
10
|
+
|
|
11
|
+
export interface WindowsOpts {
|
|
12
|
+
borgPath: string;
|
|
13
|
+
platform: NodeJS.Platform;
|
|
14
|
+
launchedAtISO: string;
|
|
15
|
+
/** Stagger between drone launches (ms) to avoid the rate limiter; 0 disables. */
|
|
16
|
+
launchDelayMs: number;
|
|
17
|
+
/** Injectable sleep (real setTimeout in prod; no-op spy in tests). */
|
|
18
|
+
sleep: (ms: number) => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** AppleScript string-literal escaping (backslash + double-quote). */
|
|
22
|
+
function appleScriptEscape(s: string): string {
|
|
23
|
+
return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class NoTerminalError extends Error {}
|
|
27
|
+
|
|
28
|
+
/** macOS: open each candidate in iTerm or Terminal via osascript. */
|
|
29
|
+
async function launchMacOS(candidates: DroneCandidate[], opts: WindowsOpts, deps: LaunchAllDeps): Promise<void> {
|
|
30
|
+
const hasITerm = deps.pathExists('/Applications/iTerm.app');
|
|
31
|
+
const hasTerminal = deps.pathExists('/Applications/Terminal.app');
|
|
32
|
+
if (!hasITerm && !hasTerminal) {
|
|
33
|
+
throw new NoTerminalError(
|
|
34
|
+
'borg launch-all: --mode windows requires a compatible terminal app.\n' +
|
|
35
|
+
'Not found: iTerm.app, Terminal.app\n' +
|
|
36
|
+
'Install iTerm2 (https://iterm2.com) or use --mode tmux (brew install tmux).\n'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
40
|
+
const c = candidates[i];
|
|
41
|
+
if (i > 0 && opts.launchDelayMs > 0) await opts.sleep(opts.launchDelayMs); // rate-limit stagger
|
|
42
|
+
const cmd = buildLaunchCommand(c.worktreeDir, opts.borgPath);
|
|
43
|
+
const script = hasITerm
|
|
44
|
+
? `tell application "iTerm"\n tell current window to create tab with default profile command "${appleScriptEscape(cmd)}"\nend tell`
|
|
45
|
+
: `tell application "Terminal"\n do script "${appleScriptEscape(cmd)}"\n activate\nend tell`;
|
|
46
|
+
deps.runSync('osascript', ['-e', script]);
|
|
47
|
+
writeLockMarker(deps, c.cubeId, c.droneLabel, c.worktreeDir, opts.launchedAtISO);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Linux: open each candidate in the first available terminal emulator. */
|
|
52
|
+
async function launchLinux(candidates: DroneCandidate[], opts: WindowsOpts, deps: LaunchAllDeps): Promise<void> {
|
|
53
|
+
const explicit = deps.getEnv('BORG_TERMINAL') || deps.getEnv('TERMINAL');
|
|
54
|
+
const probe = ['gnome-terminal', 'konsole', 'kitty', 'wezterm', 'xterm'];
|
|
55
|
+
let term: string | undefined = explicit;
|
|
56
|
+
if (!term) {
|
|
57
|
+
for (const name of probe) {
|
|
58
|
+
if (deps.runSyncExitCode('which', [name]) === 0) {
|
|
59
|
+
term = name;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!term) {
|
|
65
|
+
throw new NoTerminalError(
|
|
66
|
+
'borg launch-all: --mode windows requires a terminal emulator.\n' +
|
|
67
|
+
'Not found. Set $BORG_TERMINAL=<path> or use --mode tmux.\n'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
71
|
+
const c = candidates[i];
|
|
72
|
+
if (i > 0 && opts.launchDelayMs > 0) await opts.sleep(opts.launchDelayMs); // rate-limit stagger
|
|
73
|
+
const cmd = buildLaunchCommand(c.worktreeDir, opts.borgPath, { keepOpenOnFail: true });
|
|
74
|
+
// `<term> -e sh -c '<cmd>'` opens a new window running the command.
|
|
75
|
+
deps.runSync(term, ['-e', 'sh', '-c', cmd]);
|
|
76
|
+
writeLockMarker(deps, c.cubeId, c.droneLabel, c.worktreeDir, opts.launchedAtISO);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Control char (incl. newline) in a worktree path. SR f94bb3fe + Coordinator
|
|
82
|
+
* c6370c41 fold-in: a newline in the path breaks the macOS osascript AppleScript
|
|
83
|
+
* string literal (parse error). Reject such paths up front (the user's own path;
|
|
84
|
+
* pathological) — fail-loud + skip, never silently mangle. Applies to both
|
|
85
|
+
* platforms defensively (the tmux primary handles control chars fine via
|
|
86
|
+
* shellEscape + array-args, so this guard is windows-backend-specific).
|
|
87
|
+
*/
|
|
88
|
+
const CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
|
|
89
|
+
|
|
90
|
+
export async function runWindowsBackend(
|
|
91
|
+
candidates: DroneCandidate[],
|
|
92
|
+
opts: WindowsOpts,
|
|
93
|
+
deps: LaunchAllDeps
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
const safe = candidates.filter((c) => {
|
|
96
|
+
if (CONTROL_CHAR_RE.test(c.worktreeDir)) {
|
|
97
|
+
deps.stderr(
|
|
98
|
+
`skipping ${c.droneLabel} (${JSON.stringify(c.worktreeDir)}): worktree path contains a control ` +
|
|
99
|
+
`character — unsafe for --mode windows; use --mode tmux instead.\n`
|
|
100
|
+
);
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
});
|
|
105
|
+
if (opts.platform === 'darwin') {
|
|
106
|
+
await launchMacOS(safe, opts, deps);
|
|
107
|
+
} else {
|
|
108
|
+
await launchLinux(safe, opts, deps);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gh#853 — bare `borg` (no-args) interactive launch menu.
|
|
3
|
+
*
|
|
4
|
+
* When `borg` is run with NO arguments in a TTY, offer a small launch selector
|
|
5
|
+
* instead of launching immediately:
|
|
6
|
+
* 1. Launch (default) — the configured agent (Enter selects).
|
|
7
|
+
* 2. Launch with <other> instead — the OTHER installed agent, ONE-SHOT
|
|
8
|
+
* (does NOT persist the preference).
|
|
9
|
+
* 3. Launch all — runLaunchAll for the active cube.
|
|
10
|
+
*
|
|
11
|
+
* The option-set, the selection→action mapping, and the show/collapse decision
|
|
12
|
+
* are pure functions so they're unit-testable without a real TTY. claude.ts
|
|
13
|
+
* main() is thin glue: it computes the inputs (default cli, other-installed cli,
|
|
14
|
+
* launch-all targets), gates on shouldShowLaunchMenu, runs the orchestrator with
|
|
15
|
+
* the real readline prompt, then dispatches the returned action.
|
|
16
|
+
*
|
|
17
|
+
* Load-bearing safety: TTY-only + bare-args-only (shouldShowLaunchMenu) so every
|
|
18
|
+
* scripted/programmatic `borg` and every explicit subcommand/flag is untouched.
|
|
19
|
+
*/
|
|
20
|
+
import type { BorgCli } from './cubes.js';
|
|
21
|
+
|
|
22
|
+
export type LaunchMenuAction =
|
|
23
|
+
| { kind: 'launch'; cli: BorgCli }
|
|
24
|
+
| { kind: 'launch-all' };
|
|
25
|
+
|
|
26
|
+
export interface LaunchMenuOption {
|
|
27
|
+
/** The keystroke that selects this option (sequential: '1', '2', …). */
|
|
28
|
+
key: string;
|
|
29
|
+
label: string;
|
|
30
|
+
action: LaunchMenuAction;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface LaunchMenuInputs {
|
|
34
|
+
/** The configured/resolved current agent (option 1). */
|
|
35
|
+
defaultCli: BorgCli;
|
|
36
|
+
/** All installed agents that are NOT the default, in display order. */
|
|
37
|
+
otherInstalledClis: BorgCli[];
|
|
38
|
+
/** True iff there's an active cube with >=1 discoverable drone (option 3). */
|
|
39
|
+
hasLaunchAllTargets: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const PRETTY: Record<BorgCli, string> = { claude: 'Claude', codex: 'Codex', opencode: 'OpenCode' };
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gate: the menu fires ONLY for bare `borg` (no args) in a TTY. Any explicit
|
|
46
|
+
* subcommand/flag, or a non-TTY (piped/scripted/CI) invocation, falls straight
|
|
47
|
+
* through to the existing default launch — no menu, no behavior change.
|
|
48
|
+
*/
|
|
49
|
+
export function shouldShowLaunchMenu(args: {
|
|
50
|
+
extraArgs: string[];
|
|
51
|
+
stdinIsTTY: boolean;
|
|
52
|
+
stdoutIsTTY: boolean;
|
|
53
|
+
}): boolean {
|
|
54
|
+
return args.extraArgs.length === 0 && args.stdinIsTTY && args.stdoutIsTTY;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function explicitCliLaunchHint(args: {
|
|
58
|
+
explicitCli: BorgCli | undefined;
|
|
59
|
+
stdinIsTTY: boolean;
|
|
60
|
+
stdoutIsTTY: boolean;
|
|
61
|
+
hasActiveCube: boolean;
|
|
62
|
+
hasLaunchAllTargets: boolean;
|
|
63
|
+
}): string | null {
|
|
64
|
+
if (!args.explicitCli || !args.stdinIsTTY || !args.stdoutIsTTY) return null;
|
|
65
|
+
if (!args.hasActiveCube || !args.hasLaunchAllTargets) return null;
|
|
66
|
+
return `borg --cli ${args.explicitCli} launches ${PRETTY[args.explicitCli]} directly; use bare borg for the launch menu or borg launch-all --cli ${args.explicitCli} for all drone worktrees.\n`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function shouldResolveExplicitCliLaunchHintTargets(args: {
|
|
70
|
+
explicitCli: BorgCli | undefined;
|
|
71
|
+
stdinIsTTY: boolean;
|
|
72
|
+
stdoutIsTTY: boolean;
|
|
73
|
+
hasActiveCube: boolean;
|
|
74
|
+
}): boolean {
|
|
75
|
+
return Boolean(args.explicitCli && args.stdinIsTTY && args.stdoutIsTTY && args.hasActiveCube);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The context-filtered option set. Option 1 is always present; options 2/3 are
|
|
80
|
+
* included only when applicable. Keys are sequential with no gaps, so a hidden
|
|
81
|
+
* middle option never produces a "1) … 3) …" gap menu.
|
|
82
|
+
*/
|
|
83
|
+
export function buildLaunchMenuOptions(inputs: LaunchMenuInputs): LaunchMenuOption[] {
|
|
84
|
+
const options: LaunchMenuOption[] = [
|
|
85
|
+
{
|
|
86
|
+
key: '1',
|
|
87
|
+
label: `Launch (default · ${PRETTY[inputs.defaultCli]})`,
|
|
88
|
+
action: { kind: 'launch', cli: inputs.defaultCli },
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
for (const cli of inputs.otherInstalledClis) {
|
|
92
|
+
options.push({
|
|
93
|
+
key: String(options.length + 1),
|
|
94
|
+
label: `Launch with ${PRETTY[cli]} (one-shot)`,
|
|
95
|
+
action: { kind: 'launch', cli },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (inputs.hasLaunchAllTargets) {
|
|
99
|
+
options.push({
|
|
100
|
+
key: String(options.length + 1),
|
|
101
|
+
label: "Launch all (this cube's drone worktrees)",
|
|
102
|
+
action: { kind: 'launch-all' },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return options;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Map a raw prompt answer to an action. Empty/Enter → option 1 (default). */
|
|
109
|
+
export function resolveLaunchMenuChoice(
|
|
110
|
+
options: LaunchMenuOption[],
|
|
111
|
+
rawInput: string
|
|
112
|
+
): { ok: true; action: LaunchMenuAction } | { ok: false } {
|
|
113
|
+
const trimmed = rawInput.trim();
|
|
114
|
+
if (trimmed === '') return { ok: true, action: options[0].action };
|
|
115
|
+
const match = options.find((o) => o.key === trimmed);
|
|
116
|
+
return match ? { ok: true, action: match.action } : { ok: false };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The rendered menu text (prompt suffix `[1]:` defaults to option 1 on Enter). */
|
|
120
|
+
export function renderLaunchMenu(options: LaunchMenuOption[]): string {
|
|
121
|
+
const lines = options.map((o) => ` ${o.key}) ${o.label}`);
|
|
122
|
+
return `borg — how do you want to launch?\n${lines.join('\n')}\n[1]: `;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Orchestrate the menu with an injected readline-style prompt. Collapses to a
|
|
127
|
+
* direct default launch (no render, no prompt) when only option 1 applies.
|
|
128
|
+
* Re-prompts on invalid input up to `maxAttempts`, then falls back to the safe
|
|
129
|
+
* default (option 1) so a fat-fingered session still launches.
|
|
130
|
+
*/
|
|
131
|
+
export async function runBareLaunchMenu(
|
|
132
|
+
inputs: LaunchMenuInputs,
|
|
133
|
+
prompt: (message: string) => Promise<string>,
|
|
134
|
+
opts: { maxAttempts?: number; warn?: (message: string) => void } = {}
|
|
135
|
+
): Promise<LaunchMenuAction> {
|
|
136
|
+
const options = buildLaunchMenuOptions(inputs);
|
|
137
|
+
if (options.length === 1) return options[0].action; // collapse — never a 1-item menu
|
|
138
|
+
|
|
139
|
+
const maxAttempts = opts.maxAttempts ?? 3;
|
|
140
|
+
const menu = renderLaunchMenu(options);
|
|
141
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
142
|
+
const raw = await prompt(attempt === 0 ? menu : `Invalid choice.\n${menu}`);
|
|
143
|
+
const res = resolveLaunchMenuChoice(options, raw);
|
|
144
|
+
if (res.ok) return res.action;
|
|
145
|
+
opts.warn?.(`invalid launch-menu selection: ${JSON.stringify(raw.trim())}`);
|
|
146
|
+
}
|
|
147
|
+
return options[0].action; // exhausted → safe default
|
|
148
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gh#702 — borg-launched Claude Code drones auto-allow the borg MCP
|
|
3
|
+
* coordination tools so a drone never prompts on borg_regen / borg_log /
|
|
4
|
+
* borg_ack / etc. mid-loop.
|
|
5
|
+
*
|
|
6
|
+
* SCOPED, by deliberate design (Option A, per-launch — avoids the gh#844
|
|
7
|
+
* settings-mutation/consent class):
|
|
8
|
+
* - ONLY `mcp__borg__*` is auto-allowed. Bash, file edits (Read/Write/Edit),
|
|
9
|
+
* web (WebFetch/WebSearch), and everything else STILL prompt. This is an
|
|
10
|
+
* allowlist ADD, NOT `--dangerously-skip-permissions` and NOT a blanket
|
|
11
|
+
* allow.
|
|
12
|
+
* - Applied ONLY by the borg launcher (a per-invocation CLI flag) — there is
|
|
13
|
+
* NO persistent user-settings write, so no consent gate is involved.
|
|
14
|
+
* - claude only. Codex parity is a separate follow-up (different permission
|
|
15
|
+
* model) — intentionally not handled here.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** The allowlist pattern matching every tool from the `borg` MCP server. */
|
|
19
|
+
export const BORG_MCP_ALLOWED_TOOLS = 'mcp__borg__*';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Build the argv for a borg-launched `claude` process: the user's passthrough
|
|
23
|
+
* args.
|
|
24
|
+
*
|
|
25
|
+
* ORDER IS LOAD-BEARING (CR blocker 0e5c697e): `--allowedTools` is a VARIADIC
|
|
26
|
+
* option (`<tools...>`, a space-separated list), so it greedily consumes every
|
|
27
|
+
* following non-flag argv element. If the kickoff prompt came AFTER it, claude
|
|
28
|
+
* would absorb the prompt as a 2nd "allowed tool" and launch with NO kickoff.
|
|
29
|
+
* So the kickoff positional goes FIRST and the variadic flag goes LAST, where
|
|
30
|
+
* it can only consume its own single value:
|
|
31
|
+
* [...passthrough, kickoff, '--allowedTools', 'mcp__borg__*']
|
|
32
|
+
*/
|
|
33
|
+
export function buildClaudeLaunchArgs(passthroughArgs: string[], kickoff: string): string[] {
|
|
34
|
+
return [...passthroughArgs, kickoff, '--allowedTools', BORG_MCP_ALLOWED_TOOLS];
|
|
35
|
+
}
|