@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,110 @@
1
+ /**
2
+ * hosted-roster.ts — the last answer the daemon gave about what it is hosting.
3
+ *
4
+ * The session picker is where a person goes to ask "what sessions are there?",
5
+ * and the honest answer includes conversations running inside the
6
+ * daemon — not only this terminal's saved transcripts and the cross-surface
7
+ * union. The picker is a synchronous render over modal state, though, and
8
+ * `sessions.hosted.list` is a round trip. This roster is the seam between them:
9
+ * it holds the last list the daemon answered with, refreshes on demand, and
10
+ * says plainly when it has never been able to ask.
11
+ *
12
+ * ── Never a fabricated empty list ─────────────────────────────────────────
13
+ *
14
+ * `capturedAt === null` means nobody has successfully read the roster yet,
15
+ * which is a different fact from "the daemon hosts nothing" and renders
16
+ * differently. A refresh that fails keeps the LAST known rows and records the
17
+ * reason, on the same reasoning the fleet poller keeps its rows through a blip:
18
+ * a momentary refusal should not make half the picker blink out.
19
+ *
20
+ * ── Why the client is bound rather than passed ────────────────────────────
21
+ *
22
+ * The picker is constructed in the input layer, which has no config manager and
23
+ * no home directory to resolve a daemon from. The composition root
24
+ * (runtime/services.ts) has both and already builds the verb caller, so it binds
25
+ * the client here once — the same shape the shared notification feed uses for a
26
+ * surface that two unrelated layers read.
27
+ */
28
+ import type { HostedSessionRecord, HostedSessionsClient } from './hosted-sessions.ts';
29
+ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
30
+
31
+ export interface HostedRosterSnapshot {
32
+ readonly sessions: readonly HostedSessionRecord[];
33
+ /** When the daemon last answered, or null when it never has. */
34
+ readonly capturedAt: number | null;
35
+ /** Why the roster is not current. Null when the last read succeeded. */
36
+ readonly note: string | null;
37
+ }
38
+
39
+ const NEVER_READ: HostedRosterSnapshot = { sessions: [], capturedAt: null, note: null };
40
+
41
+ export class HostedSessionRoster {
42
+ private state: HostedRosterSnapshot = NEVER_READ;
43
+ private client: HostedSessionsClient | null = null;
44
+ private readonly listeners = new Set<() => void>();
45
+ private inFlight: Promise<void> | null = null;
46
+
47
+ bindClient(client: HostedSessionsClient | null): void {
48
+ this.client = client;
49
+ }
50
+
51
+ snapshot(): HostedRosterSnapshot {
52
+ return this.state;
53
+ }
54
+
55
+ subscribe(listener: () => void): () => void {
56
+ this.listeners.add(listener);
57
+ return () => { this.listeners.delete(listener); };
58
+ }
59
+
60
+ /** Record a list a caller already has in hand (the `/hosted list` path). */
61
+ accept(sessions: readonly HostedSessionRecord[]): void {
62
+ this.state = { sessions, capturedAt: Date.now(), note: null };
63
+ this.emit();
64
+ }
65
+
66
+ /**
67
+ * Ask the daemon again. Never throws and never runs twice at once — a picker
68
+ * opened repeatedly must not stack round trips.
69
+ */
70
+ async refresh(): Promise<void> {
71
+ if (this.inFlight) return await this.inFlight;
72
+ const client = this.client;
73
+ if (!client) {
74
+ this.state = {
75
+ ...this.state,
76
+ note: 'no daemon client is wired in this terminal, so hosted sessions cannot be listed',
77
+ };
78
+ this.emit();
79
+ return;
80
+ }
81
+ this.inFlight = (async () => {
82
+ try {
83
+ this.accept(await client.list());
84
+ } catch (error) {
85
+ this.state = { ...this.state, note: `the daemon did not answer: ${summarizeError(error)}` };
86
+ this.emit();
87
+ } finally {
88
+ this.inFlight = null;
89
+ }
90
+ })();
91
+ await this.inFlight;
92
+ }
93
+
94
+ private emit(): void {
95
+ for (const listener of [...this.listeners]) listener();
96
+ }
97
+ }
98
+
99
+ let sharedRoster: HostedSessionRoster | null = null;
100
+
101
+ /** The one roster the session picker reads and the composition root feeds. */
102
+ export function getSharedHostedSessionRoster(): HostedSessionRoster {
103
+ sharedRoster ??= new HostedSessionRoster();
104
+ return sharedRoster;
105
+ }
106
+
107
+ /** Tests build their own roster; this resets the shared one between them. */
108
+ export function resetSharedHostedSessionRoster(): void {
109
+ sharedRoster = null;
110
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * hosted-session-stream.ts — watching a conversation that is running somewhere
3
+ * else.
4
+ *
5
+ * A hosted session's loop is the ORDINARY Orchestrator, composed inside the
6
+ * daemon. So it emits exactly what a local turn emits — STREAM_DELTA, tool
7
+ * starts, tool results, turn transitions — on the `turn` and `tools` runtime
8
+ * domains, and the control-plane forwards those domains to any subscriber with
9
+ * the session id stamped on every envelope. There is no hosted-only token
10
+ * stream to consume and this file does not invent one: it opens the same event
11
+ * stream a client already uses and keeps the frames whose id matches the
12
+ * session it was told to watch.
13
+ *
14
+ * The third domain is `session`, which carries `hosted-session-update` — the
15
+ * lifecycle channel: created, attached, detached, turn started, turn ended,
16
+ * terminated, restored. That is how an attached terminal learns its session was
17
+ * killed from another surface, or that a turn started that it did not begin.
18
+ *
19
+ * ── Why a refused stream is a value, not a throw ──────────────────────────
20
+ *
21
+ * The same reasoning the SDK's approval-update watcher records: a stream can be
22
+ * refused (no daemon, a 401, a proxy that will not hold a connection), and the
23
+ * caller must still be able to act on the session over the verbs. `watch`
24
+ * resolves to null instead of throwing, and the caller says so honestly rather
25
+ * than pretending the conversation ended.
26
+ */
27
+ import { openServerSentEventStream } from '@/runtime/index.ts';
28
+ import { logger, summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
29
+ import type { HostedSessionUpdatePayload } from '@pellux/goodvibes-sdk/platform/hosted-sessions';
30
+
31
+ /** The domains a hosted session's whole story arrives on. */
32
+ export const HOSTED_SESSION_STREAM_DOMAINS = ['turn', 'tools', 'session'] as const;
33
+
34
+ /** The wire event name the daemon publishes hosted lifecycle notices on. */
35
+ export const HOSTED_SESSION_LIFECYCLE_WIRE_EVENT = 'hosted-session-update';
36
+
37
+ /** One runtime-domain frame, already narrowed to the watched session. */
38
+ export interface HostedSessionStreamEvent {
39
+ readonly domain: 'turn' | 'tools';
40
+ /** The runtime event type, e.g. STREAM_DELTA, TOOL_EXECUTING, TURN_COMPLETED. */
41
+ readonly type: string;
42
+ readonly sessionId: string;
43
+ readonly at: number;
44
+ readonly payload: Record<string, unknown>;
45
+ }
46
+
47
+ export interface WatchHostedSessionOptions {
48
+ /** The daemon's base URL, e.g. `http://127.0.0.1:3421`. */
49
+ readonly baseUrl: string;
50
+ /** The hosted session id to keep frames for. Everything else is discarded. */
51
+ readonly sessionId: string;
52
+ readonly getAuthToken?: (() => string | null | Promise<string | null>) | undefined;
53
+ /** Every turn/tools frame belonging to this session. */
54
+ readonly onEvent: (event: HostedSessionStreamEvent) => void;
55
+ /** Every lifecycle transition of this session. */
56
+ readonly onLifecycle?: ((update: HostedSessionUpdatePayload) => void) | undefined;
57
+ /** The stream dropped for good. The caller decides what to say about it. */
58
+ readonly onTerminate?: ((error: unknown) => void) | undefined;
59
+ readonly fetchImpl?: typeof fetch | undefined;
60
+ readonly signal?: AbortSignal | undefined;
61
+ }
62
+
63
+ /** A live subscription. `close()` is idempotent. */
64
+ export interface HostedSessionSubscription {
65
+ close(): void;
66
+ }
67
+
68
+ /**
69
+ * The control-plane events URL narrowed to the three domains a hosted session
70
+ * speaks on. Narrowing matters: an unnarrowed subscriber receives every domain
71
+ * the daemon publishes, which for a client watching one conversation is a great
72
+ * deal of traffic it would immediately discard.
73
+ */
74
+ export function hostedSessionStreamUrl(baseUrl: string): string {
75
+ const url = new URL('/api/control-plane/events', baseUrl);
76
+ url.searchParams.set('domains', HOSTED_SESSION_STREAM_DOMAINS.join(','));
77
+ return url.toString();
78
+ }
79
+
80
+ /** Read a serialized runtime envelope, or null when the frame is not one. */
81
+ export function readHostedStreamEnvelope(
82
+ domain: 'turn' | 'tools',
83
+ payload: unknown,
84
+ ): HostedSessionStreamEvent | null {
85
+ if (typeof payload !== 'object' || payload === null) return null;
86
+ const envelope = payload as Record<string, unknown>;
87
+ const type = envelope['type'];
88
+ const sessionId = envelope['sessionId'];
89
+ if (typeof type !== 'string' || type.length === 0) return null;
90
+ if (typeof sessionId !== 'string' || sessionId.length === 0) return null;
91
+ const body = envelope['payload'];
92
+ return {
93
+ domain,
94
+ type,
95
+ sessionId,
96
+ at: typeof envelope['ts'] === 'number' ? envelope['ts'] : Date.now(),
97
+ payload: typeof body === 'object' && body !== null ? body as Record<string, unknown> : {},
98
+ };
99
+ }
100
+
101
+ /** Read a hosted lifecycle notice, or null when the frame is not one. */
102
+ export function readHostedLifecycleNotice(payload: unknown): HostedSessionUpdatePayload | null {
103
+ if (typeof payload !== 'object' || payload === null) return null;
104
+ const record = payload as Record<string, unknown>;
105
+ const session = record['session'];
106
+ const event = record['event'];
107
+ if (typeof event !== 'string' || typeof session !== 'object' || session === null) return null;
108
+ if (typeof (session as Record<string, unknown>)['id'] !== 'string') return null;
109
+ return record as unknown as HostedSessionUpdatePayload;
110
+ }
111
+
112
+ /**
113
+ * Open a subscription to one hosted session's live output.
114
+ *
115
+ * Resolves to null when the stream could not be opened; the reason is logged
116
+ * once rather than thrown into a keystroke path, and the caller keeps whatever
117
+ * it had (the verbs still work — the conversation is simply not being watched).
118
+ */
119
+ export async function watchHostedSession(
120
+ options: WatchHostedSessionOptions,
121
+ ): Promise<HostedSessionSubscription | null> {
122
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
123
+ if (typeof fetchImpl !== 'function') {
124
+ logger.debug('[hosted-sessions] no fetch implementation is available for the session stream');
125
+ return null;
126
+ }
127
+ const deliver = (event: HostedSessionStreamEvent): void => {
128
+ if (event.sessionId !== options.sessionId) return;
129
+ try {
130
+ options.onEvent(event);
131
+ } catch (error) {
132
+ // A throwing subscriber must not take the stream down for itself.
133
+ logger.debug('[hosted-sessions] a stream subscriber threw', { error: summarizeError(error) });
134
+ }
135
+ };
136
+ try {
137
+ const close = await openServerSentEventStream(
138
+ fetchImpl,
139
+ hostedSessionStreamUrl(options.baseUrl),
140
+ {
141
+ onEvent: (eventName, payload) => {
142
+ if (eventName === 'turn' || eventName === 'tools') {
143
+ const event = readHostedStreamEnvelope(eventName, payload);
144
+ if (event) deliver(event);
145
+ return;
146
+ }
147
+ if (eventName !== HOSTED_SESSION_LIFECYCLE_WIRE_EVENT) return;
148
+ const notice = readHostedLifecycleNotice(payload);
149
+ if (!notice || notice.session.id !== options.sessionId) return;
150
+ try {
151
+ options.onLifecycle?.(notice);
152
+ } catch (error) {
153
+ logger.debug('[hosted-sessions] a lifecycle subscriber threw', { error: summarizeError(error) });
154
+ }
155
+ },
156
+ onTerminate: ({ error }) => options.onTerminate?.(error),
157
+ },
158
+ {
159
+ ...(options.getAuthToken ? { getAuthToken: options.getAuthToken } : {}),
160
+ ...(options.signal ? { signal: options.signal } : {}),
161
+ },
162
+ );
163
+ let closed = false;
164
+ return {
165
+ close: (): void => {
166
+ if (closed) return;
167
+ closed = true;
168
+ close();
169
+ },
170
+ };
171
+ } catch (error) {
172
+ logger.info('[hosted-sessions] the session stream could not be opened; the session is still steerable over its verbs', {
173
+ sessionId: options.sessionId,
174
+ error: summarizeError(error),
175
+ });
176
+ return null;
177
+ }
178
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * hosted-sessions.ts — this terminal's handle on a conversation the DAEMON runs.
3
+ *
4
+ * A local session's loop lives in this process: the orchestrator, the tools and
5
+ * the permission gate are all here, and closing the terminal ends the work. A
6
+ * HOSTED session is the same loop composed on the other side of the wire, in
7
+ * the daemon, driven by the five `sessions.hosted.*` verbs. Local stays the
8
+ * default experience; hosting is something the user asks for.
9
+ *
10
+ * ── What this module is, and what it deliberately is not ──────────────────
11
+ *
12
+ * It is the five lifecycle verbs plus the ORDINARY session verbs a hosted id
13
+ * also answers to. There is no `sessions.hosted.steer` and this file does not
14
+ * invent one: `sessions.steer`, `sessions.followUp` and
15
+ * `sessions.toolCalls.cancel` resolve a hosted session's id daemon-side, so
16
+ * steering a hosted conversation is the same call as steering any other. Two
17
+ * spellings of one action is how they drift apart.
18
+ *
19
+ * It is not the stream. The hosted loop is the ordinary Orchestrator, so its
20
+ * tokens, tool calls and turn transitions arrive on the `turn` and `tools`
21
+ * event domains stamped with the hosted session's id — see
22
+ * hosted-session-stream.ts, which watches exactly what a local session watches
23
+ * and filters on the id `attach` handed back.
24
+ *
25
+ * ── Why the verbs go through DaemonVerbCaller ─────────────────────────────
26
+ *
27
+ * Every `sessions.hosted.*` verb is declared `transport: ['ws']` with no REST
28
+ * path of its own, so `sdk.operator.invoke` refuses them before making a
29
+ * request. `createDaemonVerbCaller` (operator-endpoint.ts) already handles that
30
+ * exact class by falling through to the generic gateway route — which IS the
31
+ * binding for a ws-declared verb reached over HTTP.
32
+ */
33
+ import { hostname } from 'node:os';
34
+ import type {
35
+ CreateHostedSessionInput,
36
+ HostedDetachPolicy,
37
+ HostedSessionHistoryMessage,
38
+ HostedSessionRecord,
39
+ } from '@pellux/goodvibes-sdk/platform/hosted-sessions';
40
+ import type { DaemonVerbCaller } from './operator-endpoint.ts';
41
+
42
+ export type {
43
+ CreateHostedSessionInput,
44
+ HostedDetachPolicy,
45
+ HostedSessionHistoryMessage,
46
+ HostedSessionRecord,
47
+ };
48
+
49
+ /** What `sessions.hosted.attach` answers with: the record, and what was said so far. */
50
+ export interface HostedSessionAttachment {
51
+ readonly session: HostedSessionRecord;
52
+ readonly history: readonly HostedSessionHistoryMessage[];
53
+ }
54
+
55
+ /**
56
+ * How this terminal names itself to the daemon when it attaches.
57
+ *
58
+ * It has to be stable for the life of the process and distinct between two
59
+ * terminals on one machine, because the detach policy is applied when the LAST
60
+ * client leaves: two windows sharing one id would make the first `detach` look
61
+ * like the last one. Host + pid is both, and it is readable in
62
+ * `attachedClients` — a person reading the record can tell which terminal that
63
+ * is.
64
+ */
65
+ let cachedClientId: string | null = null;
66
+ export function terminalHostedClientId(): string {
67
+ cachedClientId ??= `tui-${hostname()}-${process.pid}`;
68
+ return cachedClientId;
69
+ }
70
+
71
+ /** The narrow client the command layer and the panel share. */
72
+ export interface HostedSessionsClient {
73
+ /** This terminal's attach identity — the same string the records carry. */
74
+ readonly clientId: string;
75
+ list(options?: { readonly includeTerminated?: boolean }): Promise<readonly HostedSessionRecord[]>;
76
+ create(input: Omit<CreateHostedSessionInput, 'clientId'>): Promise<HostedSessionRecord>;
77
+ attach(sessionId: string): Promise<HostedSessionAttachment>;
78
+ detach(sessionId: string): Promise<HostedSessionRecord>;
79
+ kill(sessionId: string): Promise<HostedSessionRecord>;
80
+ /** Send a message into a running hosted session — the ordinary steer verb. */
81
+ steer(sessionId: string, body: string): Promise<void>;
82
+ /** Queue a message for after the current turn — the ordinary follow-up verb. */
83
+ followUp(sessionId: string, body: string): Promise<void>;
84
+ /** Cancel one in-flight tool call — the ordinary live-turn verb. */
85
+ cancelToolCall(sessionId: string, callId: string): Promise<boolean>;
86
+ }
87
+
88
+ /**
89
+ * Drop the keys a verb was not given a value for.
90
+ *
91
+ * The gateway validates against the declared input schema and a present-but-
92
+ * undefined property is not the same as an absent one on the wire; sending
93
+ * `{ title: undefined }` is how a caller that meant "no title" gets a
94
+ * validation refusal instead.
95
+ */
96
+ function withoutUndefined(input: Record<string, unknown>): Record<string, unknown> {
97
+ const out: Record<string, unknown> = {};
98
+ for (const [key, value] of Object.entries(input)) {
99
+ if (value !== undefined) out[key] = value;
100
+ }
101
+ return out;
102
+ }
103
+
104
+ export function createHostedSessionsClient(verbs: DaemonVerbCaller): HostedSessionsClient {
105
+ const clientId = terminalHostedClientId();
106
+ return {
107
+ clientId,
108
+ async list(options): Promise<readonly HostedSessionRecord[]> {
109
+ const result = await verbs.invoke<{ sessions: readonly HostedSessionRecord[] }>(
110
+ 'sessions.hosted.list',
111
+ withoutUndefined({ includeTerminated: options?.includeTerminated }),
112
+ );
113
+ return result.sessions ?? [];
114
+ },
115
+ async create(input): Promise<HostedSessionRecord> {
116
+ const result = await verbs.invoke<{ session: HostedSessionRecord }>(
117
+ 'sessions.hosted.create',
118
+ withoutUndefined({
119
+ workspaceRoot: input.workspaceRoot,
120
+ title: input.title,
121
+ modelId: input.modelId,
122
+ initialPrompt: input.initialPrompt,
123
+ detachPolicy: input.detachPolicy,
124
+ clientId,
125
+ }),
126
+ );
127
+ return result.session;
128
+ },
129
+ async attach(sessionId): Promise<HostedSessionAttachment> {
130
+ const result = await verbs.invoke<HostedSessionAttachment>(
131
+ 'sessions.hosted.attach',
132
+ { sessionId, clientId },
133
+ );
134
+ return { session: result.session, history: result.history ?? [] };
135
+ },
136
+ async detach(sessionId): Promise<HostedSessionRecord> {
137
+ const result = await verbs.invoke<{ session: HostedSessionRecord }>(
138
+ 'sessions.hosted.detach',
139
+ { sessionId, clientId },
140
+ );
141
+ return result.session;
142
+ },
143
+ async kill(sessionId): Promise<HostedSessionRecord> {
144
+ const result = await verbs.invoke<{ session: HostedSessionRecord }>(
145
+ 'sessions.hosted.kill',
146
+ { sessionId },
147
+ );
148
+ return result.session;
149
+ },
150
+ async steer(sessionId, body): Promise<void> {
151
+ await verbs.invoke('sessions.steer', { sessionId, body, surfaceKind: 'tui' });
152
+ },
153
+ async followUp(sessionId, body): Promise<void> {
154
+ await verbs.invoke('sessions.followUp', { sessionId, body, surfaceKind: 'tui' });
155
+ },
156
+ async cancelToolCall(sessionId, callId): Promise<boolean> {
157
+ const result = await verbs.invoke<{ cancelled: boolean }>(
158
+ 'sessions.toolCalls.cancel',
159
+ { sessionId, callId },
160
+ );
161
+ return result.cancelled === true;
162
+ },
163
+ };
164
+ }
165
+
166
+ /**
167
+ * One line describing what leaving this session would do right now, in the
168
+ * words the record itself carries.
169
+ *
170
+ * The policy is the daemon's answer, never this client's guess: a session
171
+ * created with an override reports the override, and one following the setting
172
+ * reports the setting's current value. Rendering a locally-remembered default
173
+ * here is how a user learns the wrong thing about a quit.
174
+ */
175
+ export function describeDetachEffect(record: HostedSessionRecord): string {
176
+ const source = record.detachPolicy === null
177
+ ? 'the hostedSessions.detachPolicy setting'
178
+ : 'this session\'s own override';
179
+ return record.effectiveDetachPolicy === 'survive'
180
+ ? `leaving keeps it running (survive, from ${source})`
181
+ : `leaving ends it (kill, from ${source})`;
182
+ }
183
+
184
+ /** A short, stable label for a record in a list. Never invents a title. */
185
+ export function hostedSessionLabel(record: HostedSessionRecord): string {
186
+ return record.title.trim() || record.id;
187
+ }