@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
@@ -1,156 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Inbound provider adapter contract + registry.
3
- //
4
- // Each adapter owns ONE provider (slack, discord, email, ...). The poller calls
5
- // adapter.poll() on a cadence, dedups by item.id, and persists into the cursor
6
- // store. Adapters resolve credentials ONLY through the daemon credential store
7
- // and NEVER return raw sender ids or unredacted bodies — mapping/redaction is
8
- // the adapter's responsibility (see mapping helpers in `./mapping.ts`).
9
- //
10
- // CRITICAL: when a credential is missing/misconfigured an adapter returns
11
- // state 'unavailable' WITH an error string. It is NEVER silently omitted — the
12
- // caller must be able to distinguish "configured-but-empty" from "not wired".
13
- // ---------------------------------------------------------------------------
14
-
15
- import type { DaemonCredentialStore } from '../credentials.ts';
16
- import type { HandlerLogger } from '../context.ts';
17
-
18
- /**
19
- * Daemon-internal inbound item. This is NOT the SDK wire shape — the inbox
20
- * surface maps it onto the SDK `CHANNEL_INBOX_ITEM_SCHEMA` shape
21
- * (`from`/`subject`/`bodyPreview`/...) before returning. `fromDigest` is the
22
- * redacted sender (the only sender value that ever leaves the daemon).
23
- */
24
- export interface InboundChannelItem {
25
- /** Stable, provider-scoped dedup key. Idempotent across polls. */
26
- id: string;
27
- provider: string;
28
- kind: 'dm' | 'thread' | 'mention' | 'reaction';
29
- /**
30
- * sha256First(senderExternalId, 16) — NEVER the raw id. 16 hex chars == the
31
- * first 8 bytes of the SHA-256 digest.
32
- */
33
- fromDigest: string;
34
- /** <= 200 chars, safe for display. */
35
- subjectPreview: string;
36
- /** <= 500 chars, plain text, PII-stripped. */
37
- bodyPreview: string;
38
- /** Daemon route binding id, when resolvable. */
39
- routeId?: string;
40
- /** Unix ms. */
41
- receivedAt: number;
42
- unread: boolean;
43
- /** Optional triage metadata written by the triage surface (read-only here). */
44
- triageScore?: number;
45
- triageTags?: string[];
46
- }
47
-
48
- export type ProviderState = 'ready' | 'unavailable' | 'empty';
49
-
50
- export interface ProviderPollResult {
51
- items: InboundChannelItem[];
52
- state: ProviderState;
53
- /** Present only when state === 'unavailable'. */
54
- error?: string;
55
- }
56
-
57
- export interface ProviderPollOptions {
58
- /** Only return items newer than this Unix-ms timestamp, when supported. */
59
- since?: number;
60
- /** Max items to return this poll. */
61
- limit: number;
62
- }
63
-
64
- /** Context handed to every adapter at construction time. */
65
- export interface AdapterContext {
66
- readonly credentials: DaemonCredentialStore;
67
- readonly logger: HandlerLogger;
68
- /**
69
- * Optional route resolver supplied by the routing surface. Returns the route
70
- * binding id for a given inbound item, or undefined when no route matches /
71
- * the routing surface is not wired yet. Adapters/poller call this best-effort.
72
- */
73
- readonly resolveRouteId?: RouteResolver;
74
- }
75
-
76
- /**
77
- * Best-effort route resolution seam. The routing surface injects its
78
- * profile-backed implementation via the inbox bridge. Until then it is
79
- * undefined and items carry no routeId.
80
- */
81
- export type RouteResolver = (input: {
82
- provider: string;
83
- fromDigest: string;
84
- kind: InboundChannelItem['kind'];
85
- }) => Promise<string | undefined> | string | undefined;
86
-
87
- export interface InboundProviderAdapter {
88
- /** Provider id, e.g. 'slack'. Must be unique within the registry. */
89
- readonly id: string;
90
- /**
91
- * Poll cadence in ms. Slack/Discord 30s, email 60s, everything else 120s.
92
- * The poller reads this to schedule its per-provider interval.
93
- */
94
- readonly pollIntervalMs: number;
95
- /**
96
- * Pull recent DMs/threads/mentions. MUST resolve (never reject) — failures
97
- * are reported via state:'unavailable' + error so one bad provider cannot
98
- * crash the aggregate feed.
99
- */
100
- poll(opts: ProviderPollOptions): Promise<ProviderPollResult>;
101
- }
102
-
103
- /** Factory signature: adapters are constructed lazily with shared context. */
104
- export type AdapterFactory = (ctx: AdapterContext) => InboundProviderAdapter;
105
-
106
- // ---------------------------------------------------------------------------
107
- // Cadence constants (single source of truth, referenced by adapters + tests).
108
- // ---------------------------------------------------------------------------
109
-
110
- export const POLL_CADENCE_MS = {
111
- realtime: 30_000, // slack, discord
112
- email: 60_000,
113
- default: 120_000,
114
- } as const;
115
-
116
- // ---------------------------------------------------------------------------
117
- // Registry
118
- // ---------------------------------------------------------------------------
119
-
120
- const FACTORIES = new Map<string, AdapterFactory>();
121
-
122
- /** Register a provider factory. Last registration for an id wins (idempotent). */
123
- export function registerAdapterFactory(id: string, factory: AdapterFactory): void {
124
- FACTORIES.set(id, factory);
125
- }
126
-
127
- /** All registered provider ids, in insertion order. */
128
- export function registeredProviderIds(): string[] {
129
- return [...FACTORIES.keys()];
130
- }
131
-
132
- /**
133
- * Construct adapters for the requested provider ids (or all registered ids when
134
- * `requested` is undefined/empty). Unknown ids are dropped: the returned map
135
- * only contains known providers.
136
- */
137
- export function buildAdapters(
138
- ctx: AdapterContext,
139
- requested?: readonly string[],
140
- ): Map<string, InboundProviderAdapter> {
141
- const ids = requested && requested.length > 0
142
- ? requested.filter((id) => FACTORIES.has(id))
143
- : registeredProviderIds();
144
- const out = new Map<string, InboundProviderAdapter>();
145
- for (const id of ids) {
146
- const factory = FACTORIES.get(id);
147
- if (!factory) continue;
148
- out.set(id, factory(ctx));
149
- }
150
- return out;
151
- }
152
-
153
- /** Test/seam hook: clear the registry. */
154
- export function clearAdapterRegistry(): void {
155
- FACTORIES.clear();
156
- }
@@ -1,252 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Discord inbound adapter.
3
- //
4
- // Transport note (contract fidelity): the daemon-handoff checklist names the
5
- // Discord Gateway for DM polling. The Gateway is a persistent websocket push
6
- // transport and cannot be driven by the inbound poller, whose contract is a
7
- // stateless, cadence-driven adapter.poll() that MUST resolve each call (see
8
- // provider-adapter.ts) — a long-lived socket the poller neither owns nor
9
- // supervises is out of scope for that contract. We therefore satisfy the
10
- // DM-polling goal over Discord's supported request/response surface, the REST
11
- // API — the same DM data the Gateway streams, fetched on the poll cadence and
12
- // paged so a busy DM is never truncated:
13
- // GET /users/@me/channels -> list DM channels the bot participates in
14
- // GET /channels/{id}/messages -> recent messages per DM channel (paged via
15
- // the `before` snowflake cursor)
16
- //
17
- // Discord snowflake ids encode their creation timestamp, so receivedAt is
18
- // derived from the message id (snowflake) when no explicit timestamp is present.
19
- //
20
- // Credential: surfaces.discord.botToken. Missing => 'unavailable'.
21
- // Cadence: 30s (realtime tier).
22
- // ---------------------------------------------------------------------------
23
-
24
- import type {
25
- AdapterContext,
26
- InboundChannelItem,
27
- InboundProviderAdapter,
28
- ProviderPollOptions,
29
- ProviderPollResult,
30
- } from '../provider-adapter.ts';
31
- import { POLL_CADENCE_MS } from '../provider-adapter.ts';
32
- import { digestSender, toBodyPreview, toSubjectPreview } from '../mapping.ts';
33
- import { resolveRouteId } from './route-util.ts';
34
- import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
35
-
36
- const DISCORD_API = 'https://discord.com/api/v10';
37
- // Discord epoch (2015-01-01T00:00:00Z) in ms, used to decode snowflakes.
38
- const DISCORD_EPOCH_MS = 1_420_070_400_000;
39
- export const DISCORD_PROVIDER_ID = 'discord';
40
- export const DISCORD_CREDENTIAL_KEY = 'surfaces.discord.botToken';
41
-
42
- interface DiscordChannel {
43
- id: string;
44
- type: number; // 1 = DM, 3 = group DM
45
- }
46
-
47
- interface DiscordSelf {
48
- id: string;
49
- }
50
-
51
- interface DiscordReaction {
52
- count?: number;
53
- emoji?: { id?: string | null; name?: string | null };
54
- }
55
-
56
- interface DiscordMessage {
57
- id: string;
58
- channel_id?: string;
59
- content?: string;
60
- timestamp?: string; // ISO-8601
61
- author?: { id: string; bot?: boolean };
62
- referenced_message?: unknown;
63
- mentions?: Array<{ id: string }>;
64
- reactions?: DiscordReaction[];
65
- }
66
-
67
- /**
68
- * Classify a Discord message into the InboundChannelItem `kind`.
69
- * - reaction: someone reacted to OUR OWN message — a genuine inbound reaction
70
- * event. Requires the message to be authored by us (its author id
71
- * is selfId) AND to carry a non-empty reactions[]. A message
72
- * authored by someone else that merely carries reactions[] is a
73
- * normal DM, not a reaction event.
74
- * - mention: the message mentions us (our id is in mentions[])
75
- * - thread: the message is a reply (referenced_message present)
76
- * - dm: a plain direct message
77
- * Reaction outranks mention which outranks thread/dm (most-specific first).
78
- */
79
- function classifyDiscordKind(
80
- msg: DiscordMessage,
81
- selfId: string | undefined,
82
- ): InboundChannelItem['kind'] {
83
- if (
84
- selfId &&
85
- msg.author?.id === selfId &&
86
- Array.isArray(msg.reactions) &&
87
- msg.reactions.length > 0
88
- ) {
89
- return 'reaction';
90
- }
91
- if (selfId && Array.isArray(msg.mentions) && msg.mentions.some((m) => m.id === selfId)) {
92
- return 'mention';
93
- }
94
- if (msg.referenced_message) return 'thread';
95
- return 'dm';
96
- }
97
-
98
- /** Decode a Discord snowflake id to its creation Unix-ms timestamp. */
99
- function snowflakeToMs(id: string): number {
100
- try {
101
- const asBig = BigInt(id);
102
- return Number((asBig >> 22n)) + DISCORD_EPOCH_MS;
103
- } catch {
104
- return 0;
105
- }
106
- }
107
-
108
- async function discordGet<T>(token: string, path: string): Promise<T> {
109
- const res = await fetch(`${DISCORD_API}${path}`, {
110
- method: 'GET',
111
- headers: {
112
- Authorization: `Bot ${token}`,
113
- Accept: 'application/json',
114
- },
115
- });
116
- if (res.status === 401) throw new Error('Discord authentication failed (401)');
117
- if (!res.ok) throw new Error(`Discord GET ${path} HTTP ${res.status}`);
118
- return (await res.json()) as T;
119
- }
120
-
121
- export function createDiscordAdapter(ctx: AdapterContext): InboundProviderAdapter {
122
- return {
123
- id: DISCORD_PROVIDER_ID,
124
- pollIntervalMs: POLL_CADENCE_MS.realtime,
125
- async poll(opts: ProviderPollOptions): Promise<ProviderPollResult> {
126
- let token: string | null;
127
- try {
128
- token = await ctx.credentials.resolveConfigSecret(DISCORD_CREDENTIAL_KEY);
129
- } catch (error) {
130
- return unavailable(`credential lookup failed: ${errMsg(error)}`);
131
- }
132
- if (!token || token.trim().length === 0) {
133
- return unavailable('missing surfaces.discord.botToken');
134
- }
135
-
136
- // Resolve our own user id so we can classify @-mentions of us. Best-effort:
137
- // a failure only disables mention classification, never the provider.
138
- let selfId: string | undefined;
139
- try {
140
- const self = await discordGet<DiscordSelf>(token, '/users/@me');
141
- if (self.id) selfId = self.id;
142
- } catch (error) {
143
- ctx.logger.warn('discord /users/@me failed; mentions will not be classified', {
144
- error: errMsg(error),
145
- });
146
- }
147
-
148
- try {
149
- const channels = await discordGet<DiscordChannel[]>(token, '/users/@me/channels');
150
- const dmChannels = channels.filter((c) => c.type === 1 || c.type === 3);
151
- const items: InboundChannelItem[] = [];
152
- // /channels/{id}/messages returns at most `perChannel` (<=50) messages
153
- // newest-first. A DM that accrued more than one page of new messages in
154
- // the `since` window would silently drop the oldest beyond the first page
155
- // unless we page backwards via the `before` cursor (the id of the oldest
156
- // message seen so far). MAX_HISTORY_PAGES bounds the walk.
157
- const MAX_HISTORY_PAGES = 20;
158
- const perChannel = Math.min(opts.limit, 50);
159
- channelLoop: for (const channel of dmChannels) {
160
- if (items.length >= opts.limit) break;
161
- let before: string | undefined;
162
- for (let page = 0; page < MAX_HISTORY_PAGES; page += 1) {
163
- const params = new URLSearchParams({ limit: String(perChannel) });
164
- // Discord treats after/before/around as mutually exclusive: sending
165
- // both silently drops older in-window messages. Use `after` only on
166
- // the first page (to bound the window at `since`); once paging
167
- // backwards via `before`, drop `after` and rely on the
168
- // oldestMs<=since stop condition below to terminate the walk.
169
- if (before) params.set('before', before);
170
- else if (opts.since) params.set('after', msToSnowflake(opts.since));
171
- let messages: DiscordMessage[];
172
- try {
173
- messages = await discordGet<DiscordMessage[]>(
174
- token,
175
- `/channels/${channel.id}/messages?${params.toString()}`,
176
- );
177
- } catch (error) {
178
- ctx.logger.warn('discord channel messages failed', {
179
- channel: channel.id,
180
- error: errMsg(error),
181
- });
182
- continue channelLoop;
183
- }
184
- if (messages.length === 0) break;
185
- // Track the oldest id on this page for the next `before` cursor before
186
- // we filter/skip, so pagination is driven by the raw page, not by what
187
- // survived classification.
188
- let oldestId: string | undefined;
189
- let oldestMs = Number.POSITIVE_INFINITY;
190
- for (const msg of messages) {
191
- const msgMs = msg.timestamp
192
- ? Date.parse(msg.timestamp) || snowflakeToMs(msg.id)
193
- : snowflakeToMs(msg.id);
194
- if (msgMs < oldestMs) {
195
- oldestMs = msgMs;
196
- oldestId = msg.id;
197
- }
198
- if (items.length >= opts.limit) break;
199
- if (msg.author?.bot) continue;
200
- const receivedAt = msgMs;
201
- if (opts.since && receivedAt <= opts.since) continue;
202
- const senderId = msg.author?.id ?? channel.id;
203
- // Contract: fromDigest is SHA-256 (first 16 hex == 8 bytes) of the
204
- // provider user id. Discord user ids (snowflakes) are globally
205
- // unique, and the item.id / provider fields already namespace by
206
- // provider.
207
- const fromDigest = digestSender(senderId);
208
- const kind = classifyDiscordKind(msg, selfId);
209
- const item: InboundChannelItem = {
210
- id: `discord:${channel.id}:${msg.id}`,
211
- provider: DISCORD_PROVIDER_ID,
212
- kind,
213
- fromDigest,
214
- subjectPreview: toSubjectPreview('Direct message'),
215
- bodyPreview: toBodyPreview(msg.content),
216
- receivedAt,
217
- unread: true,
218
- };
219
- const routeId = await resolveRouteId(ctx, DISCORD_PROVIDER_ID, fromDigest, kind);
220
- if (routeId) item.routeId = routeId;
221
- items.push(item);
222
- }
223
- // Stop paging this channel when the page was not full (no older
224
- // messages exist), the item budget is spent, or the oldest message on
225
- // this page is already at/older than the `since` floor.
226
- if (messages.length < perChannel || items.length >= opts.limit) break;
227
- if (opts.since && oldestMs <= opts.since) break;
228
- if (!oldestId) break;
229
- before = oldestId;
230
- }
231
- }
232
- return { items, state: items.length > 0 ? 'ready' : 'empty' };
233
- } catch (error) {
234
- return unavailable(errMsg(error));
235
- }
236
- },
237
- };
238
- }
239
-
240
- /** Build a synthetic snowflake from a Unix-ms timestamp for the `after` cursor. */
241
- function msToSnowflake(ms: number): string {
242
- const delta = Math.max(0, Math.floor(ms) - DISCORD_EPOCH_MS);
243
- return (BigInt(delta) << 22n).toString();
244
- }
245
-
246
- function unavailable(error: string): ProviderPollResult {
247
- return { items: [], state: 'unavailable', error };
248
- }
249
-
250
- function errMsg(error: unknown): string {
251
- return summarizeError(error);
252
- }
@@ -1,152 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // Email (IMAP) inbound adapter.
3
- //
4
- // Uses the dependency-free ImapClient (node:tls) to pull recent INBOX messages.
5
- // Connection params resolve through the daemon credential store (env/secrets
6
- // backend) so nothing sensitive is read from plaintext config:
7
- // surfaces.email.imapHost (e.g. imap.fastmail.com)
8
- // surfaces.email.imapPort (default 993)
9
- // surfaces.email.imapUser
10
- // surfaces.email.imapPassword (app password / token)
11
- //
12
- // Any missing required field => state 'unavailable' WITH an explanatory error.
13
- // Cadence: 60s (email tier).
14
- // ---------------------------------------------------------------------------
15
-
16
- import type {
17
- AdapterContext,
18
- InboundChannelItem,
19
- InboundProviderAdapter,
20
- ProviderPollOptions,
21
- ProviderPollResult,
22
- } from '../provider-adapter.ts';
23
- import { POLL_CADENCE_MS } from '../provider-adapter.ts';
24
- import { digestSender, toBodyPreview, toSubjectPreview } from '../mapping.ts';
25
- import { resolveRouteId } from './route-util.ts';
26
- import { ImapClient } from './imap-client.ts';
27
- import type { ImapConfig, ImapEnvelope } from './imap-client.ts';
28
- import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
29
-
30
- export const EMAIL_PROVIDER_ID = 'email';
31
- export const EMAIL_HOST_KEY = 'surfaces.email.imapHost';
32
- export const EMAIL_PORT_KEY = 'surfaces.email.imapPort';
33
- export const EMAIL_USER_KEY = 'surfaces.email.imapUser';
34
- export const EMAIL_PASSWORD_KEY = 'surfaces.email.imapPassword';
35
-
36
- /**
37
- * Injectable client factory so tests can substitute a fake IMAP client without
38
- * opening a TLS socket. Production default constructs the real ImapClient.
39
- */
40
- export interface ImapLike {
41
- connect(): Promise<void>;
42
- login(): Promise<void>;
43
- select(mailbox?: string): Promise<void>;
44
- searchUids(since?: number): Promise<number[]>;
45
- fetchEnvelopes(uids: readonly number[]): Promise<ImapEnvelope[]>;
46
- logout(): Promise<void>;
47
- close(): void;
48
- }
49
-
50
- export type ImapClientFactory = (cfg: ImapConfig) => ImapLike;
51
-
52
- const defaultFactory: ImapClientFactory = (cfg) => new ImapClient(cfg);
53
-
54
- export function createEmailAdapter(
55
- ctx: AdapterContext,
56
- factory: ImapClientFactory = defaultFactory,
57
- ): InboundProviderAdapter {
58
- return {
59
- id: EMAIL_PROVIDER_ID,
60
- pollIntervalMs: POLL_CADENCE_MS.email,
61
- async poll(opts: ProviderPollOptions): Promise<ProviderPollResult> {
62
- let host: string | null;
63
- let user: string | null;
64
- let password: string | null;
65
- let portRaw: string | null;
66
- try {
67
- [host, portRaw, user, password] = await Promise.all([
68
- ctx.credentials.resolveConfigSecret(EMAIL_HOST_KEY),
69
- ctx.credentials.resolveConfigSecret(EMAIL_PORT_KEY),
70
- ctx.credentials.resolveConfigSecret(EMAIL_USER_KEY),
71
- ctx.credentials.resolveConfigSecret(EMAIL_PASSWORD_KEY),
72
- ]);
73
- } catch (error) {
74
- return unavailable(`credential lookup failed: ${errMsg(error)}`);
75
- }
76
-
77
- const missing: string[] = [];
78
- if (!host) missing.push('imapHost');
79
- if (!user) missing.push('imapUser');
80
- if (!password) missing.push('imapPassword');
81
- if (missing.length > 0) {
82
- return unavailable(`missing email IMAP credentials: ${missing.join(', ')}`);
83
- }
84
- const port = portRaw ? Number.parseInt(portRaw, 10) : 993;
85
- if (!Number.isFinite(port) || port <= 0) {
86
- return unavailable(`invalid surfaces.email.imapPort: ${portRaw}`);
87
- }
88
-
89
- const client = factory({
90
- host: host!,
91
- port,
92
- user: user!,
93
- password: password!,
94
- });
95
-
96
- try {
97
- await client.connect();
98
- await client.login();
99
- await client.select('INBOX');
100
- const uids = await client.searchUids(opts.since);
101
- // Newest UIDs first, capped at limit.
102
- const selected = uids.sort((a, b) => b - a).slice(0, opts.limit);
103
- const envelopes = await client.fetchEnvelopes(selected);
104
- const items: InboundChannelItem[] = [];
105
- for (const env of envelopes) {
106
- const receivedAt = env.date > 0 ? env.date : Date.now();
107
- if (opts.since && receivedAt <= opts.since) continue;
108
- const fromDigest = digestSender(`email:${normalizeAddress(env.from)}`);
109
- const kind = 'dm';
110
- const item: InboundChannelItem = {
111
- id: `email:${user}:${env.uid}`,
112
- provider: EMAIL_PROVIDER_ID,
113
- kind,
114
- fromDigest,
115
- subjectPreview: toSubjectPreview(env.subject),
116
- bodyPreview: toBodyPreview(env.bodyPreview),
117
- receivedAt,
118
- unread: !env.seen,
119
- };
120
- const routeId = await resolveRouteId(ctx, EMAIL_PROVIDER_ID, fromDigest, kind);
121
- if (routeId) item.routeId = routeId;
122
- items.push(item);
123
- }
124
- return { items, state: items.length > 0 ? 'ready' : 'empty' };
125
- } catch (error) {
126
- return unavailable(errMsg(error));
127
- } finally {
128
- try {
129
- await client.logout();
130
- } catch {
131
- // ignore
132
- }
133
- client.close();
134
- }
135
- },
136
- };
137
- }
138
-
139
- /** Extract a bare address from a `Name <addr@host>` From header for digesting. */
140
- function normalizeAddress(from: string): string {
141
- const angle = /<([^>]+)>/.exec(from);
142
- const addr = (angle ? angle[1]! : from).trim().toLowerCase();
143
- return addr.length > 0 ? addr : from.trim().toLowerCase();
144
- }
145
-
146
- function unavailable(error: string): ProviderPollResult {
147
- return { items: [], state: 'unavailable', error };
148
- }
149
-
150
- function errMsg(error: unknown): string {
151
- return summarizeError(error);
152
- }