@pellux/goodvibes-tui 1.27.1 → 2.0.2

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 (405) hide show
  1. package/CHANGELOG.md +127 -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 +3 -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 +9 -122
  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 +21 -33
  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 +4 -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 -693
  288. package/src/daemon/fatal-boot-report.ts +0 -111
  289. package/src/daemon/handlers/context.ts +0 -29
  290. package/src/daemon/handlers/contracts.ts +0 -77
  291. package/src/daemon/handlers/credentials.ts +0 -139
  292. package/src/daemon/handlers/drafts/draft-store.ts +0 -427
  293. package/src/daemon/handlers/drafts/index.ts +0 -17
  294. package/src/daemon/handlers/drafts/register.ts +0 -331
  295. package/src/daemon/handlers/errors.ts +0 -18
  296. package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
  297. package/src/daemon/handlers/inbox/index.ts +0 -284
  298. package/src/daemon/handlers/inbox/mapping.ts +0 -192
  299. package/src/daemon/handlers/inbox/poller.ts +0 -212
  300. package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
  301. package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
  302. package/src/daemon/handlers/inbox/providers/email.ts +0 -152
  303. package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
  304. package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
  305. package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
  306. package/src/daemon/handlers/index.ts +0 -117
  307. package/src/daemon/handlers/register.ts +0 -168
  308. package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
  309. package/src/daemon/handlers/remote/backends/docker.ts +0 -79
  310. package/src/daemon/handlers/remote/backends/index.ts +0 -40
  311. package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
  312. package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
  313. package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
  314. package/src/daemon/handlers/remote/backends/types.ts +0 -97
  315. package/src/daemon/handlers/remote/dispatcher.ts +0 -181
  316. package/src/daemon/handlers/remote/index.ts +0 -119
  317. package/src/daemon/handlers/remote/peer-registry.ts +0 -357
  318. package/src/daemon/handlers/remote/service.ts +0 -191
  319. package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
  320. package/src/daemon/handlers/routing/index.ts +0 -261
  321. package/src/daemon/handlers/routing/route-store.ts +0 -319
  322. package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
  323. package/src/daemon/handlers/sqlite-store.ts +0 -278
  324. package/src/daemon/handlers/triage/index.ts +0 -57
  325. package/src/daemon/handlers/triage/integration.ts +0 -213
  326. package/src/daemon/handlers/triage/pipeline.ts +0 -274
  327. package/src/daemon/handlers/triage/scorer.ts +0 -287
  328. package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
  329. package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
  330. package/src/daemon/handlers/triage/tagger/index.ts +0 -184
  331. package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
  332. package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
  333. package/src/daemon/handlers/triage/types.ts +0 -50
  334. package/src/daemon/lifecycle.ts +0 -41
  335. package/src/daemon/provision-wake-model.ts +0 -81
  336. package/src/daemon/safe-serve.ts +0 -61
  337. package/src/daemon/send/channels.ts +0 -200
  338. package/src/daemon/send/command.ts +0 -332
  339. package/src/daemon/send/composition.ts +0 -99
  340. package/src/daemon/send/failure-text.ts +0 -93
  341. package/src/daemon/send/inert-text.ts +0 -225
  342. package/src/daemon/send/stdin.ts +0 -24
  343. package/src/daemon/service-commands.ts +0 -329
  344. package/src/export/cost-utils.ts +0 -319
  345. package/src/input/selection.ts +0 -135
  346. package/src/plugins/loader.ts +0 -15
  347. package/src/renderer/bottom-bar.ts +0 -58
  348. package/src/renderer/conversation-tree.ts +0 -228
  349. package/src/runtime/agent-graph-composition.ts +0 -78
  350. package/src/runtime/channel-composition.ts +0 -46
  351. package/src/runtime/cluster-composition.ts +0 -124
  352. package/src/runtime/cluster-group-composition.ts +0 -284
  353. package/src/runtime/code-index-services.ts +0 -167
  354. package/src/runtime/daemon-handler-composition.ts +0 -76
  355. package/src/runtime/device-posture-composition.ts +0 -110
  356. package/src/runtime/durability-housekeeping.ts +0 -183
  357. package/src/runtime/durability-services.ts +0 -155
  358. package/src/runtime/embedded-service-factories.ts +0 -74
  359. package/src/runtime/feature-settings.ts +0 -154
  360. package/src/runtime/fleet-needs-input-push.ts +0 -70
  361. package/src/runtime/fleet-services.ts +0 -41
  362. package/src/runtime/idle-power-services.ts +0 -85
  363. package/src/runtime/mail-composition.ts +0 -65
  364. package/src/runtime/memory-fold.ts +0 -55
  365. package/src/runtime/operator-token-cleanup.ts +0 -109
  366. package/src/runtime/path-shadow.ts +0 -418
  367. package/src/runtime/perf/panel-health-monitor.ts +0 -18
  368. package/src/runtime/provider-optimizer-wiring.ts +0 -55
  369. package/src/runtime/reachability-notice.ts +0 -100
  370. package/src/runtime/remote-execution-composition.ts +0 -62
  371. package/src/runtime/session-liveness-marker.ts +0 -257
  372. package/src/runtime/session-pointer-surface.ts +0 -22
  373. package/src/runtime/session-storage-services.ts +0 -41
  374. package/src/runtime/surface-feature-flags.ts +0 -96
  375. package/src/runtime/terminal-output-guard.ts +0 -235
  376. package/src/runtime/trust/workspace-registration.ts +0 -192
  377. package/src/runtime/trust/workspace-trust.ts +0 -229
  378. package/src/runtime/ui/index.ts +0 -39
  379. package/src/runtime/ui/model-picker/data-provider.ts +0 -182
  380. package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
  381. package/src/runtime/ui/model-picker/index.ts +0 -59
  382. package/src/runtime/ui/model-picker/types.ts +0 -153
  383. package/src/runtime/ui/provider-health/data-provider.ts +0 -244
  384. package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
  385. package/src/runtime/ui/provider-health/index.ts +0 -46
  386. package/src/runtime/ui/provider-health/types.ts +0 -146
  387. package/src/runtime/ui-events.ts +0 -1
  388. package/src/runtime/ui-read-model-helpers.ts +0 -1
  389. package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
  390. package/src/runtime/ui-read-models-observability-options.ts +0 -1
  391. package/src/runtime/ui-read-models-observability-remote.ts +0 -1
  392. package/src/runtime/ui-read-models-observability-security.ts +0 -1
  393. package/src/runtime/ui-read-models-observability-system.ts +0 -1
  394. package/src/runtime/ui-read-models-observability.ts +0 -1
  395. package/src/runtime/ui-service-queries.ts +0 -1
  396. package/src/runtime/voice-setup-services.ts +0 -98
  397. package/src/runtime/workstream-attempts-validation.ts +0 -77
  398. package/src/runtime/workstream-draft-edits.ts +0 -95
  399. package/src/runtime/workstream-draft-store.ts +0 -274
  400. package/src/runtime/workstream-draft-types.ts +0 -42
  401. package/src/runtime/workstream-services.ts +0 -373
  402. package/src/tools/index.ts +0 -1
  403. package/src/types/grid.ts +0 -48
  404. package/src/types/sql-js.d.ts +0 -15
  405. 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
+ }