@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
@@ -0,0 +1,330 @@
1
+ /**
2
+ * hosted-runtime.ts — `/hosted`, the front door to a conversation the DAEMON
3
+ * runs.
4
+ *
5
+ * Local sessions are unchanged and remain the default experience: a turn typed
6
+ * into the composer runs in this process, exactly as it always has. `/hosted`
7
+ * is the opt-in — it asks the daemon to compose the same loop on its side, so
8
+ * the conversation does not depend on this window staying open.
9
+ *
10
+ * ── The subcommands, and why they are these ───────────────────────────────
11
+ *
12
+ * /hosted what this terminal is attached to, and what
13
+ * leaving would do
14
+ * /hosted new [prompt…] create one here and attach; `--survive` /
15
+ * `--kill` set this session's own detach override
16
+ * /hosted list [--all] every hosted session the daemon has
17
+ * /hosted attach <id|n> join one and backfill its transcript
18
+ * /hosted say <text…> steer the attached session (ordinary verb)
19
+ * /hosted later <text…> queue a follow-up (ordinary verb)
20
+ * /hosted cancel [callId] cancel one in-flight tool call (ordinary verb)
21
+ * /hosted detach leave — the policy the record names then applies
22
+ * /hosted kill [id] end it regardless of policy
23
+ *
24
+ * There is no `/hosted steer` beside `say` and no hosted-only cancel: those
25
+ * operations are `sessions.steer`, `sessions.followUp` and
26
+ * `sessions.toolCalls.cancel`, which resolve a hosted id daemon-side. This
27
+ * command spells each one once.
28
+ */
29
+ import type { CommandContext, CommandRegistry } from '../command-registry.ts';
30
+ import { describeOperatorRpcError } from './operator-rpc.ts';
31
+ import { requireShellPaths } from './runtime-services.ts';
32
+ import {
33
+ createDaemonVerbCaller,
34
+ resolveControlPlaneBaseUrl,
35
+ resolveDaemonStateDirectory,
36
+ } from '../../runtime/client/operator-endpoint.ts';
37
+ import {
38
+ createHostedSessionsClient,
39
+ describeDetachEffect,
40
+ hostedSessionLabel,
41
+ type HostedDetachPolicy,
42
+ type HostedSessionRecord,
43
+ type HostedSessionsClient,
44
+ } from '../../runtime/client/hosted-sessions.ts';
45
+ import { watchHostedSession, type HostedSessionSubscription } from '../../runtime/client/hosted-session-stream.ts';
46
+ import { getOrCreateCompanionToken } from '@pellux/goodvibes-sdk/platform/pairing';
47
+ import { getSharedHostedSessionFeed, type HostedSessionFeed } from '../../panels/hosted-session-feed.ts';
48
+ import { getSharedHostedSessionRoster } from '../../runtime/client/hosted-roster.ts';
49
+
50
+ /** The last list this terminal printed, so `attach 2` means what the user just read. */
51
+ let lastListedIds: readonly string[] = [];
52
+
53
+ /** One row of `/hosted list`, in the record's own words. */
54
+ export function renderHostedRecordLine(record: HostedSessionRecord, index: number): string {
55
+ const attached = record.attachedClients.length > 0 ? record.attachedClients.join(', ') : 'nobody';
56
+ const ended = record.status === 'terminated'
57
+ ? ` — ended: ${record.terminatedReason ?? 'no reason recorded'}`
58
+ : '';
59
+ return [
60
+ ` ${index + 1}. ${hostedSessionLabel(record)} [${record.status}]${ended}`,
61
+ ` id ${record.id}`,
62
+ ` ${describeDetachEffect(record)}`,
63
+ ` ${record.turnCount} turn(s), ${record.messageCount} message(s); attached: ${attached}`,
64
+ ].join('\n');
65
+ }
66
+
67
+ /** The status block `/hosted` with no arguments prints. */
68
+ export function renderHostedStatus(feed: HostedSessionFeed): string {
69
+ const state = feed.getState();
70
+ if (!state.record) {
71
+ return [
72
+ 'No hosted session is attached in this terminal.',
73
+ ' A hosted session runs inside the daemon, so it can outlive this window.',
74
+ ' /hosted new [prompt] start one and attach',
75
+ ' /hosted list see what already exists',
76
+ ].join('\n');
77
+ }
78
+ const record = state.record;
79
+ return [
80
+ `Attached to ${hostedSessionLabel(record)} [${record.status}]`,
81
+ ` id ${record.id}`,
82
+ ` workspace ${record.workspaceRoot}`,
83
+ ` ${describeDetachEffect(record)}`,
84
+ ` ${record.turnCount} turn(s), ${record.messageCount} message(s)`,
85
+ state.streaming
86
+ ? ' live event stream open'
87
+ : ` no live stream — ${state.streamNote ?? 'not subscribed'}`,
88
+ state.runningToolCalls.length > 0
89
+ ? ` running: ${state.runningToolCalls.map((call) => `${call.tool} (${call.callId})`).join(', ')}`
90
+ : ' no tool call is running',
91
+ ].join('\n');
92
+ }
93
+
94
+ /**
95
+ * Read `--survive` / `--kill` out of the arguments.
96
+ *
97
+ * Absent means "follow the `hostedSessions.detachPolicy` setting", which is a
98
+ * different thing from either value and is what most sessions want: the record
99
+ * then reports the setting's current answer rather than a snapshot of it.
100
+ */
101
+ export function readDetachOverride(args: readonly string[]): {
102
+ readonly policy: HostedDetachPolicy | undefined;
103
+ readonly rest: string[];
104
+ } {
105
+ const rest: string[] = [];
106
+ let policy: HostedDetachPolicy | undefined;
107
+ for (const arg of args) {
108
+ if (arg === '--survive') { policy = 'survive'; continue; }
109
+ if (arg === '--kill') { policy = 'kill'; continue; }
110
+ rest.push(arg);
111
+ }
112
+ return { policy, rest };
113
+ }
114
+
115
+ interface HostedCommandSeams {
116
+ readonly client: HostedSessionsClient;
117
+ readonly baseUrl: string | null;
118
+ readonly authToken: string | null;
119
+ }
120
+
121
+ /**
122
+ * Resolve everything a `/hosted` subcommand needs, or refuse honestly.
123
+ *
124
+ * The verbs go through `createDaemonVerbCaller` because every
125
+ * `sessions.hosted.*` verb is ws-declared with no REST path; the stream needs
126
+ * the base URL and bearer directly, which is the same resolution the verb
127
+ * caller performs internally.
128
+ */
129
+ function resolveSeams(context: CommandContext): HostedCommandSeams | null {
130
+ const configManager = context.platform.configManager;
131
+ const homeDirectory = (): string => requireShellPaths(context).homeDirectory;
132
+ const client = createHostedSessionsClient(createDaemonVerbCaller({ configManager, homeDirectory }));
133
+ const baseUrl = resolveControlPlaneBaseUrl(configManager);
134
+ if (!baseUrl) return { client, baseUrl: null, authToken: null };
135
+ let authToken: string | null = null;
136
+ try {
137
+ authToken = getOrCreateCompanionToken('tui', {
138
+ daemonHomeDir: resolveDaemonStateDirectory(homeDirectory()),
139
+ }).token;
140
+ } catch {
141
+ // A token this terminal cannot mint is a stream it cannot open; the verbs
142
+ // resolve their own and still work, so this is not a refusal of the command.
143
+ authToken = null;
144
+ }
145
+ return { client, baseUrl, authToken };
146
+ }
147
+
148
+ /** Open the live stream for the attached session, and say so in the feed either way. */
149
+ async function openStream(
150
+ seams: HostedCommandSeams,
151
+ sessionId: string,
152
+ feed: HostedSessionFeed,
153
+ ): Promise<void> {
154
+ // The feed owns the subscription handle: the exit path has to be able to
155
+ // close it too, and it has no way to reach a variable in this module.
156
+ feed.closeStream();
157
+ if (!seams.baseUrl) {
158
+ feed.setStreaming(false, 'no control-plane base URL is configured, so nothing can be watched live');
159
+ return;
160
+ }
161
+ if (!seams.authToken) {
162
+ feed.setStreaming(false, 'no bearer token could be read for the event stream');
163
+ return;
164
+ }
165
+ const token = seams.authToken;
166
+ const subscription: HostedSessionSubscription | null = await watchHostedSession({
167
+ baseUrl: seams.baseUrl,
168
+ sessionId,
169
+ getAuthToken: () => token,
170
+ onEvent: (event) => feed.apply(event),
171
+ onLifecycle: (update) => feed.applyLifecycle(update),
172
+ onTerminate: (error) => {
173
+ feed.setStreaming(false, `the event stream ended: ${describeOperatorRpcError(error)}`);
174
+ },
175
+ });
176
+ feed.bindStream(subscription ? () => subscription.close() : null);
177
+ feed.setStreaming(
178
+ subscription !== null,
179
+ subscription === null ? 'the daemon would not open an event stream' : null,
180
+ );
181
+ }
182
+
183
+ /** Attach to a session by id, backfill it, and start watching it. */
184
+ async function attachSession(
185
+ seams: HostedCommandSeams,
186
+ sessionId: string,
187
+ feed: HostedSessionFeed,
188
+ context: CommandContext,
189
+ ): Promise<void> {
190
+ const attachment = await seams.client.attach(sessionId);
191
+ feed.attach(attachment.session, attachment.history);
192
+ await openStream(seams, attachment.session.id, feed);
193
+ context.print([
194
+ `[hosted] attached to ${hostedSessionLabel(attachment.session)} (${attachment.history.length} message(s) backfilled)`,
195
+ ` ${describeDetachEffect(attachment.session)}`,
196
+ ].join('\n'));
197
+ context.showPanel?.('hosted');
198
+ }
199
+
200
+ /** Turn `attach 2` into the id the user just read off `/hosted list`. */
201
+ function resolveIdArgument(argument: string): string {
202
+ const index = Number.parseInt(argument, 10);
203
+ if (Number.isInteger(index) && index >= 1 && index <= lastListedIds.length) {
204
+ return lastListedIds[index - 1] as string;
205
+ }
206
+ return argument;
207
+ }
208
+
209
+ export function registerHostedRuntimeCommands(registry: CommandRegistry): void {
210
+ registry.register({
211
+ name: 'hosted',
212
+ description: 'Daemon-hosted sessions: start, join, steer and leave a conversation whose loop runs in the daemon',
213
+ usage: '[new|list|attach|say|later|cancel|detach|kill] [args]',
214
+ argsHint: '[new|list|attach|say|later|cancel|detach|kill]',
215
+ async handler(args, ctx) {
216
+ const feed = getSharedHostedSessionFeed();
217
+ const sub = (args[0] ?? '').toLowerCase();
218
+
219
+ if (sub === '' || sub === 'status') {
220
+ ctx.print(renderHostedStatus(feed));
221
+ return;
222
+ }
223
+
224
+ const seams = resolveSeams(ctx);
225
+ if (!seams) return;
226
+ const attachedId = feed.getState().record?.id ?? null;
227
+
228
+ try {
229
+ switch (sub) {
230
+ case 'new': {
231
+ const { policy, rest } = readDetachOverride(args.slice(1));
232
+ const workspaceRoot = requireShellPaths(ctx).workingDirectory;
233
+ const prompt = rest.join(' ').trim();
234
+ const record = await seams.client.create({
235
+ workspaceRoot,
236
+ ...(prompt ? { initialPrompt: prompt } : {}),
237
+ ...(policy ? { detachPolicy: policy } : {}),
238
+ });
239
+ ctx.print([
240
+ `[hosted] created ${hostedSessionLabel(record)} in ${record.workspaceRoot}`,
241
+ ` ${describeDetachEffect(record)}`,
242
+ ].join('\n'));
243
+ await attachSession(seams, record.id, feed, ctx);
244
+ return;
245
+ }
246
+ case 'list': {
247
+ const includeTerminated = args.includes('--all');
248
+ const records = await seams.client.list({ includeTerminated });
249
+ lastListedIds = records.map((record) => record.id);
250
+ // The session picker reads the same roster, so a list typed here is
251
+ // the list it shows — one answer, not two that drift.
252
+ if (!includeTerminated) getSharedHostedSessionRoster().accept(records);
253
+ if (records.length === 0) {
254
+ ctx.print(includeTerminated
255
+ ? '[hosted] the daemon is hosting no sessions, and has no retained terminated ones.'
256
+ : '[hosted] the daemon is hosting no sessions. Add --all to include ones that have ended.');
257
+ return;
258
+ }
259
+ ctx.print([
260
+ `Hosted sessions (${records.length}${includeTerminated ? ', including ended' : ''}):`,
261
+ ...records.map(renderHostedRecordLine),
262
+ '',
263
+ ' /hosted attach <id or number>',
264
+ ].join('\n'));
265
+ return;
266
+ }
267
+ case 'attach': {
268
+ const target = args[1];
269
+ if (!target) { ctx.print('Usage: /hosted attach <id or list number>'); return; }
270
+ await attachSession(seams, resolveIdArgument(target), feed, ctx);
271
+ return;
272
+ }
273
+ case 'say':
274
+ case 'later': {
275
+ if (!attachedId) { ctx.print('[hosted] no hosted session is attached — /hosted attach <id> first.'); return; }
276
+ const body = args.slice(1).join(' ').trim();
277
+ if (!body) { ctx.print(`Usage: /hosted ${sub} <text>`); return; }
278
+ if (sub === 'say') await seams.client.steer(attachedId, body);
279
+ else await seams.client.followUp(attachedId, body);
280
+ ctx.print(sub === 'say'
281
+ ? '[hosted] sent — its output arrives on the Hosted Session panel.'
282
+ : '[hosted] queued — it runs after the current turn.');
283
+ return;
284
+ }
285
+ case 'cancel': {
286
+ if (!attachedId) { ctx.print('[hosted] no hosted session is attached.'); return; }
287
+ const running = feed.getState().runningToolCalls;
288
+ const callId = args[1] ?? running[0]?.callId;
289
+ if (!callId) { ctx.print('[hosted] no tool call is running in this session. Pass a callId to cancel a specific one.'); return; }
290
+ const cancelled = await seams.client.cancelToolCall(attachedId, callId);
291
+ ctx.print(cancelled
292
+ ? `[hosted] cancelled tool call ${callId}.`
293
+ : `[hosted] the daemon did not cancel ${callId} — it may have already settled.`);
294
+ return;
295
+ }
296
+ case 'detach': {
297
+ if (!attachedId) { ctx.print('[hosted] no hosted session is attached.'); return; }
298
+ const record = await seams.client.detach(attachedId);
299
+ feed.clear();
300
+ ctx.print(record.status === 'terminated'
301
+ ? `[hosted] detached — the session ended (${record.terminatedReason ?? 'no reason recorded'}), which is what its detach policy said would happen.`
302
+ : '[hosted] detached — the session is still running in the daemon and can be reattached.');
303
+ return;
304
+ }
305
+ case 'kill': {
306
+ const target = args[1] ? resolveIdArgument(args[1]) : attachedId;
307
+ if (!target) { ctx.print('Usage: /hosted kill <id> (or attach one first)'); return; }
308
+ const record = await seams.client.kill(target);
309
+ if (target === attachedId) feed.clear();
310
+ ctx.print(`[hosted] ended ${hostedSessionLabel(record)} — ${record.terminatedReason ?? 'no reason recorded'}.`);
311
+ return;
312
+ }
313
+ default:
314
+ ctx.print('Usage: /hosted [status|new|list|attach|say|later|cancel|detach|kill]');
315
+ return;
316
+ }
317
+ } catch (error) {
318
+ ctx.print(`[hosted] ${describeOperatorRpcError(error)}`);
319
+ }
320
+ },
321
+ });
322
+ }
323
+
324
+ /**
325
+ * Tests drive the module-level list memory (`/hosted attach 2`); this resets it
326
+ * between them. The live stream is the feed's, and is reset with the feed.
327
+ */
328
+ export function resetHostedCommandState(): void {
329
+ lastListedIds = [];
330
+ }
@@ -4,7 +4,7 @@ import type { CommandContext } from '../command-registry.ts';
4
4
  import { discoverSkills } from '../../panels/skills-panel.ts';
5
5
  import { buildSandboxReview, isRunningInWsl } from '@/runtime/index.ts';
6
6
  import { renderQemuWrapperTemplate } from '@/runtime/index.ts';
7
- import { getPluginDirectories } from '../../plugins/loader';
7
+ import { getPluginDirectories } from '@pellux/goodvibes-sdk/platform/plugins';
8
8
  import { listBuiltinSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
9
9
  import type { SetupReviewSnapshot } from './local-setup-transfer.ts';
10
10
  import { requireProviderApi, requireReadModels, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from './runtime-services.ts';
@@ -1,8 +1,8 @@
1
1
  import { dirname, join, resolve } from 'node:path';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import type { CommandContext } from '../command-registry.ts';
4
- import type { ConfigKey } from '../../config/index.ts';
5
- import { CONFIG_SCHEMA } from '../../config/index.ts';
4
+ import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
5
+ import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
6
6
  import { requireShellPaths } from './runtime-services.ts';
7
7
 
8
8
  export interface SetupReviewSnapshot {
@@ -1,9 +1,9 @@
1
1
  import { dirname, join } from 'path';
2
2
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
- import { atomicWriteFileSync } from '../../config/atomic-write.ts';
3
+ import { atomicWriteFileSync } from '@pellux/goodvibes-sdk/platform/config';
4
4
  import type { CommandRegistry } from '../command-registry.ts';
5
- import type { ConfigKey } from '../../config/index.ts';
6
- import { CONFIG_SCHEMA } from '../../config/index.ts';
5
+ import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
6
+ import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
7
7
  import { listHookPointContracts } from '@pellux/goodvibes-sdk/platform/hooks';
8
8
  import { renderQemuWrapperTemplate } from '@/runtime/index.ts';
9
9
  import type { SetupTransferBundle } from './local-setup-transfer.ts';
@@ -2,8 +2,8 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, resolve } from 'node:path';
3
3
  import type { CommandRegistry } from '../command-registry.ts';
4
4
  import { profileDataToConfigSnapshot } from '@pellux/goodvibes-sdk/platform/profiles';
5
- import { CONFIG_SCHEMA, type ConfigKey } from '../../config/index.ts';
6
- import { getProviderIdFromModel } from '../../config/provider-model.ts';
5
+ import { CONFIG_SCHEMA, type ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
6
+ import { getProviderIdFromModel } from '@pellux/goodvibes-sdk/platform/providers';
7
7
  import { CONFIG_KEYS } from '@pellux/goodvibes-sdk/platform/config';
8
8
  import type { ManagedSettingsBundle } from '@/runtime/index.ts';
9
9
  import {
@@ -1,103 +1,35 @@
1
1
  /**
2
- * operator-rpc.ts
2
+ * operator-rpc.ts — the command layer's handle on the daemon.
3
3
  *
4
- * Generic operator-verb dispatch for gateway methods that do not (yet) have a
5
- * named facade on the in-process `OperatorClient` (`ctx.clients.operator`,
6
- * always DirectTransport-backed in this TUI — see bootstrap-shell.ts). The
7
- * initiative cluster (`ci.*`, `checkin.*`, `principals.*`,
8
- * `channels.profiles.*`) ships in the operator contract but has not been
9
- * promoted to that narrow facade, so commands reach it the same way any
10
- * external operator client would: a real HTTP round-trip to the currently
11
- * configured control-plane daemon, using `createGoodVibesSdk`'s generic
12
- * `sdk.operator.invoke(methodId, input)` (typed against the installed
13
- * contract — see `@pellux/goodvibes-contracts`).
4
+ * The resolution itself (is the daemon enabled, what base URL, what bearer)
5
+ * moved to runtime/client/operator-endpoint.ts when the terminal app became a
6
+ * pure client: the runtime seams — approvals, config, credentials, sessions,
7
+ * fleet, tasks, devices, checkpoints — all need the same answer, and two copies
8
+ * of it is how one call ended up on a DirectTransport while another made a real
9
+ * request. This module keeps the command-context-shaped entry point and
10
+ * re-exports the rest so no command import site had to change.
14
11
  *
15
- * This is deliberately a fresh, lightweight connection per call (no pooling,
16
- * no persistent socket) — these are low-frequency, operator-initiated admin
17
- * calls, not hot-path session traffic. `getOperatorRpc` never throws: it
18
- * returns `{ available: false, reason }` up front for every case the caller
19
- * can decide about statically (daemon disabled, no reachable base URL), so
20
- * commands can print an honest "not available" line instead of guessing.
21
- * Once a call is made, a non-2xx response (including the 404 a not-yet-wired
22
- * verb returns) surfaces to the caller as a thrown `GoodVibesSdkError` —
23
- * callers should catch and render `describeOperatorRpcError` rather than
24
- * pretend the request succeeded.
12
+ * Every command verb is now a real HTTP round-trip to the configured
13
+ * control-plane daemon; there is no in-process catalog left to answer one.
25
14
  */
26
- import { join } from 'node:path';
27
- import { createGoodVibesSdk } from '@pellux/goodvibes-sdk';
28
- import type { GoodVibesSdk } from '@pellux/goodvibes-sdk';
29
- import { GoodVibesSdkError } from '@pellux/goodvibes-sdk';
30
- import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
31
- import { resolveDaemonEnabled } from '@pellux/goodvibes-sdk/platform/config';
32
- import { getOrCreateCompanionToken } from '@pellux/goodvibes-sdk/platform/pairing';
15
+ export {
16
+ describeOperatorRpcError,
17
+ resolveOperatorRpc,
18
+ type OperatorRpc,
19
+ type OperatorRpcAvailable,
20
+ type OperatorRpcUnavailable,
21
+ } from '../../runtime/client/operator-endpoint.ts';
22
+
23
+ import { resolveOperatorRpc } from '../../runtime/client/operator-endpoint.ts';
24
+ import type { OperatorRpc } from '../../runtime/client/operator-endpoint.ts';
33
25
  import type { CommandContext } from '../command-registry.ts';
34
26
  import { requireShellPaths } from './runtime-services.ts';
35
27
 
36
- export interface OperatorRpcUnavailable {
37
- readonly available: false;
38
- readonly reason: string;
39
- }
40
-
41
- export interface OperatorRpcAvailable {
42
- readonly available: true;
43
- readonly sdk: GoodVibesSdk;
44
- }
45
-
46
- export type OperatorRpc = OperatorRpcUnavailable | OperatorRpcAvailable;
47
-
48
- function resolveControlPlaneBaseUrl(configManager: ConfigManager): string | null {
49
- // An explicitly declared external address wins; otherwise the URL is DERIVED
50
- // from hostMode/host/port/tls.mode. This used to prefer a stored
51
- // `controlPlane.baseUrl`, which had no writers and so drifted from the bind
52
- // on port, scheme, and host at once.
53
- // The cast drops once a published SDK carries this key in ConfigKey; the
54
- // installed 1.14.0 predates it (same idiom cloudflare-control-plane.ts uses).
55
- const explicit = String(configManager.get('controlPlane.publicBaseUrl' as never) ?? '').trim();
56
- if (explicit) return explicit.replace(/\/+$/, '');
57
- const host = String(configManager.get('controlPlane.host') ?? '').trim();
58
- const port = configManager.get('controlPlane.port');
59
- if (host && typeof port === 'number' && port > 0) {
60
- const scheme = String(configManager.get('controlPlane.tls.mode') ?? 'off') !== 'off' ? 'https' : 'http';
61
- // A wildcard bind is not a dial target; loopback is the interface it answers on.
62
- const dialHost = host === '0.0.0.0' || host === '::' ? '127.0.0.1' : host;
63
- return `${scheme}://${dialHost.includes(':') && !dialHost.startsWith('[') ? `[${dialHost}]` : dialHost}:${port}`;
64
- }
65
- return null;
66
- }
67
-
68
28
  /**
69
- * Context-free core of {@link getOperatorRpc}: resolve (or honestly refuse to
70
- * resolve) an operator SDK client wired to this workspace's control-plane
71
- * daemon from just the two things the resolution actually needs — the config
72
- * manager and the home directory. Shared by the command layer (via
73
- * getOperatorRpc) and the Fleet panel's gateway (fleet-gateway.ts) so both
74
- * reach the same daemon over the same generic invoke path, never two divergent
75
- * clients. Refusal reasons are surfaced verbatim so callers print them directly.
76
- */
77
- export function resolveOperatorRpc(deps: { readonly configManager: ConfigManager; readonly homeDirectory: string | (() => string) }): OperatorRpc {
78
- const { configManager } = deps;
79
- if (!resolveDaemonEnabled(configManager)) {
80
- return { available: false, reason: 'the daemon is disabled (daemon.enabled=false) — no operator surface to reach. Enable it in /settings, then retry.' };
81
- }
82
- const baseUrl = resolveControlPlaneBaseUrl(configManager);
83
- if (!baseUrl) {
84
- return { available: false, reason: 'no control-plane base URL is configured (controlPlane.publicBaseUrl / controlPlane.host+port) — cannot reach the operator surface.' };
85
- }
86
- // Resolve the home directory only AFTER the static refusals — a caller whose
87
- // shell paths are not wired (a disabled-daemon path) must still get the honest
88
- // unavailable reason above, never a "shell paths not wired" throw.
89
- const homeDirectory = typeof deps.homeDirectory === 'function' ? deps.homeDirectory() : deps.homeDirectory;
90
- const daemonHomeDir = join(homeDirectory, '.goodvibes', 'daemon');
91
- const token = getOrCreateCompanionToken('tui', { daemonHomeDir }).token;
92
- const sdk = createGoodVibesSdk({ baseUrl, authToken: token });
93
- return { available: true, sdk };
94
- }
95
-
96
- /**
97
- * Resolve (or honestly refuse to resolve) an operator SDK client wired to
98
- * this workspace's control-plane daemon. Reasons for refusal are surfaced
99
- * verbatim to the caller so `/ci`, `/checkin`, and `/principals` can print
100
- * them directly rather than inventing their own wording.
29
+ * Resolve (or honestly refuse to resolve) an operator SDK client wired to this
30
+ * workspace's control-plane daemon. Reasons for refusal are surfaced verbatim
31
+ * to the caller so commands print them directly rather than inventing their own
32
+ * wording.
101
33
  */
102
34
  export function getOperatorRpc(context: CommandContext): OperatorRpc {
103
35
  return resolveOperatorRpc({
@@ -107,21 +39,3 @@ export function getOperatorRpc(context: CommandContext): OperatorRpc {
107
39
  homeDirectory: () => requireShellPaths(context).homeDirectory,
108
40
  });
109
41
  }
110
-
111
- /**
112
- * Render a thrown operator-rpc error honestly: a 404 means this daemon has
113
- * not wired a handler for the verb (a live local runtime that simply doesn't
114
- * implement it yet), never "no result" or a fabricated empty state.
115
- */
116
- export function describeOperatorRpcError(error: unknown): string {
117
- if (error instanceof GoodVibesSdkError) {
118
- if (error.status === 404) {
119
- return 'the connected daemon returned 404 — this operator verb is not wired up on that daemon yet.';
120
- }
121
- if (error.status === 401 || error.status === 403) {
122
- return `the connected daemon rejected the request (${error.status}): ${error.message}`;
123
- }
124
- return `operator request failed${error.status ? ` (${error.status})` : ''}: ${error.message}`;
125
- }
126
- return error instanceof Error ? error.message : String(error);
127
- }
@@ -59,7 +59,7 @@
59
59
 
60
60
  import type { CommandRegistry, CommandContext } from '../command-registry.ts';
61
61
  import { persistSecretBackedConfigValue } from '../../config/secret-config.ts';
62
- import type { ConfigKey } from '../../config/index.ts';
62
+ import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
63
63
  import { describeCardEntryRefusal, mayOfferCardEntryFlow } from '@pellux/goodvibes-sdk/platform/payments';
64
64
  import {
65
65
  PAYMENTS_CARD_NUMBER_CONFIG_KEY,
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
- import type { ConfigManager, ConfigKey } from '../../config/index.ts';
3
- import { CONFIG_SCHEMA } from '../../config/index.ts';
2
+ import type { ConfigManager, ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
3
+ import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
4
4
  import { SHIPPED_CREDENTIAL_READ_RULES } from '@pellux/goodvibes-sdk/platform/permissions';
5
5
 
6
6
  // ---------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  import { resolve } from 'path';
2
2
  import type { PluginStatus } from '@pellux/goodvibes-sdk/platform/plugins';
3
- import { getPluginDirectories, getUserPluginDirectory } from '../../plugins/loader';
3
+ import { getPluginDirectories, getUserPluginDirectory } from '@pellux/goodvibes-sdk/platform/plugins';
4
4
  import type { CommandRegistry } from '../command-registry.ts';
5
5
  import {
6
6
  installEcosystemCatalogEntry,
@@ -19,7 +19,7 @@ import type { RouteExplanation } from '@pellux/goodvibes-sdk/platform/providers'
19
19
  import type { FallbackTestResult, FallbackTransition } from '@pellux/goodvibes-sdk/platform/providers';
20
20
  import type { ProviderApiModelRecord } from '@pellux/goodvibes-sdk/platform/providers';
21
21
  import { requireProviderApi } from './runtime-services.ts';
22
- import { featureEnablementWrite } from '../../runtime/feature-settings.ts';
22
+ import { featureEnablementWrite } from '@pellux/goodvibes-terminal-shell';
23
23
 
24
24
  const PROVIDER_OPTIMIZER_FLAG = 'provider-optimizer';
25
25
 
@@ -1,13 +1,20 @@
1
1
  import type { CommandContext } from '../command-registry.ts';
2
2
  import type { CommandRegistry } from '../command-registry.ts';
3
3
  import { generateQrMatrix, renderQrToString } from '@pellux/goodvibes-sdk/platform/pairing';
4
+ import { RELAY_STATE_NOT_READABLE_HERE } from '../../runtime/relay-reachability-bridge.ts';
4
5
 
5
6
  /**
6
- * Register the /relay command — reachability status and QR-encodable pairing
7
- * for the SDK's outbound zero-knowledge relay (relay.* settings, gated by the
8
- * `relay-connect` feature flag). The live registration state lives only in
9
- * the running daemon's memory (`DaemonServer.getRelayReachability()`), reached
10
- * here through `ctx.platform.externalServices` — see relay-reachability-bridge.ts.
7
+ * Register the /relay command — the relay's configuration, its reachability
8
+ * state, and a QR-encodable pairing payload for the SDK's outbound
9
+ * zero-knowledge relay (relay.* settings, gated by the `relay-connect` feature
10
+ * flag).
11
+ *
12
+ * The CONFIGURATION half is read here, from this terminal's own config. The
13
+ * LIVE half is not: registration state and pairing live in the running daemon's
14
+ * memory (`DaemonServer.getRelayReachability()`), and no verb exposes either to
15
+ * a client — so both read 'unavailable' with the reason said out loud rather
16
+ * than a state this terminal is in no position to know. See
17
+ * relay-reachability-bridge.ts.
11
18
  */
12
19
 
13
20
  function relayConfigured(ctx: CommandContext): { enabled: boolean; url: string; rendezvousId: string; label: string; flagOn: boolean } {
@@ -32,14 +39,16 @@ async function renderStatus(ctx: CommandContext): Promise<void> {
32
39
  ].join('\n'));
33
40
  return;
34
41
  }
35
- const live = ctx.platform.externalServices?.relayStatus() ?? 'disabled';
36
- const state = live === 'registered' ? 'registered' : live === 'disabled' ? 'disabled' : 'offline';
42
+ const live = ctx.platform.externalServices?.relayStatus() ?? 'unavailable';
43
+ const state = live === 'registered' || live === 'disabled' || live === 'unavailable' ? live : 'offline';
37
44
  ctx.print([
38
45
  `Relay: ${state}`,
39
46
  ` rendezvous id: ${cfg.rendezvousId || '(not yet minted — start the daemon to generate one)'}`,
40
47
  ` url: ${cfg.url || '(not set)'}`,
41
48
  ` label: ${cfg.label || '(not set)'}`,
42
- ` live connection state: ${live}`,
49
+ state === 'unavailable'
50
+ ? ` ${RELAY_STATE_NOT_READABLE_HERE}`
51
+ : ` live connection state: ${live}`,
43
52
  ' The relay operator sees only ciphertext and connection metadata — self-host your own relay for full control.',
44
53
  ].join('\n'));
45
54
  }
@@ -57,7 +66,7 @@ async function renderPair(ctx: CommandContext): Promise<void> {
57
66
  }
58
67
  const minted = await externalServices.mintRelayPairing();
59
68
  if (!minted) {
60
- ctx.print('Could not mint a relay pairing payload — the relay connection may not be registered yet. Check /relay status.');
69
+ ctx.print(`Relay pairing cannot be minted from here. ${RELAY_STATE_NOT_READABLE_HERE}`);
61
70
  return;
62
71
  }
63
72
  const qrMatrix = generateQrMatrix(minted.encoded);
@@ -42,7 +42,7 @@ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
42
42
  import type { WorkspaceCheckpoint, WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
43
43
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
44
44
  import { buildRewindReceiptBlock } from '../../core/rewind-receipt.ts';
45
- import { getTurnAnchors, type TurnAnchor } from '../../core/rewind-turn-anchors.ts';
45
+ import { getTurnAnchors, type TurnAnchor } from '@pellux/goodvibes-sdk/platform/rewind';
46
46
  import { createConversationRewindPort, type ConversationRewindPort } from '../../runtime/conversation-rewind-port.ts';
47
47
  import { requirePanelManager } from './runtime-services.ts';
48
48
  import { shortId } from './checkpoint-runtime.ts';
@@ -14,7 +14,7 @@ import type { CompactionQualityScore } from '../../renderer/compaction-quality.t
14
14
  import type { UiReadModels } from '../../runtime/ui-read-models.ts';
15
15
  import type { ShellPathService, SessionSurface } from '@/runtime/index.ts';
16
16
  import type { EcosystemCatalogPathOptions } from '@/runtime/index.ts';
17
- import type { PluginPathOptions } from '../../plugins/loader';
17
+ import type { PluginPathOptions } from '@pellux/goodvibes-sdk/platform/plugins';
18
18
  import type { DirectTransport } from '@/runtime/index.ts';
19
19
  import type { KnowledgeApi } from '@pellux/goodvibes-sdk/platform/knowledge';
20
20
  import type { HookApi } from '@pellux/goodvibes-sdk/platform/hooks';