@pellux/goodvibes-tui 1.27.0 → 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.
Files changed (404) hide show
  1. package/CHANGELOG.md +125 -2
  2. package/README.md +7 -9
  3. package/bin/goodvibes +2 -2
  4. package/bin/launcher-support.js +8 -4
  5. package/docs/README.md +11 -2
  6. package/docs/foundation-artifacts/operator-contract.json +6403 -2347
  7. package/package.json +14 -25
  8. package/scripts/postinstall.js +35 -35
  9. package/src/audio/spoken-turn-model-routing.ts +1 -1
  10. package/src/cli/bundle-command.ts +5 -5
  11. package/src/cli/completions/generate.ts +1 -1
  12. package/src/cli/doctor.ts +3 -3
  13. package/src/cli/entrypoint.ts +12 -7
  14. package/src/cli/help.ts +4 -5
  15. package/src/cli/hooks-command.ts +1 -1
  16. package/src/cli/index.ts +1 -4
  17. package/src/cli/launch-auto-update.ts +59 -7
  18. package/src/cli/management-commands.ts +6 -6
  19. package/src/cli/management-utils.ts +5 -5
  20. package/src/cli/management.ts +7 -7
  21. package/src/cli/network-posture.ts +1 -1
  22. package/src/cli/package-verification.ts +7 -6
  23. package/src/cli/plugin-bundles-command.ts +1 -1
  24. package/src/cli/plugin-command.ts +2 -2
  25. package/src/cli/service-command.ts +2 -2
  26. package/src/cli/service-posture.ts +4 -4
  27. package/src/cli/status.ts +9 -8
  28. package/src/cli/surface-command.ts +4 -4
  29. package/src/cli/tui-startup.ts +12 -3
  30. package/src/cli-flags.ts +3 -3
  31. package/src/config/goodvibes-home-audit.ts +0 -2
  32. package/src/config/secret-config.ts +37 -5
  33. package/src/config/tui-extension-settings.ts +1 -1
  34. package/src/core/approval-alert.ts +2 -2
  35. package/src/core/budget-breach-notifier.ts +3 -3
  36. package/src/core/conversation-compaction-render.ts +1 -1
  37. package/src/core/conversation-line-cache.ts +1 -1
  38. package/src/core/conversation-render-context.ts +1 -1
  39. package/src/core/conversation-rendering.ts +2 -2
  40. package/src/core/conversation.ts +10 -10
  41. package/src/core/long-task-notifier.ts +2 -2
  42. package/src/core/memory-diagnostics-gateway.ts +1 -1
  43. package/src/core/scriptable-statusline.ts +1 -1
  44. package/src/core/session-auto-titler.ts +1 -1
  45. package/src/core/session-resume-core.ts +2 -2
  46. package/src/core/stream-event-wiring.ts +24 -44
  47. package/src/core/terminal-notifier.ts +3 -3
  48. package/src/core/turn-cancellation.ts +1 -1
  49. package/src/core/turn-event-wiring.ts +5 -5
  50. package/src/input/command-registry.ts +6 -6
  51. package/src/input/commands/channel-pairing.ts +1 -1
  52. package/src/input/commands/cluster-runtime.ts +1 -1
  53. package/src/input/commands/codebase-runtime.ts +1 -1
  54. package/src/input/commands/devices-runtime.ts +1 -1
  55. package/src/input/commands/hosted-runtime.ts +330 -0
  56. package/src/input/commands/local-setup-review.ts +1 -1
  57. package/src/input/commands/local-setup-transfer.ts +2 -2
  58. package/src/input/commands/local-setup.ts +3 -3
  59. package/src/input/commands/managed-runtime.ts +2 -2
  60. package/src/input/commands/operator-rpc.ts +24 -110
  61. package/src/input/commands/payment-card-intake.ts +1 -1
  62. package/src/input/commands/permissions-provenance.ts +2 -2
  63. package/src/input/commands/plugin-runtime.ts +1 -1
  64. package/src/input/commands/provider.ts +1 -1
  65. package/src/input/commands/relay-runtime.ts +18 -9
  66. package/src/input/commands/rewind-runtime.ts +1 -1
  67. package/src/input/commands/runtime-services.ts +1 -1
  68. package/src/input/commands/services-runtime.ts +1 -1
  69. package/src/input/commands/session-workflow.ts +1 -1
  70. package/src/input/commands/settings-sync-runtime.ts +2 -2
  71. package/src/input/commands/share-runtime.ts +1 -1
  72. package/src/input/commands/tasks-runtime.ts +145 -55
  73. package/src/input/commands/update-runtime.ts +31 -28
  74. package/src/input/commands/work-plan-runtime.ts +2 -2
  75. package/src/input/commands/workstream-attempts.ts +1 -1
  76. package/src/input/commands/workstream-runtime.ts +2 -2
  77. package/src/input/commands.ts +2 -0
  78. package/src/input/feature-unit-layout.ts +1 -1
  79. package/src/input/feed-context-factory.ts +3 -3
  80. package/src/input/handler-content-actions.ts +2 -2
  81. package/src/input/handler-feed-routes.ts +1 -1
  82. package/src/input/handler-feed.ts +3 -3
  83. package/src/input/handler-modal-token-routes.ts +1 -1
  84. package/src/input/handler-onboarding-daemon-adopt.ts +3 -2
  85. package/src/input/handler-onboarding.ts +1 -1
  86. package/src/input/handler-types.ts +2 -2
  87. package/src/input/handler-ui-state.ts +1 -1
  88. package/src/input/handler.ts +4 -4
  89. package/src/input/input-history.ts +1 -1
  90. package/src/input/onboarding/onboarding-feature-units.ts +2 -2
  91. package/src/input/onboarding/onboarding-runtime-status.ts +15 -1
  92. package/src/input/onboarding/onboarding-wizard-apply.ts +17 -8
  93. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +5 -3
  94. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +1 -1
  95. package/src/input/onboarding/onboarding-wizard-types.ts +1 -1
  96. package/src/input/payments-config.ts +6 -6
  97. package/src/input/search.ts +1 -1
  98. package/src/input/session-picker-modal.ts +46 -0
  99. package/src/input/settings-modal-activation.ts +1 -1
  100. package/src/input/settings-modal-behavior.ts +4 -4
  101. package/src/input/settings-modal-commit.ts +11 -0
  102. package/src/input/settings-modal-data.ts +13 -80
  103. package/src/input/settings-modal-mutations.ts +33 -0
  104. package/src/input/settings-modal-secrets.ts +34 -0
  105. package/src/input/settings-modal-subscriptions.ts +1 -1
  106. package/src/input/settings-modal-types.ts +15 -1
  107. package/src/input/settings-modal.ts +28 -3
  108. package/src/input/worktree-setup-config.ts +1 -1
  109. package/src/main.ts +11 -9
  110. package/src/panels/agent-inspector-shared.ts +2 -2
  111. package/src/panels/base-panel.ts +2 -2
  112. package/src/panels/builtin/operations.ts +6 -8
  113. package/src/panels/builtin/session.ts +17 -0
  114. package/src/panels/builtin/shared.ts +5 -5
  115. package/src/panels/builtin-modals.ts +3 -3
  116. package/src/panels/confirm-state.ts +1 -1
  117. package/src/panels/cost-tracker-panel.ts +4 -4
  118. package/src/panels/diff-panel.ts +2 -2
  119. package/src/panels/diff-review-panel.ts +2 -2
  120. package/src/panels/expandable-list-panel.ts +2 -2
  121. package/src/panels/fleet-acts.ts +1 -1
  122. package/src/panels/fleet-observed-render.ts +1 -1
  123. package/src/panels/fleet-panel-format.ts +1 -1
  124. package/src/panels/fleet-panel.ts +1 -1
  125. package/src/panels/fleet-spawn.ts +1 -1
  126. package/src/panels/fleet-steer.ts +1 -1
  127. package/src/panels/fleet-transcript.ts +1 -1
  128. package/src/panels/git-panel.ts +1 -1
  129. package/src/panels/hosted-session-feed.ts +352 -0
  130. package/src/panels/hosted-session-panel.ts +221 -0
  131. package/src/panels/local-auth-panel.ts +3 -3
  132. package/src/panels/modals/devices-modal.ts +1 -1
  133. package/src/panels/modals/local-auth-modal.ts +1 -1
  134. package/src/panels/modals/pairing-modal.ts +1 -1
  135. package/src/panels/modals/services-modal.ts +1 -1
  136. package/src/panels/modals/settings-sync-modal.ts +1 -1
  137. package/src/panels/modals/subscription-modal.ts +1 -1
  138. package/src/panels/modals/work-plan-modal.ts +1 -1
  139. package/src/panels/notifications-panel.ts +1 -1
  140. package/src/panels/panel-confirm-overlay.ts +1 -1
  141. package/src/panels/plugins-panel.ts +2 -2
  142. package/src/panels/polish-core.ts +2 -2
  143. package/src/panels/polish-tables.ts +1 -1
  144. package/src/panels/polish.ts +2 -2
  145. package/src/panels/scrollable-list-panel.ts +3 -3
  146. package/src/panels/skills-panel.ts +3 -3
  147. package/src/panels/token-budget-panel.ts +5 -5
  148. package/src/panels/types.ts +1 -2
  149. package/src/permissions/prompt.ts +1 -1
  150. package/src/renderer/autocomplete-overlay.ts +1 -1
  151. package/src/renderer/block-actions-overlay.ts +1 -1
  152. package/src/renderer/bookmark-modal.ts +1 -1
  153. package/src/renderer/buffer.ts +1 -1
  154. package/src/renderer/code-block.ts +1 -1
  155. package/src/renderer/composer-fragments.ts +1 -1
  156. package/src/renderer/compositor.ts +2 -2
  157. package/src/renderer/config-modal.ts +1 -1
  158. package/src/renderer/context-inspector.ts +1 -1
  159. package/src/renderer/conversation-layout.ts +2 -2
  160. package/src/renderer/conversation-overlays.ts +1 -1
  161. package/src/renderer/conversation-surface.ts +2 -2
  162. package/src/renderer/diff-view.ts +1 -1
  163. package/src/renderer/diff.ts +1 -1
  164. package/src/renderer/file-picker-overlay.ts +1 -1
  165. package/src/renderer/fleet-tab-strip.ts +1 -1
  166. package/src/renderer/fullscreen-primitives.ts +2 -2
  167. package/src/renderer/fullscreen-workspace.ts +1 -1
  168. package/src/renderer/header-line.ts +1 -1
  169. package/src/renderer/help-overlay.ts +1 -1
  170. package/src/renderer/history-search-overlay.ts +2 -2
  171. package/src/renderer/layout.ts +5 -8
  172. package/src/renderer/markdown-inline.ts +1 -1
  173. package/src/renderer/markdown-table.ts +1 -1
  174. package/src/renderer/markdown.ts +1 -1
  175. package/src/renderer/mcp-workspace.ts +1 -1
  176. package/src/renderer/modal-factory.ts +2 -2
  177. package/src/renderer/model-workspace.ts +2 -2
  178. package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
  179. package/src/renderer/overlay-box.ts +1 -1
  180. package/src/renderer/panel-composite.ts +1 -1
  181. package/src/renderer/panel-workspace-bar.ts +1 -1
  182. package/src/renderer/process-indicator.ts +1 -1
  183. package/src/renderer/profile-picker-modal.ts +1 -1
  184. package/src/renderer/search-overlay.ts +2 -2
  185. package/src/renderer/selection-modal-overlay.ts +1 -1
  186. package/src/renderer/session-picker-modal.ts +124 -3
  187. package/src/renderer/settings-modal-helpers.ts +2 -0
  188. package/src/renderer/settings-modal.ts +2 -2
  189. package/src/renderer/shell-surface.ts +2 -2
  190. package/src/renderer/system-message.ts +1 -1
  191. package/src/renderer/tab-strip.ts +1 -1
  192. package/src/renderer/theme-mode-config.ts +1 -1
  193. package/src/renderer/theme.ts +11 -12
  194. package/src/renderer/thinking.ts +1 -1
  195. package/src/renderer/tool-call.ts +2 -2
  196. package/src/renderer/tool-result-expanded-lines.ts +1 -1
  197. package/src/renderer/turn-injection.ts +7 -8
  198. package/src/renderer/ui-factory.ts +3 -3
  199. package/src/runtime/bootstrap-command-context.ts +4 -4
  200. package/src/runtime/bootstrap-command-parts.ts +5 -5
  201. package/src/runtime/bootstrap-core.ts +30 -30
  202. package/src/runtime/bootstrap-shell.ts +4 -4
  203. package/src/runtime/bootstrap.ts +128 -157
  204. package/src/runtime/client/approval-updates.ts +82 -0
  205. package/src/runtime/client/build-floors.ts +167 -0
  206. package/src/runtime/client/daemon-attach-handshake.ts +115 -0
  207. package/src/runtime/client/fleet-union.ts +147 -0
  208. package/src/runtime/client/host-service-status.ts +71 -0
  209. package/src/runtime/client/hosted-exit.ts +86 -0
  210. package/src/runtime/client/hosted-roster.ts +110 -0
  211. package/src/runtime/client/hosted-session-stream.ts +178 -0
  212. package/src/runtime/client/hosted-sessions.ts +187 -0
  213. package/src/runtime/client/operator-endpoint.ts +213 -0
  214. package/src/runtime/client/spine-adoption.ts +99 -0
  215. package/src/runtime/cloudflare-control-plane.ts +1 -1
  216. package/src/runtime/context-accounting-source.ts +1 -1
  217. package/src/runtime/context.ts +2 -2
  218. package/src/runtime/conversation-rewind-port.ts +42 -14
  219. package/src/runtime/daemon-attach-notices.ts +55 -19
  220. package/src/runtime/diagnostics/panels/ops.ts +1 -1
  221. package/src/runtime/disposal-wiring.ts +4 -24
  222. package/src/runtime/index.ts +119 -105
  223. package/src/runtime/install-self-check-startup.ts +2 -2
  224. package/src/runtime/interaction-seams.ts +1 -1
  225. package/src/runtime/knowledge-services.ts +8 -2
  226. package/src/runtime/legacy-daemon-migration.ts +15 -3
  227. package/src/runtime/legacy-daemon-reconcile.ts +3 -2
  228. package/src/runtime/memory-spine-transport.ts +37 -267
  229. package/src/runtime/notification-dispatch.ts +2 -2
  230. package/src/runtime/onboarding/apply.ts +2 -2
  231. package/src/runtime/onboarding/derivation.ts +2 -2
  232. package/src/runtime/onboarding/markers.ts +2 -2
  233. package/src/runtime/onboarding/progress.ts +2 -2
  234. package/src/runtime/onboarding/snapshot.ts +1 -1
  235. package/src/runtime/onboarding/state.ts +2 -2
  236. package/src/runtime/onboarding/types.ts +2 -2
  237. package/src/runtime/orchestrator-core-services.ts +1 -1
  238. package/src/runtime/path-shadow-startup.ts +28 -221
  239. package/src/runtime/power-keepawake-remote.ts +3 -2
  240. package/src/runtime/process-lifecycle.ts +2 -2
  241. package/src/runtime/provider-fallback.ts +10 -66
  242. package/src/runtime/recovery-autosave.ts +1 -1
  243. package/src/runtime/recovery-offer-wiring.ts +39 -23
  244. package/src/runtime/recovery-prompt.ts +31 -17
  245. package/src/runtime/relay-reachability-bridge.ts +53 -42
  246. package/src/runtime/release-artifacts.ts +2 -1
  247. package/src/runtime/runtime-services-types.ts +82 -35
  248. package/src/runtime/services.ts +305 -300
  249. package/src/runtime/session-resume-liveness-confirm.ts +1 -1
  250. package/src/runtime/ui-services.ts +7 -6
  251. package/src/runtime/update-check.ts +23 -43
  252. package/src/runtime/workspace-checkpointing.ts +1 -1
  253. package/src/runtime/wrfc-persistence.ts +2 -2
  254. package/src/shell/ui-openers.ts +30 -7
  255. package/src/utils/clipboard.ts +1 -1
  256. package/src/verification/verification-ledger.ts +10 -8
  257. package/src/version.ts +1 -1
  258. package/bin/goodvibes-daemon +0 -90
  259. package/src/cli/config-overrides.ts +0 -267
  260. package/src/cli/endpoints.ts +0 -109
  261. package/src/cli/parser.ts +0 -395
  262. package/src/cli/redaction.ts +0 -170
  263. package/src/cli/types.ts +0 -84
  264. package/src/cluster/commands.ts +0 -382
  265. package/src/cluster/remote-daemon-target.ts +0 -225
  266. package/src/cluster/render.ts +0 -268
  267. package/src/config/atomic-write.ts +0 -70
  268. package/src/config/credential-availability.ts +0 -122
  269. package/src/config/goodvibes-home.ts +0 -149
  270. package/src/config/index.ts +0 -88
  271. package/src/config/provider-model.ts +0 -23
  272. package/src/config/read-versioned.ts +0 -228
  273. package/src/core/alert-gating.ts +0 -67
  274. package/src/core/consolidation-receipt.ts +0 -41
  275. package/src/core/focus-tracker.ts +0 -41
  276. package/src/core/history.ts +0 -45
  277. package/src/core/memory-status.ts +0 -118
  278. package/src/core/orchestrator.ts +0 -7
  279. package/src/core/pairing-devices.ts +0 -49
  280. package/src/core/pairing-handoff.ts +0 -101
  281. package/src/core/pairing-offers.ts +0 -83
  282. package/src/core/pairing-origin.ts +0 -78
  283. package/src/core/rewind-turn-anchors.ts +0 -311
  284. package/src/core/session-recovery.ts +0 -210
  285. package/src/core/stable-host.ts +0 -171
  286. package/src/core/transcript-journal.ts +0 -503
  287. package/src/daemon/cli.ts +0 -641
  288. package/src/daemon/handlers/context.ts +0 -29
  289. package/src/daemon/handlers/contracts.ts +0 -77
  290. package/src/daemon/handlers/credentials.ts +0 -139
  291. package/src/daemon/handlers/drafts/draft-store.ts +0 -427
  292. package/src/daemon/handlers/drafts/index.ts +0 -17
  293. package/src/daemon/handlers/drafts/register.ts +0 -331
  294. package/src/daemon/handlers/errors.ts +0 -18
  295. package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
  296. package/src/daemon/handlers/inbox/index.ts +0 -284
  297. package/src/daemon/handlers/inbox/mapping.ts +0 -192
  298. package/src/daemon/handlers/inbox/poller.ts +0 -212
  299. package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
  300. package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
  301. package/src/daemon/handlers/inbox/providers/email.ts +0 -152
  302. package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
  303. package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
  304. package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
  305. package/src/daemon/handlers/index.ts +0 -117
  306. package/src/daemon/handlers/register.ts +0 -168
  307. package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
  308. package/src/daemon/handlers/remote/backends/docker.ts +0 -79
  309. package/src/daemon/handlers/remote/backends/index.ts +0 -40
  310. package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
  311. package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
  312. package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
  313. package/src/daemon/handlers/remote/backends/types.ts +0 -97
  314. package/src/daemon/handlers/remote/dispatcher.ts +0 -181
  315. package/src/daemon/handlers/remote/index.ts +0 -119
  316. package/src/daemon/handlers/remote/peer-registry.ts +0 -357
  317. package/src/daemon/handlers/remote/service.ts +0 -191
  318. package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
  319. package/src/daemon/handlers/routing/index.ts +0 -261
  320. package/src/daemon/handlers/routing/route-store.ts +0 -319
  321. package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
  322. package/src/daemon/handlers/sqlite-store.ts +0 -278
  323. package/src/daemon/handlers/triage/index.ts +0 -57
  324. package/src/daemon/handlers/triage/integration.ts +0 -213
  325. package/src/daemon/handlers/triage/pipeline.ts +0 -274
  326. package/src/daemon/handlers/triage/scorer.ts +0 -287
  327. package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
  328. package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
  329. package/src/daemon/handlers/triage/tagger/index.ts +0 -184
  330. package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
  331. package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
  332. package/src/daemon/handlers/triage/types.ts +0 -50
  333. package/src/daemon/lifecycle.ts +0 -41
  334. package/src/daemon/provision-wake-model.ts +0 -81
  335. package/src/daemon/safe-serve.ts +0 -61
  336. package/src/daemon/send/channels.ts +0 -200
  337. package/src/daemon/send/command.ts +0 -332
  338. package/src/daemon/send/composition.ts +0 -99
  339. package/src/daemon/send/failure-text.ts +0 -93
  340. package/src/daemon/send/inert-text.ts +0 -225
  341. package/src/daemon/send/stdin.ts +0 -24
  342. package/src/daemon/service-commands.ts +0 -329
  343. package/src/export/cost-utils.ts +0 -319
  344. package/src/input/selection.ts +0 -135
  345. package/src/plugins/loader.ts +0 -15
  346. package/src/renderer/bottom-bar.ts +0 -58
  347. package/src/renderer/conversation-tree.ts +0 -228
  348. package/src/runtime/agent-graph-composition.ts +0 -78
  349. package/src/runtime/channel-composition.ts +0 -46
  350. package/src/runtime/cluster-composition.ts +0 -124
  351. package/src/runtime/cluster-group-composition.ts +0 -284
  352. package/src/runtime/code-index-services.ts +0 -167
  353. package/src/runtime/daemon-handler-composition.ts +0 -76
  354. package/src/runtime/device-posture-composition.ts +0 -110
  355. package/src/runtime/durability-housekeeping.ts +0 -183
  356. package/src/runtime/durability-services.ts +0 -155
  357. package/src/runtime/embedded-service-factories.ts +0 -58
  358. package/src/runtime/feature-settings.ts +0 -154
  359. package/src/runtime/fleet-needs-input-push.ts +0 -70
  360. package/src/runtime/fleet-services.ts +0 -41
  361. package/src/runtime/idle-power-services.ts +0 -85
  362. package/src/runtime/mail-composition.ts +0 -65
  363. package/src/runtime/memory-fold.ts +0 -55
  364. package/src/runtime/operator-token-cleanup.ts +0 -109
  365. package/src/runtime/path-shadow.ts +0 -418
  366. package/src/runtime/perf/panel-health-monitor.ts +0 -18
  367. package/src/runtime/provider-optimizer-wiring.ts +0 -55
  368. package/src/runtime/reachability-notice.ts +0 -100
  369. package/src/runtime/remote-execution-composition.ts +0 -62
  370. package/src/runtime/session-liveness-marker.ts +0 -257
  371. package/src/runtime/session-pointer-surface.ts +0 -22
  372. package/src/runtime/session-storage-services.ts +0 -41
  373. package/src/runtime/surface-feature-flags.ts +0 -96
  374. package/src/runtime/terminal-output-guard.ts +0 -235
  375. package/src/runtime/trust/workspace-registration.ts +0 -192
  376. package/src/runtime/trust/workspace-trust.ts +0 -229
  377. package/src/runtime/ui/index.ts +0 -39
  378. package/src/runtime/ui/model-picker/data-provider.ts +0 -182
  379. package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
  380. package/src/runtime/ui/model-picker/index.ts +0 -59
  381. package/src/runtime/ui/model-picker/types.ts +0 -153
  382. package/src/runtime/ui/provider-health/data-provider.ts +0 -244
  383. package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
  384. package/src/runtime/ui/provider-health/index.ts +0 -46
  385. package/src/runtime/ui/provider-health/types.ts +0 -146
  386. package/src/runtime/ui-events.ts +0 -1
  387. package/src/runtime/ui-read-model-helpers.ts +0 -1
  388. package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
  389. package/src/runtime/ui-read-models-observability-options.ts +0 -1
  390. package/src/runtime/ui-read-models-observability-remote.ts +0 -1
  391. package/src/runtime/ui-read-models-observability-security.ts +0 -1
  392. package/src/runtime/ui-read-models-observability-system.ts +0 -1
  393. package/src/runtime/ui-read-models-observability.ts +0 -1
  394. package/src/runtime/ui-service-queries.ts +0 -1
  395. package/src/runtime/voice-setup-services.ts +0 -98
  396. package/src/runtime/workstream-attempts-validation.ts +0 -77
  397. package/src/runtime/workstream-draft-edits.ts +0 -95
  398. package/src/runtime/workstream-draft-store.ts +0 -274
  399. package/src/runtime/workstream-draft-types.ts +0 -42
  400. package/src/runtime/workstream-services.ts +0 -373
  401. package/src/tools/index.ts +0 -1
  402. package/src/types/grid.ts +0 -48
  403. package/src/types/sql-js.d.ts +0 -15
  404. package/src/work-plans/work-plan-store.ts +0 -702
@@ -1,418 +0,0 @@
1
- /**
2
- * path-shadow.ts — decide whether the copy of a command the updater maintains
3
- * is actually the copy the user's shell runs.
4
- *
5
- * OWNERSHIP: this is a verbatim copy of the SDK's canonical module,
6
- * `@pellux/goodvibes-sdk/platform/runtime/path-shadow`, which is where the
7
- * policy lives because more than one surface needs it (this TUI, the agent,
8
- * and the installer's POSIX sh statement of the same rules). The copy exists
9
- * only because the SDK release carrying that module has not been published
10
- * yet and this package pins an exact published version. When it publishes,
11
- * replace this file's body with a re-export of the SDK subpath — exactly the
12
- * shape update-check.ts already uses for the update policy — and delete
13
- * nothing else; the wiring in path-shadow-startup.ts and the tests in
14
- * src/test/runtime/path-shadow.test.ts keep working unchanged.
15
- *
16
- * The platform's update guarantee is "one verified swap mechanism, nothing
17
- * ever drifts". That guarantee holds only while there is exactly one copy of
18
- * each command reachable on PATH. When a second, older copy sits in a
19
- * directory that comes EARLIER on PATH than the install directory, the
20
- * updater keeps upgrading a file the user never reaches: `goodvibes-agent`
21
- * reports itself current, an older build answers the typing, and the product
22
- * looks like it is lying about its own capabilities. That is exactly what
23
- * happened with a leftover `~/.bun/bin/goodvibes-agent` link (1.18.1) sitting
24
- * at PATH position 2 while `~/.local/bin/goodvibes-agent` (1.21.0) sat at
25
- * position 21.
26
- *
27
- * This module is the one place that decides those facts. It is pure: every
28
- * filesystem and subprocess touch (does this file exist and is it runnable,
29
- * where does this symlink actually point, what does `<path> --version` say)
30
- * is injected, so the policy is provable under test with fake paths and no
31
- * real install. The surfaces wire the real I/O:
32
- * - a client's startup check reports a shadow before anything else renders;
33
- * - the installer's shell implementation (goodvibes-tui scripts/install.sh)
34
- * mirrors these same rules in POSIX sh, because an installer cannot
35
- * import TypeScript.
36
- *
37
- * Removal is deliberately conservative. A copy is only ever offered for
38
- * removal when it is recognisably one of OUR programs — a link into an
39
- * installed `@pellux/goodvibes-*` package, or a file that answers
40
- * `--version` with `<command> <semver>` — and only when it lives inside the
41
- * user's own home directory. Everything else is reported and left alone.
42
- */
43
-
44
- // ---------------------------------------------------------------------------
45
- // Types
46
- // ---------------------------------------------------------------------------
47
-
48
- /**
49
- * How confident we are that a copy found on PATH is one of our own programs,
50
- * and therefore whether it is safe to offer to remove it.
51
- *
52
- * - `install-target`: the copy living in the directory the installer and
53
- * the auto-updater maintain. Never a removal candidate.
54
- * - `package-link`: an entry that resolves into an installed
55
- * `@pellux/goodvibes-*` package (a `bun add -g` / `npm i -g` link, or a
56
- * project-local dependency link). Removed by uninstalling that package.
57
- * - `our-binary`: a standalone file that answers `--version` with
58
- * `<command> <semver>`, i.e. a previous standalone install of the same
59
- * program. Removed by deleting the file.
60
- * - `unknown`: anything we cannot positively identify, including anything
61
- * outside the user's home directory. Reported, never removed.
62
- */
63
- export type ShadowOwnership = 'install-target' | 'package-link' | 'our-binary' | 'unknown';
64
-
65
- /** How a recognised copy is removed, and by what command. */
66
- export interface ShadowRemoval {
67
- /** `package` = uninstall the owning package; `file` = delete the PATH entry itself. */
68
- readonly kind: 'package' | 'file';
69
- /** The `@pellux/...` package name, when `kind` is `package`. */
70
- readonly packageName?: string | undefined;
71
- /** The exact command a user (or the installer) runs to remove this copy. */
72
- readonly command: string;
73
- }
74
-
75
- /** One copy of a command found on PATH. */
76
- export interface CommandCopy {
77
- /** The command name, e.g. `goodvibes-agent`. */
78
- readonly command: string;
79
- /** The PATH directory the copy was found in. */
80
- readonly directory: string;
81
- /** `<directory>/<command>` — the path the shell would execute. */
82
- readonly path: string;
83
- /** Zero-based position of `directory` in PATH. Lower wins. */
84
- readonly pathIndex: number;
85
- /** The symlink-resolved path, or `path` when it is not a link. */
86
- readonly resolvedPath: string;
87
- /** What `<path> --version` reported, when it could be probed. */
88
- readonly version?: string | undefined;
89
- readonly ownership: ShadowOwnership;
90
- /** Present only when `ownership` is `package-link` or `our-binary`. */
91
- readonly removal?: ShadowRemoval | undefined;
92
- }
93
-
94
- /** The reachability verdict for one command. */
95
- export interface CommandShadowReport {
96
- readonly command: string;
97
- /** Every copy found, in PATH order. */
98
- readonly copies: readonly CommandCopy[];
99
- /** The copy the shell actually runs — the first on PATH. Absent when the command is not on PATH at all. */
100
- readonly winner?: CommandCopy | undefined;
101
- /** The copy in the install directory. Absent when the install directory is not on PATH. */
102
- readonly installed?: CommandCopy | undefined;
103
- /**
104
- * Copies that come earlier on PATH than the install directory's copy. A
105
- * non-empty list means the maintained install is unreachable by name.
106
- */
107
- readonly shadowing: readonly CommandCopy[];
108
- /** True when the install directory holds this command but is not on PATH at all. */
109
- readonly installDirNotOnPath: boolean;
110
- }
111
-
112
- /** The whole-install verdict across every command the installer maintains. */
113
- export interface ShadowScanResult {
114
- readonly reports: readonly CommandShadowReport[];
115
- /** Commands whose maintained copy loses to an earlier PATH entry. */
116
- readonly shadowed: readonly CommandShadowReport[];
117
- /** True when any command is shadowed or the install directory is missing from PATH. */
118
- readonly hasProblem: boolean;
119
- }
120
-
121
- export interface ShadowScanInput {
122
- /** Command names the installer/updater maintains, e.g. `['goodvibes', 'goodvibes-daemon', 'goodvibes-agent']`. */
123
- readonly commands: readonly string[];
124
- /** The directory the installer writes to and the auto-updater swaps in place. */
125
- readonly installDir: string;
126
- /** PATH split into directories, in order, exactly as the shell would search them. */
127
- readonly pathEntries: readonly string[];
128
- /** The user's home directory. Nothing outside it is ever a removal candidate. */
129
- readonly homeDir: string;
130
- /** True when `path` exists and is a runnable file. */
131
- readonly isExecutableFile: (path: string) => boolean;
132
- /** Resolves a symlink chain; returns `path` unchanged when it is not a link or cannot be resolved. */
133
- readonly realPath: (path: string) => string;
134
- /**
135
- * Runs `<path> --version` and returns its first line, or undefined when it
136
- * cannot be run. Optional: without it, `our-binary` can never be
137
- * established and such copies stay `unknown` (reported, never removed).
138
- */
139
- readonly probeVersion?: ((path: string) => string | undefined) | undefined;
140
- }
141
-
142
- // ---------------------------------------------------------------------------
143
- // PATH handling
144
- // ---------------------------------------------------------------------------
145
-
146
- /**
147
- * Splits a raw PATH string into directories in search order.
148
- *
149
- * Empty entries (from a leading, trailing, or doubled separator) mean "the
150
- * current directory" to a POSIX shell. They are dropped rather than resolved:
151
- * a cwd-relative hit is not a stable install anyone can reason about, and
152
- * treating it as one would produce a different verdict per directory.
153
- * Duplicated directories collapse to their first occurrence, which is the
154
- * only position that can ever win.
155
- */
156
- export function splitPathEntries(rawPath: string | undefined, separator = ':'): string[] {
157
- if (!rawPath) return [];
158
- const seen = new Set<string>();
159
- const entries: string[] = [];
160
- for (const raw of rawPath.split(separator)) {
161
- const entry = raw.trim();
162
- if (entry.length === 0) continue;
163
- const normalized = stripTrailingSeparators(entry);
164
- if (normalized.length === 0) continue;
165
- if (seen.has(normalized)) continue;
166
- seen.add(normalized);
167
- entries.push(normalized);
168
- }
169
- return entries;
170
- }
171
-
172
- /** Drops trailing `/` (or `\`) so `~/.local/bin` and `~/.local/bin/` are one directory. */
173
- function stripTrailingSeparators(value: string): string {
174
- let end = value.length;
175
- while (end > 1 && (value[end - 1] === '/' || value[end - 1] === '\\')) end -= 1;
176
- return value.slice(0, end);
177
- }
178
-
179
- function joinPath(directory: string, name: string): string {
180
- return `${stripTrailingSeparators(directory)}/${name}`;
181
- }
182
-
183
- function segmentsOf(path: string): string[] {
184
- return path.split(/[\\/]/).filter((segment) => segment.length > 0);
185
- }
186
-
187
- /** True when `path` is `root` itself or lives underneath it. */
188
- export function isWithinDirectory(path: string, root: string): boolean {
189
- const normalizedRoot = stripTrailingSeparators(root);
190
- if (normalizedRoot.length === 0) return false;
191
- const normalizedPath = stripTrailingSeparators(path);
192
- if (normalizedPath === normalizedRoot) return true;
193
- return normalizedPath.startsWith(`${normalizedRoot}/`);
194
- }
195
-
196
- // ---------------------------------------------------------------------------
197
- // Ownership classification
198
- // ---------------------------------------------------------------------------
199
-
200
- /** The npm scope every package this platform publishes lives under. */
201
- const PACKAGE_SCOPE = '@pellux';
202
- /** Only `@pellux/goodvibes-*` packages are ours; a same-scope stranger is not assumed. */
203
- const PACKAGE_PREFIX = 'goodvibes-';
204
-
205
- /**
206
- * Extracts the owning `@pellux/goodvibes-*` package name from a resolved
207
- * path, by finding the LAST `node_modules` segment and reading the scoped
208
- * package directory that follows it. The last occurrence is the one that
209
- * owns the file: a nested `node_modules/a/node_modules/b/bin/x` belongs to
210
- * `b`, not `a`.
211
- */
212
- export function owningPackageName(resolvedPath: string): string | undefined {
213
- const segments = segmentsOf(resolvedPath);
214
- for (let i = segments.length - 1; i >= 0; i -= 1) {
215
- if (segments[i] !== 'node_modules') continue;
216
- const scope = segments[i + 1];
217
- const name = segments[i + 2];
218
- if (scope !== PACKAGE_SCOPE || name === undefined) return undefined;
219
- if (!name.startsWith(PACKAGE_PREFIX)) return undefined;
220
- return `${scope}/${name}`;
221
- }
222
- return undefined;
223
- }
224
-
225
- /**
226
- * Picks the uninstall command for a package link, from where the package
227
- * actually lives. A bun global install lives under `.bun/install/global`;
228
- * everything else is treated as npm-managed, which is also the correct
229
- * advice for a `bun add -g` that used an npm-style prefix.
230
- */
231
- function packageRemoval(packageName: string, resolvedPath: string): ShadowRemoval {
232
- const isBunGlobal = /[\\/]\.bun[\\/]install[\\/]global[\\/]/.test(resolvedPath)
233
- || segmentsOf(resolvedPath).includes('.bun');
234
- return {
235
- kind: 'package',
236
- packageName,
237
- command: isBunGlobal ? `bun remove -g ${packageName}` : `npm rm -g ${packageName}`,
238
- };
239
- }
240
-
241
- /**
242
- * True when a `--version` line is one of ours: `<command> <dotted numbers>`,
243
- * which is the exact shape every goodvibes command prints. Anything else —
244
- * an unrelated program that happens to share the name, a wrapper script, a
245
- * `--version` that errors — fails, and the copy stays `unknown`.
246
- */
247
- export function versionLineIdentifiesCommand(line: string | undefined, command: string): string | undefined {
248
- if (!line) return undefined;
249
- const match = /^([A-Za-z0-9._-]+)[ \t]+v?(\d+(?:\.\d+)*(?:[-+][0-9A-Za-z.-]+)?)\s*$/.exec(line.trim());
250
- if (!match) return undefined;
251
- if (match[1] !== command) return undefined;
252
- return match[2];
253
- }
254
-
255
- // ---------------------------------------------------------------------------
256
- // The scan
257
- // ---------------------------------------------------------------------------
258
-
259
- function classify(input: ShadowScanInput, copy: {
260
- readonly command: string;
261
- readonly directory: string;
262
- readonly path: string;
263
- readonly pathIndex: number;
264
- readonly resolvedPath: string;
265
- }): { ownership: ShadowOwnership; removal?: ShadowRemoval | undefined; version?: string | undefined } {
266
- if (isWithinDirectory(copy.path, input.installDir)) {
267
- return { ownership: 'install-target', version: probe(input, copy.path, copy.command) };
268
- }
269
-
270
- const version = probe(input, copy.path, copy.command);
271
-
272
- // Nothing outside the user's own home is ever a removal candidate, however
273
- // confidently we recognise it: a system-wide copy is somebody else's to
274
- // manage, and this code must never reach outside the user's directories.
275
- const insideHome = isWithinDirectory(copy.path, input.homeDir)
276
- && isWithinDirectory(copy.resolvedPath, input.homeDir);
277
-
278
- const packageName = owningPackageName(copy.resolvedPath);
279
- if (packageName && insideHome) {
280
- return { ownership: 'package-link', removal: packageRemoval(packageName, copy.resolvedPath), version };
281
- }
282
- if (packageName) {
283
- return { ownership: 'unknown', version };
284
- }
285
- if (version !== undefined && insideHome) {
286
- return { ownership: 'our-binary', removal: { kind: 'file', command: `rm ${copy.path}` }, version };
287
- }
288
- return { ownership: 'unknown', version };
289
- }
290
-
291
- function probe(input: ShadowScanInput, path: string, command: string): string | undefined {
292
- if (!input.probeVersion) return undefined;
293
- try {
294
- return versionLineIdentifiesCommand(input.probeVersion(path), command);
295
- } catch {
296
- return undefined;
297
- }
298
- }
299
-
300
- function resolve(input: ShadowScanInput, path: string): string {
301
- try {
302
- return input.realPath(path);
303
- } catch {
304
- return path;
305
- }
306
- }
307
-
308
- function exists(input: ShadowScanInput, path: string): boolean {
309
- try {
310
- return input.isExecutableFile(path);
311
- } catch {
312
- return false;
313
- }
314
- }
315
-
316
- /** Scans PATH for every copy of every maintained command and decides which one wins. */
317
- export function scanCommandShadows(input: ShadowScanInput): ShadowScanResult {
318
- const entries = input.pathEntries.map(stripTrailingSeparators).filter((entry) => entry.length > 0);
319
- const installDir = stripTrailingSeparators(input.installDir);
320
- const installDirOnPath = entries.some((entry) => entry === installDir);
321
-
322
- const reports: CommandShadowReport[] = [];
323
- for (const command of input.commands) {
324
- const copies: CommandCopy[] = [];
325
- for (let index = 0; index < entries.length; index += 1) {
326
- const directory = entries[index] as string;
327
- const path = joinPath(directory, command);
328
- if (!exists(input, path)) continue;
329
- const resolvedPath = resolve(input, path);
330
- const partial = { command, directory, path, pathIndex: index, resolvedPath };
331
- copies.push({ ...partial, ...classify(input, partial) });
332
- }
333
-
334
- const installedOnPath = copies.find((copy) => copy.ownership === 'install-target');
335
- // The install directory may hold the command while being absent from
336
- // PATH; that install is just as unreachable as a shadowed one.
337
- const installedOffPath = !installDirOnPath && exists(input, joinPath(installDir, command));
338
-
339
- const shadowing = installedOnPath
340
- ? copies.filter((copy) => copy.pathIndex < installedOnPath.pathIndex)
341
- : [];
342
-
343
- reports.push({
344
- command,
345
- copies,
346
- winner: copies[0],
347
- installed: installedOnPath,
348
- shadowing,
349
- installDirNotOnPath: installedOffPath,
350
- });
351
- }
352
-
353
- const shadowed = reports.filter((report) => report.shadowing.length > 0 || report.installDirNotOnPath);
354
- return { reports, shadowed, hasProblem: shadowed.length > 0 };
355
- }
356
-
357
- // ---------------------------------------------------------------------------
358
- // Plain-words reporting
359
- // ---------------------------------------------------------------------------
360
-
361
- function describeVersion(copy: CommandCopy): string {
362
- return copy.version ? `version ${copy.version}` : 'version unknown';
363
- }
364
-
365
- /**
366
- * Renders one shadowed command as plain lines: which path wins, what version
367
- * each copy is, and the exact command that fixes it. No jargon, no severity
368
- * words — the user needs to know which file answers when they type the name.
369
- */
370
- export function describeShadowReport(report: CommandShadowReport): string[] {
371
- const lines: string[] = [];
372
- if (report.installDirNotOnPath) {
373
- lines.push(
374
- `${report.command} is installed but its directory is not on your PATH, so typing "${report.command}" does not reach it.`,
375
- );
376
- return lines;
377
- }
378
- const winner = report.winner;
379
- const installed = report.installed;
380
- if (!winner || !installed) return lines;
381
-
382
- lines.push(
383
- `Typing "${report.command}" runs ${winner.path} (${describeVersion(winner)}), `
384
- + `not the copy this installer maintains at ${installed.path} (${describeVersion(installed)}).`,
385
- );
386
- for (const copy of report.shadowing) {
387
- if (copy.removal) {
388
- lines.push(` ${copy.path} is a copy of our own program. Remove it with: ${copy.removal.command}`);
389
- } else {
390
- lines.push(
391
- ` ${copy.path} is not something we can identify as ours, so it will not be touched. `
392
- + `Remove or reorder it yourself, or put ${installed.directory} earlier on your PATH.`,
393
- );
394
- }
395
- }
396
- return lines;
397
- }
398
-
399
- /** Renders every problem in a scan, in command order. Empty when the scan is clean. */
400
- export function describeShadowScan(result: ShadowScanResult): string[] {
401
- return result.shadowed.flatMap((report) => describeShadowReport(report));
402
- }
403
-
404
- /**
405
- * The copies a caller may offer to remove: recognised copies of our own
406
- * program that are shadowing the maintained install. Deduplicated by path,
407
- * since one leftover package install typically provides several commands.
408
- */
409
- export function removableShadows(result: ShadowScanResult): CommandCopy[] {
410
- const byPath = new Map<string, CommandCopy>();
411
- for (const report of result.shadowed) {
412
- for (const copy of report.shadowing) {
413
- if (!copy.removal) continue;
414
- if (!byPath.has(copy.path)) byPath.set(copy.path, copy);
415
- }
416
- }
417
- return [...byPath.values()];
418
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Panel health monitor — backward-compat shim.
3
- *
4
- * Re-exports the SDK's ComponentHealthMonitor so that the TUI and the SDK
5
- * share a single class declaration. This eliminates the TypeScript nominal
6
- * incompatibility that arises from two classes having separate `private`
7
- * field declarations with the same name.
8
- *
9
- * All call-sites that previously imported the TUI-local ComponentHealthMonitor
10
- * now receive the SDK's canonical class without any behavioral change —
11
- * the public API is identical (register/deregister/canRender/recordRender/
12
- * getHealth/getAllHealth/getContract/resetHealth).
13
- */
14
-
15
- export {
16
- ComponentHealthMonitor,
17
- ComponentHealthMonitor as PanelHealthMonitor,
18
- } from '@/runtime/index.ts';
@@ -1,55 +0,0 @@
1
- /**
2
- * provider-optimizer-wiring — bind the provider optimizer to its capability
3
- * gate and seed its persisted routing mode at startup.
4
- *
5
- * Mirrors the SDK composition root's provider-optimizer-wiring module (which
6
- * the SDK does not export through a public seam) so this repo's composition
7
- * fork cannot drift from it silently: the optimizer is constructed dark, the
8
- * gate subscription flips it live, and provider.optimizerMode seeds the mode.
9
- */
10
-
11
- import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
12
- import type { ProviderOptimizer } from '@pellux/goodvibes-sdk/platform/providers';
13
- import type { FeatureFlagManager } from '@/runtime/index.ts';
14
-
15
- export function bindProviderOptimizerFeatureFlag(
16
- featureFlags: Pick<FeatureFlagManager, 'isEnabled' | 'subscribe'>,
17
- providerOptimizer: Pick<ProviderOptimizer, 'setEnabled'>,
18
- ): () => void {
19
- providerOptimizer.setEnabled(featureFlags.isEnabled('provider-optimizer'));
20
- return featureFlags.subscribe((flagId, state) => {
21
- if (flagId === 'provider-optimizer') {
22
- providerOptimizer.setEnabled(state === 'enabled');
23
- }
24
- });
25
- }
26
-
27
- /**
28
- * Apply the persistent provider-optimizer routing mode from config at startup.
29
- * provider.optimizerMode 'off' keeps the optimizer inactive (its gate derives
30
- * from the same key); this only seeds the mode/pin so an operator can persist
31
- * "auto" or a pinned model without re-issuing a /provider command each
32
- * session. Runtime pin/unpin/setMode still override for the live session.
33
- */
34
- export function applyProviderOptimizerConfigMode(
35
- configManager: Pick<ConfigManager, 'get'>,
36
- providerOptimizer: Pick<ProviderOptimizer, 'setMode' | 'pin'>,
37
- ): void {
38
- const mode = configManager.get('provider.optimizerMode');
39
- if (mode === 'off') {
40
- providerOptimizer.setMode('manual'); // inert baseline while inactive
41
- return;
42
- }
43
- if (mode === 'pinned') {
44
- const pinned = configManager.get('provider.optimizerPinnedModel').trim();
45
- const sep = pinned.indexOf(':');
46
- if (sep > 0 && sep < pinned.length - 1) {
47
- providerOptimizer.pin(pinned.slice(0, sep), pinned.slice(sep + 1));
48
- } else {
49
- // Pinned mode requested without a valid provider-qualified model — stay manual.
50
- providerOptimizer.setMode('manual');
51
- }
52
- } else {
53
- providerOptimizer.setMode(mode);
54
- }
55
- }
@@ -1,100 +0,0 @@
1
- /**
2
- * reachability-notice.ts — the two ways a running build can be the wrong one,
3
- * stated in plain words at startup.
4
- *
5
- * The platform's guarantee is that clients auto-update at startup, the daemon
6
- * checks hourly, and nothing ever drifts. Two things break that guarantee
7
- * without breaking anything visible:
8
- *
9
- * 1. Another copy of this command sits EARLIER on PATH. The updater keeps
10
- * maintaining the copy it installed; the shell keeps running the other
11
- * one. Both installs "succeed", the version number reports itself
12
- * current, and an older build answers every question.
13
- * 2. This build is simply behind the latest release and, for whatever
14
- * reason, did not update itself — a package-managed install, a failed
15
- * swap, a check that could not reach the network.
16
- *
17
- * Either way the user finds out by being told a capability does not exist. A
18
- * build that knows it is not the current one must say so before anything
19
- * else, so this module turns those two facts into lines and the wiring in
20
- * path-shadow-startup.ts prints them ahead of the session.
21
- *
22
- * Pure by construction: it is handed a completed scan and two version strings
23
- * and decides only what to say.
24
- */
25
-
26
- import { compareVersions, normalizeVersion } from './update-check.ts';
27
- import { describeShadowReport, type ShadowScanResult } from './path-shadow.ts';
28
-
29
- export type ReachabilityNoticeKind = 'shadowed' | 'not-on-path' | 'behind';
30
-
31
- export interface ReachabilityNotice {
32
- readonly kind: ReachabilityNoticeKind;
33
- /** Plain lines, already in the order they should be read. */
34
- readonly lines: readonly string[];
35
- }
36
-
37
- export interface ReachabilityNoticeInput {
38
- /** The completed PATH scan for this command. */
39
- readonly scan: ShadowScanResult;
40
- /** The version this process is running. */
41
- readonly runningVersion: string;
42
- /** The newest released version, or undefined when it could not be determined. */
43
- readonly latestVersion?: string | undefined;
44
- /** The exact command that brings this install up to date. */
45
- readonly updateCommand: string;
46
- }
47
-
48
- /**
49
- * Builds the notices for this startup. Returns an empty list for the healthy
50
- * case — one reachable copy, running the latest release — so a normal start
51
- * says nothing at all.
52
- */
53
- export function buildReachabilityNotices(input: ReachabilityNoticeInput): ReachabilityNotice[] {
54
- const notices: ReachabilityNotice[] = [];
55
-
56
- for (const report of input.scan.shadowed) {
57
- const lines = describeShadowReport(report);
58
- if (lines.length === 0) continue;
59
- notices.push({
60
- kind: report.installDirNotOnPath ? 'not-on-path' : 'shadowed',
61
- lines: [
62
- ...lines,
63
- report.installDirNotOnPath
64
- ? 'Until then, run it by its full path.'
65
- : 'Until then, updating this install changes nothing you can reach by name.',
66
- ],
67
- });
68
- }
69
-
70
- const behind = describeVersionGap(input);
71
- if (behind) notices.push(behind);
72
-
73
- return notices;
74
- }
75
-
76
- /**
77
- * The staleness line. Deliberately silent when the latest version is unknown:
78
- * an unreachable network is not evidence of being behind, and saying so would
79
- * be the same kind of false certainty this module exists to remove.
80
- */
81
- function describeVersionGap(input: ReachabilityNoticeInput): ReachabilityNotice | undefined {
82
- if (!input.latestVersion) return undefined;
83
- const running = normalizeVersion(input.runningVersion);
84
- const latest = normalizeVersion(input.latestVersion);
85
- if (running.length === 0 || latest.length === 0) return undefined;
86
- if (compareVersions(running, latest) >= 0) return undefined;
87
- return {
88
- kind: 'behind',
89
- lines: [
90
- `This build is v${running}. The current release is v${latest}, so what you are running is behind.`,
91
- `Anything added since v${running} is genuinely absent from this build — if it says it cannot do something, that may be why.`,
92
- `Update with: ${input.updateCommand}`,
93
- ],
94
- };
95
- }
96
-
97
- /** One flat list of lines, for a surface that prints rather than groups. */
98
- export function reachabilityNoticeLines(notices: readonly ReachabilityNotice[]): string[] {
99
- return notices.flatMap((notice) => [...notice.lines]);
100
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * remote-execution-composition.ts — running work somewhere other than here.
3
- *
4
- * Four collaborators that only make sense together, so they are built together
5
- * rather than as four unrelated lines in the middle of the runtime composition:
6
- *
7
- * - RemoteRunnerRegistry knows which remote runners exist and how to reach
8
- * them; RemoteSupervisor drives them and is meaningless without it.
9
- *
10
- * - SandboxSessionRegistry owns the sandboxes a tool call can be confined to,
11
- * and McpRegistry is the thing that confines them — an MCP server started
12
- * without the sandbox registry runs its tools directly on the host.
13
- *
14
- * The pairing in each case is the point: handing the supervisor a registry it
15
- * did not build, or the MCP registry a sandbox runtime it does not share with
16
- * the session registry, produces a runtime that looks wired and quietly is not.
17
- */
18
- import { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
19
- import {
20
- RemoteRunnerRegistry,
21
- RemoteSupervisor,
22
- SandboxSessionRegistry,
23
- type RuntimeEventBus,
24
- } from '@/runtime/index.ts';
25
- import type { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
26
- import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
27
- import type { HookDispatcher } from '@pellux/goodvibes-sdk/platform/hooks';
28
-
29
- export interface RemoteExecutionServices {
30
- readonly remoteRunnerRegistry: RemoteRunnerRegistry;
31
- readonly remoteSupervisor: RemoteSupervisor;
32
- readonly sandboxSessionRegistry: SandboxSessionRegistry;
33
- readonly mcpRegistry: McpRegistry;
34
- }
35
-
36
- /**
37
- * Build the remote-execution and sandboxing seam.
38
- *
39
- * Constructing these opens no connection and starts no server: a runner is
40
- * reached when something asks for it, and an MCP server starts when a session
41
- * requests it. Composing a runtime in a test therefore executes nothing.
42
- */
43
- export function createRemoteExecutionServices(options: {
44
- readonly agentManager: AgentManager;
45
- readonly workingDirectory: string;
46
- readonly hookDispatcher: HookDispatcher;
47
- readonly configManager: ConfigManager;
48
- readonly runtimeBus: RuntimeEventBus;
49
- }): RemoteExecutionServices {
50
- const remoteRunnerRegistry = new RemoteRunnerRegistry(options.agentManager);
51
- const remoteSupervisor = new RemoteSupervisor(remoteRunnerRegistry);
52
- const sandboxSessionRegistry = new SandboxSessionRegistry(options.workingDirectory);
53
- const mcpRegistry = new McpRegistry({
54
- hookDispatcher: options.hookDispatcher,
55
- sandboxSessions: sandboxSessionRegistry,
56
- });
57
- mcpRegistry.setRuntimeBus(options.runtimeBus);
58
- // The SAME sandbox registry the session registry above owns, so a tool call
59
- // confined by one is confined by the other.
60
- mcpRegistry.setSandboxRuntime(options.configManager, sandboxSessionRegistry);
61
- return { remoteRunnerRegistry, remoteSupervisor, sandboxSessionRegistry, mcpRegistry };
62
- }