@vellumai/assistant 0.8.0 → 0.8.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 (991) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +2 -7
  3. package/Dockerfile +80 -5
  4. package/README.md +2 -2
  5. package/bun.lock +11 -1
  6. package/docker-entrypoint.sh +21 -0
  7. package/docker-init-apt-root.sh +94 -0
  8. package/docker-kata-apt-env.sh +39 -0
  9. package/docs/plugins.md +88 -47
  10. package/docs/skills.md +9 -7
  11. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  12. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  13. package/eslint.config.mjs +12 -0
  14. package/examples/plugins/echo/README.md +27 -27
  15. package/examples/plugins/echo/package.json +3 -0
  16. package/examples/plugins/echo/register.ts +31 -31
  17. package/knip.json +2 -1
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  20. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  21. package/openapi.yaml +4462 -991
  22. package/package.json +5 -1
  23. package/scripts/generate-openapi.ts +135 -14
  24. package/scripts/sync-llm-catalog.ts +165 -0
  25. package/scripts/sync-web-search-catalog.ts +129 -0
  26. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  27. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  28. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  29. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  30. package/src/__tests__/anthropic-provider.test.ts +137 -2
  31. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  32. package/src/__tests__/app-control-flow.test.ts +7 -0
  33. package/src/__tests__/app-executors.test.ts +220 -4
  34. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  35. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  36. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  37. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  38. package/src/__tests__/btw-routes.test.ts +1 -0
  39. package/src/__tests__/bundled-asset.test.ts +6 -6
  40. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  41. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  42. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  43. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  44. package/src/__tests__/channel-policy.test.ts +12 -0
  45. package/src/__tests__/checker.test.ts +89 -0
  46. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  47. package/src/__tests__/clawhub.test.ts +75 -16
  48. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  49. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  50. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  51. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  52. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  53. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  54. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  55. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  56. package/src/__tests__/config-schema.test.ts +35 -3
  57. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  58. package/src/__tests__/config-set-route.test.ts +278 -0
  59. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  60. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  61. package/src/__tests__/config-watcher.test.ts +6 -0
  62. package/src/__tests__/contacts-tools.test.ts +51 -199
  63. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  64. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  65. package/src/__tests__/context-search-conversations-source.test.ts +159 -18
  66. package/src/__tests__/context-search-fanout.test.ts +20 -157
  67. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
  68. package/src/__tests__/context-search-types.test.ts +7 -2
  69. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  70. package/src/__tests__/context-token-estimator.test.ts +1 -0
  71. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  72. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  73. package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
  74. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  75. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  76. package/src/__tests__/conversation-error.test.ts +80 -3
  77. package/src/__tests__/conversation-fork-crud.test.ts +323 -1
  78. package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
  79. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  80. package/src/__tests__/conversation-lifecycle.test.ts +297 -0
  81. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  82. package/src/__tests__/conversation-pairing.test.ts +54 -0
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  84. package/src/__tests__/conversation-process-callsite.test.ts +25 -2
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  86. package/src/__tests__/conversation-queue.test.ts +4 -1
  87. package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
  88. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  90. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  91. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  92. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  93. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  94. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  95. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  96. package/src/__tests__/credential-security-invariants.test.ts +8 -8
  97. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  98. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  99. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  100. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  101. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  102. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  103. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  104. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  105. package/src/__tests__/dm-backfill.test.ts +121 -10
  106. package/src/__tests__/document-tool-security.test.ts +258 -0
  107. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  108. package/src/__tests__/edit-propagation.test.ts +33 -0
  109. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  110. package/src/__tests__/external-plugin-loader.test.ts +482 -0
  111. package/src/__tests__/filing-service.test.ts +163 -3
  112. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  113. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  114. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  115. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  116. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
  117. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  118. package/src/__tests__/heartbeat-service.test.ts +50 -233
  119. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  120. package/src/__tests__/helpers/wait-for.ts +21 -0
  121. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  122. package/src/__tests__/history-repair.test.ts +162 -0
  123. package/src/__tests__/host-app-control-proxy.test.ts +365 -1
  124. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  125. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  126. package/src/__tests__/host-browser-routes.test.ts +325 -33
  127. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  128. package/src/__tests__/image-credentials.test.ts +1 -1
  129. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  130. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  131. package/src/__tests__/inference-profile-reaper.test.ts +156 -0
  132. package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
  133. package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
  134. package/src/__tests__/injector-chain.test.ts +10 -8
  135. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  136. package/src/__tests__/install-skill-routing.test.ts +157 -39
  137. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
  138. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  139. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  140. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  141. package/src/__tests__/llm-catalog-parity.test.ts +190 -2
  142. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
  143. package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
  144. package/src/__tests__/llm-resolver.test.ts +46 -0
  145. package/src/__tests__/llm-usage-store.test.ts +114 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +145 -14
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  148. package/src/__tests__/managed-store.test.ts +84 -192
  149. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  150. package/src/__tests__/mcp-cli.test.ts +182 -220
  151. package/src/__tests__/mcp-health-check.test.ts +56 -27
  152. package/src/__tests__/media-generate-image.test.ts +1 -1
  153. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  154. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  155. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  156. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  157. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  158. package/src/__tests__/oauth-cli.test.ts +38 -2009
  159. package/src/__tests__/oauth-commands-routes.test.ts +863 -0
  160. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  161. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  162. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  163. package/src/__tests__/openai-provider.test.ts +24 -0
  164. package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
  165. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  166. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  167. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  168. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  169. package/src/__tests__/platform.test.ts +2 -0
  170. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  171. package/src/__tests__/plugin-bootstrap.test.ts +41 -38
  172. package/src/__tests__/plugin-external-api.test.ts +68 -0
  173. package/src/__tests__/plugin-registry.test.ts +0 -77
  174. package/src/__tests__/plugin-route-contribution.test.ts +31 -4
  175. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  176. package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
  177. package/src/__tests__/plugin-types.test.ts +15 -23
  178. package/src/__tests__/process-message-background-slack.test.ts +53 -0
  179. package/src/__tests__/process-message-display-content.test.ts +421 -0
  180. package/src/__tests__/profile-entry-status.test.ts +43 -0
  181. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  182. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  183. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
  184. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  185. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  186. package/src/__tests__/relay-server.test.ts +118 -0
  187. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  188. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  189. package/src/__tests__/schedule-retry.test.ts +56 -4
  190. package/src/__tests__/schedule-routes.test.ts +151 -0
  191. package/src/__tests__/schedule-store.test.ts +94 -0
  192. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  193. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  194. package/src/__tests__/scheduler-reuse-conversation.test.ts +208 -5
  195. package/src/__tests__/scheduler-wake.test.ts +0 -63
  196. package/src/__tests__/schema-transforms.test.ts +20 -0
  197. package/src/__tests__/search-skills-unified.test.ts +0 -5
  198. package/src/__tests__/secret-allowlist.test.ts +1 -0
  199. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
  200. package/src/__tests__/server-history-render.test.ts +43 -0
  201. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  202. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  203. package/src/__tests__/skill-load-feature-flag.test.ts +1 -12
  204. package/src/__tests__/skill-load-tool.test.ts +29 -93
  205. package/src/__tests__/skill-memory.test.ts +23 -3
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  208. package/src/__tests__/skills-install-extract.test.ts +49 -38
  209. package/src/__tests__/skills-install-staging.test.ts +159 -0
  210. package/src/__tests__/skills-uninstall.test.ts +9 -41
  211. package/src/__tests__/skills.test.ts +51 -58
  212. package/src/__tests__/slack-channel-config.test.ts +9 -0
  213. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  214. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +63 -0
  217. package/src/__tests__/system-prompt.test.ts +737 -63
  218. package/src/__tests__/task-scheduler.test.ts +88 -23
  219. package/src/__tests__/terminal-tools.test.ts +28 -1
  220. package/src/__tests__/thread-backfill.test.ts +557 -27
  221. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  222. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  223. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  224. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  225. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  226. package/src/__tests__/tool-executor.test.ts +16 -4
  227. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  228. package/src/__tests__/turn-events-store.test.ts +256 -0
  229. package/src/__tests__/twilio-routes.test.ts +4 -0
  230. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  231. package/src/__tests__/usage-cli.test.ts +11 -73
  232. package/src/__tests__/user-plugin-loader.test.ts +143 -5
  233. package/src/__tests__/vercel-config.test.ts +168 -0
  234. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  235. package/src/__tests__/web-search-catalog-parity.test.ts +108 -0
  236. package/src/__tests__/web-search.test.ts +303 -2
  237. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  238. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +170 -0
  239. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  240. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
  241. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  242. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  243. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  244. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  245. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  246. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  247. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  248. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  249. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  250. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  251. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  252. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  253. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  254. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  255. package/src/acp/resolve-agent.test.ts +25 -0
  256. package/src/acp/resolve-agent.ts +13 -2
  257. package/src/acp/session-manager.ts +14 -0
  258. package/src/agent/image-optimize.ts +13 -5
  259. package/src/approvals/guardian-request-resolvers.ts +32 -87
  260. package/src/calls/relay-server.ts +35 -0
  261. package/src/calls/relay-setup-router.ts +36 -0
  262. package/src/calls/types.ts +1 -0
  263. package/src/calls/voice-session-bridge.ts +74 -36
  264. package/src/channels/config.ts +14 -1
  265. package/src/channels/types.ts +109 -0
  266. package/src/cli/AGENTS.md +164 -4
  267. package/src/cli/__tests__/notifications.test.ts +54 -0
  268. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  269. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  270. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  271. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  272. package/src/cli/commands/__tests__/changelog.test.ts +578 -0
  273. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  274. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  275. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  276. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  277. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  278. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  279. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  280. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  281. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  282. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  283. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  284. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  285. package/src/cli/commands/__tests__/status.test.ts +249 -0
  286. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  287. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  288. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  289. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  290. package/src/cli/commands/attachment.ts +8 -3
  291. package/src/cli/commands/audit.ts +95 -64
  292. package/src/cli/commands/auth.ts +61 -58
  293. package/src/cli/commands/avatar.ts +276 -390
  294. package/src/cli/commands/backup.ts +409 -505
  295. package/src/cli/commands/bash.ts +9 -5
  296. package/src/cli/commands/browser.ts +28 -9
  297. package/src/cli/commands/cache.ts +9 -4
  298. package/src/cli/commands/changelog.ts +478 -0
  299. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  300. package/src/cli/commands/clients.ts +8 -3
  301. package/src/cli/commands/completions.ts +9 -9
  302. package/src/cli/commands/config.ts +102 -72
  303. package/src/cli/commands/contacts.ts +575 -696
  304. package/src/cli/commands/conversations-defer.ts +17 -69
  305. package/src/cli/commands/conversations-import.ts +90 -253
  306. package/src/cli/commands/conversations.ts +429 -434
  307. package/src/cli/commands/credential-execution.ts +9 -6
  308. package/src/cli/commands/credentials.ts +456 -736
  309. package/src/cli/commands/default-action.ts +10 -53
  310. package/src/cli/commands/domain.ts +128 -206
  311. package/src/cli/commands/email.ts +606 -794
  312. package/src/cli/commands/gateway.ts +8 -1
  313. package/src/cli/commands/image-generation.ts +157 -205
  314. package/src/cli/commands/inference-providers.ts +352 -0
  315. package/src/cli/commands/inference-session.ts +415 -0
  316. package/src/cli/commands/inference.ts +87 -65
  317. package/src/cli/commands/keys.ts +8 -3
  318. package/src/cli/commands/mcp.ts +103 -287
  319. package/src/cli/commands/memory-v2.ts +162 -516
  320. package/src/cli/commands/notifications.ts +342 -304
  321. package/src/cli/commands/oauth/apps.ts +292 -261
  322. package/src/cli/commands/oauth/connect.ts +176 -297
  323. package/src/cli/commands/oauth/disconnect.ts +16 -215
  324. package/src/cli/commands/oauth/index.ts +49 -45
  325. package/src/cli/commands/oauth/mode.ts +43 -199
  326. package/src/cli/commands/oauth/ping.ts +17 -125
  327. package/src/cli/commands/oauth/providers.ts +732 -921
  328. package/src/cli/commands/oauth/request.ts +60 -350
  329. package/src/cli/commands/oauth/shared.ts +11 -121
  330. package/src/cli/commands/oauth/status.ts +31 -121
  331. package/src/cli/commands/oauth/token.ts +13 -55
  332. package/src/cli/commands/pending.ts +19 -10
  333. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  334. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  335. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  336. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  337. package/src/cli/commands/platform/connect.ts +16 -80
  338. package/src/cli/commands/platform/disconnect.ts +14 -112
  339. package/src/cli/commands/platform/index.ts +177 -246
  340. package/src/cli/commands/plugins.ts +185 -0
  341. package/src/cli/commands/routes.ts +153 -336
  342. package/src/cli/commands/schedules.ts +391 -0
  343. package/src/cli/commands/sequence.ts +316 -360
  344. package/src/cli/commands/skills.ts +449 -671
  345. package/src/cli/commands/status.ts +58 -37
  346. package/src/cli/commands/stt.ts +94 -262
  347. package/src/cli/commands/task.ts +14 -40
  348. package/src/cli/commands/telemetry.ts +40 -0
  349. package/src/cli/commands/trust.ts +8 -3
  350. package/src/cli/commands/tts.ts +162 -167
  351. package/src/cli/commands/ui.ts +35 -42
  352. package/src/cli/commands/usage.ts +188 -126
  353. package/src/cli/commands/watchers.ts +8 -3
  354. package/src/cli/commands/webhooks.ts +99 -193
  355. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  356. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  357. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  358. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  359. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  360. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  361. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  362. package/src/cli/lib/cli-colors.ts +12 -0
  363. package/src/cli/lib/confirm-prompt.ts +79 -0
  364. package/src/cli/lib/daemon-credential-client.ts +4 -5
  365. package/src/cli/lib/install-from-github.ts +304 -0
  366. package/src/cli/lib/list-installed-plugins.ts +137 -0
  367. package/src/cli/lib/nested-value.ts +44 -0
  368. package/src/cli/lib/open-browser.ts +36 -0
  369. package/src/cli/lib/register-command.ts +19 -0
  370. package/src/cli/lib/time-ago.ts +34 -0
  371. package/src/cli/lib/uninstall-plugin.ts +82 -0
  372. package/src/cli/lib/unknown-command.ts +111 -0
  373. package/src/cli/program.ts +40 -6
  374. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  375. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  376. package/src/cli/utils/conversation-id.ts +30 -0
  377. package/src/cli/utils/parse-duration.ts +41 -0
  378. package/src/config/acp-defaults.test.ts +5 -1
  379. package/src/config/acp-defaults.ts +11 -4
  380. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  381. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  382. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  383. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  384. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  385. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  386. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  387. package/src/config/bundled-skills/document/SKILL.md +23 -3
  388. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  389. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  390. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  391. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  392. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  393. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  394. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  395. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  396. package/src/config/bundled-tool-registry.ts +6 -2
  397. package/src/config/feature-flag-registry.json +57 -1
  398. package/src/config/llm-resolver.ts +16 -1
  399. package/src/config/loader.ts +140 -52
  400. package/src/config/raw-config-utils.ts +2 -30
  401. package/src/config/schema.ts +8 -7
  402. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  403. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  404. package/src/config/schemas/call-site-catalog.ts +29 -7
  405. package/src/config/schemas/channels.ts +8 -0
  406. package/src/config/schemas/compaction.ts +28 -0
  407. package/src/config/schemas/heartbeat.ts +9 -0
  408. package/src/config/schemas/llm-request-logs.ts +81 -0
  409. package/src/config/schemas/llm.ts +55 -2
  410. package/src/config/schemas/memory-retrieval.ts +18 -0
  411. package/src/config/schemas/memory-retrospective.ts +48 -0
  412. package/src/config/schemas/memory-v2.ts +32 -1
  413. package/src/config/schemas/memory.ts +4 -0
  414. package/src/config/schemas/services.ts +15 -12
  415. package/src/config/schemas/tools.ts +14 -0
  416. package/src/config/seed-inference-profiles.ts +195 -134
  417. package/src/config/skills.ts +3 -96
  418. package/src/contacts/contact-store.ts +0 -61
  419. package/src/context/compactor.ts +1047 -0
  420. package/src/context/token-estimator.ts +2 -2
  421. package/src/context/window-manager.ts +197 -1334
  422. package/src/credential-execution/managed-catalog.ts +37 -0
  423. package/src/credential-health/credential-health-service.ts +280 -19
  424. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
  425. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  426. package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
  427. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  428. package/src/daemon/approval-generators.ts +26 -30
  429. package/src/daemon/config-watcher.ts +94 -29
  430. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  431. package/src/daemon/conversation-agent-loop.ts +293 -103
  432. package/src/daemon/conversation-error.ts +188 -33
  433. package/src/daemon/conversation-lifecycle.ts +80 -26
  434. package/src/daemon/conversation-messaging.ts +25 -6
  435. package/src/daemon/conversation-process.ts +85 -31
  436. package/src/daemon/conversation-runtime-assembly.ts +30 -6
  437. package/src/daemon/conversation-slash.ts +184 -25
  438. package/src/daemon/conversation-store.ts +24 -10
  439. package/src/daemon/conversation-surfaces.ts +76 -12
  440. package/src/daemon/conversation-tool-setup.ts +63 -21
  441. package/src/daemon/conversation.ts +81 -10
  442. package/src/daemon/external-plugins-bootstrap.ts +231 -185
  443. package/src/daemon/first-greeting.ts +22 -2
  444. package/src/daemon/guardian-action-generators.ts +7 -22
  445. package/src/daemon/handlers/config-model.ts +13 -130
  446. package/src/daemon/handlers/config-slack-channel.ts +25 -10
  447. package/src/daemon/handlers/config-vercel.ts +3 -1
  448. package/src/daemon/handlers/shared.ts +14 -5
  449. package/src/daemon/handlers/skills.ts +166 -84
  450. package/src/daemon/history-repair.ts +61 -7
  451. package/src/daemon/host-app-control-proxy.ts +129 -29
  452. package/src/daemon/host-bash-proxy.ts +85 -158
  453. package/src/daemon/host-browser-proxy.ts +96 -35
  454. package/src/daemon/host-proxy-base.ts +13 -1
  455. package/src/daemon/host-proxy-preactivation.ts +25 -1
  456. package/src/daemon/identity-helpers.ts +19 -0
  457. package/src/daemon/lifecycle.ts +79 -70
  458. package/src/daemon/meet-host-supervisor.ts +20 -19
  459. package/src/daemon/memory-v2-startup.ts +58 -2
  460. package/src/daemon/message-protocol.ts +7 -0
  461. package/src/daemon/message-types/bookmarks.ts +18 -0
  462. package/src/daemon/message-types/conversations.ts +37 -9
  463. package/src/daemon/message-types/messages.ts +70 -1
  464. package/src/daemon/message-types/subagents.ts +1 -0
  465. package/src/daemon/message-types/sync.ts +61 -0
  466. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  467. package/src/daemon/pkb-reminder-builder.ts +21 -7
  468. package/src/daemon/plugin-source-watcher.ts +146 -0
  469. package/src/daemon/process-message.ts +77 -26
  470. package/src/daemon/server.ts +34 -20
  471. package/src/daemon/shutdown-handlers.ts +0 -2
  472. package/src/daemon/skill-memory-refresh.ts +29 -0
  473. package/src/daemon/tool-setup-types.ts +9 -0
  474. package/src/daemon/tool-side-effects.ts +6 -4
  475. package/src/daemon/wake-target-adapter.ts +11 -0
  476. package/src/documents/document-store.ts +221 -3
  477. package/src/embedded/plugin-api.ts +40 -0
  478. package/src/export/transcript-formatter.ts +61 -2
  479. package/src/filing/filing-service.ts +79 -53
  480. package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
  481. package/src/heartbeat/heartbeat-run-store.ts +3 -1
  482. package/src/heartbeat/heartbeat-service.ts +189 -127
  483. package/src/home/__tests__/feed-types.test.ts +99 -127
  484. package/src/home/__tests__/feed-writer.test.ts +77 -278
  485. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  486. package/src/home/feed-types.ts +41 -73
  487. package/src/home/feed-writer.ts +25 -156
  488. package/src/home/post-connect-feed.ts +2 -3
  489. package/src/index.ts +18 -1
  490. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  491. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  492. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  493. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  494. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  495. package/src/ipc/assistant-server.ts +55 -6
  496. package/src/ipc/cli-client.ts +370 -50
  497. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  498. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  499. package/src/ipc/skill-routes/events.ts +30 -3
  500. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  501. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  502. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  503. package/src/live-voice/live-voice-session-manager.ts +11 -4
  504. package/src/live-voice/live-voice-session.ts +14 -6
  505. package/src/mcp/client.ts +20 -4
  506. package/src/media/image-credentials.ts +3 -3
  507. package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
  508. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  509. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  510. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  511. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  512. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  513. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  514. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  515. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +318 -0
  516. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  517. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  518. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  519. package/src/memory/__tests__/message-content.test.ts +35 -0
  520. package/src/memory/bookmark-crud.ts +211 -0
  521. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  522. package/src/memory/context-search/agent-protocol.ts +5 -1
  523. package/src/memory/context-search/agent-runner.ts +60 -85
  524. package/src/memory/context-search/limits.ts +1 -4
  525. package/src/memory/context-search/search.ts +23 -113
  526. package/src/memory/context-search/sources/conversations.ts +80 -8
  527. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  528. package/src/memory/context-search/sources/memory.ts +7 -0
  529. package/src/memory/context-search/sources/workspace.ts +17 -10
  530. package/src/memory/context-search/types.ts +1 -1
  531. package/src/memory/conversation-bootstrap.ts +11 -0
  532. package/src/memory/conversation-crud.ts +368 -22
  533. package/src/memory/conversation-queries.ts +116 -12
  534. package/src/memory/conversation-title-service.ts +1 -0
  535. package/src/memory/conversation-types.ts +16 -0
  536. package/src/memory/db-init.ts +20 -0
  537. package/src/memory/delivery-crud.ts +152 -5
  538. package/src/memory/embedding-backend.ts +6 -5
  539. package/src/memory/embedding-runtime-manager.ts +1 -2
  540. package/src/memory/external-conversation-store.ts +66 -5
  541. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  542. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  543. package/src/memory/graph/conversation-graph-memory.ts +92 -5
  544. package/src/memory/graph/extraction.ts +4 -0
  545. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  546. package/src/memory/graph/tool-handlers.ts +17 -7
  547. package/src/memory/graph/tools.ts +45 -6
  548. package/src/memory/indexer.ts +51 -29
  549. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
  550. package/src/memory/jobs/embed-concept-page.ts +65 -20
  551. package/src/memory/jobs-store.ts +51 -1
  552. package/src/memory/jobs-worker.ts +57 -3
  553. package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
  554. package/src/memory/llm-request-log-source-local.ts +26 -0
  555. package/src/memory/llm-request-log-source.ts +64 -0
  556. package/src/memory/llm-request-log-store.ts +1 -1
  557. package/src/memory/llm-usage-store.ts +125 -5
  558. package/src/memory/memory-retrospective-constants.ts +13 -0
  559. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  560. package/src/memory/memory-retrospective-job.ts +351 -0
  561. package/src/memory/memory-retrospective-startup-cleanup.ts +175 -0
  562. package/src/memory/memory-retrospective-state.ts +162 -0
  563. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  564. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  565. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  566. package/src/memory/message-content.ts +38 -1
  567. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  568. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  569. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  570. package/src/memory/migrations/229-delete-private-conversations.test.ts +107 -1
  571. package/src/memory/migrations/229-delete-private-conversations.ts +19 -0
  572. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  573. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  574. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  575. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  576. package/src/memory/migrations/243-provider-connections.ts +68 -0
  577. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  578. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  579. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  580. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  581. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  582. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  583. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  584. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  585. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  586. package/src/memory/migrations/index.ts +13 -0
  587. package/src/memory/migrations/registry.ts +8 -0
  588. package/src/memory/onboarding-events-store.ts +106 -0
  589. package/src/memory/published-pages-store.ts +16 -0
  590. package/src/memory/schema/bookmarks.ts +36 -0
  591. package/src/memory/schema/calls.ts +1 -0
  592. package/src/memory/schema/conversations.ts +2 -0
  593. package/src/memory/schema/index.ts +2 -0
  594. package/src/memory/schema/inference.ts +27 -0
  595. package/src/memory/schema/infrastructure.ts +12 -0
  596. package/src/memory/schema/memory-core.ts +9 -0
  597. package/src/memory/search/semantic.ts +1 -4
  598. package/src/memory/turn-events-store.ts +127 -2
  599. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  600. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  601. package/src/memory/v2/__tests__/activation.test.ts +11 -12
  602. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  603. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  604. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  605. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  606. package/src/memory/v2/__tests__/injection.test.ts +726 -18
  607. package/src/memory/v2/__tests__/migration.test.ts +94 -3
  608. package/src/memory/v2/__tests__/page-index.test.ts +360 -0
  609. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  610. package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
  611. package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
  612. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  613. package/src/memory/v2/__tests__/router.test.ts +531 -0
  614. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  615. package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
  616. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  617. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  618. package/src/memory/v2/activation-store.ts +34 -5
  619. package/src/memory/v2/activation.ts +40 -27
  620. package/src/memory/v2/backfill-jobs.ts +17 -84
  621. package/src/memory/v2/consolidation-job.ts +85 -78
  622. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  623. package/src/memory/v2/injection.ts +466 -109
  624. package/src/memory/v2/migration.ts +147 -20
  625. package/src/memory/v2/page-index.ts +221 -0
  626. package/src/memory/v2/page-store.ts +3 -0
  627. package/src/memory/v2/prompts/consolidation.ts +9 -7
  628. package/src/memory/v2/prompts/router.ts +195 -0
  629. package/src/memory/v2/prompts/sweep.ts +2 -2
  630. package/src/memory/v2/qdrant.ts +234 -93
  631. package/src/memory/v2/reranker.ts +14 -7
  632. package/src/memory/v2/router.ts +323 -0
  633. package/src/memory/v2/sim.ts +25 -12
  634. package/src/memory/v2/skill-store.ts +204 -30
  635. package/src/memory/v2/static-context.ts +16 -9
  636. package/src/memory/v2/sweep-job.ts +122 -96
  637. package/src/memory/v2/types.ts +10 -6
  638. package/src/memory/validation.ts +13 -0
  639. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  640. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  641. package/src/messaging/providers/slack/adapter.ts +43 -5
  642. package/src/messaging/providers/slack/client.ts +27 -0
  643. package/src/messaging/providers/slack/deep-link.ts +65 -0
  644. package/src/messaging/providers/slack/download.ts +104 -0
  645. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  646. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  647. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  648. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  649. package/src/messaging/providers/slack/types.ts +20 -1
  650. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  651. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  652. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  653. package/src/notifications/adapters/platform.ts +171 -0
  654. package/src/notifications/conversation-pairing.ts +4 -3
  655. package/src/notifications/copy-composer.ts +15 -0
  656. package/src/notifications/decision-engine.ts +2 -1
  657. package/src/notifications/destination-resolver.ts +21 -0
  658. package/src/notifications/emit-signal.ts +48 -2
  659. package/src/notifications/home-feed-side-effect.ts +165 -0
  660. package/src/notifications/signal.ts +8 -1
  661. package/src/oauth/connection-resolver.ts +8 -4
  662. package/src/oauth/platform-connection.ts +6 -2
  663. package/src/oauth/seed-providers.ts +10 -1
  664. package/src/permissions/checker.ts +14 -0
  665. package/src/permissions/ipc-risk-types.ts +3 -0
  666. package/src/permissions/question-prompter.test.ts +416 -0
  667. package/src/permissions/question-prompter.ts +294 -0
  668. package/src/platform/client.test.ts +1 -1
  669. package/src/platform/client.ts +1 -1
  670. package/src/plugin-api/constants.ts +26 -0
  671. package/src/plugin-api/index.ts +46 -0
  672. package/src/plugin-api/package.json +12 -0
  673. package/src/plugin-api/types.ts +144 -0
  674. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  675. package/src/plugins/defaults/compaction.ts +0 -4
  676. package/src/plugins/defaults/empty-response.ts +0 -2
  677. package/src/plugins/defaults/history-repair.ts +0 -2
  678. package/src/plugins/defaults/injectors.ts +55 -6
  679. package/src/plugins/defaults/llm-call.ts +0 -2
  680. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  681. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  682. package/src/plugins/defaults/persistence.ts +0 -2
  683. package/src/plugins/defaults/title-generate.ts +0 -5
  684. package/src/plugins/defaults/token-estimate.ts +0 -2
  685. package/src/plugins/defaults/tool-error.ts +0 -7
  686. package/src/plugins/defaults/tool-execute.ts +0 -2
  687. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  688. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  689. package/src/plugins/external-api.ts +104 -0
  690. package/src/plugins/external-plugin-loader.ts +367 -0
  691. package/src/plugins/feature-gate.ts +22 -0
  692. package/src/plugins/pipeline.ts +37 -0
  693. package/src/plugins/registry.ts +48 -80
  694. package/src/plugins/types.ts +74 -53
  695. package/src/plugins/user-loader.ts +85 -43
  696. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  697. package/src/proactive-artifact/job.test.ts +49 -9
  698. package/src/proactive-artifact/job.ts +4 -0
  699. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  700. package/src/proactive-artifact/trigger-state.ts +4 -0
  701. package/src/prompts/__tests__/system-prompt.test.ts +117 -0
  702. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  703. package/src/prompts/normalize-onboarding.ts +27 -0
  704. package/src/prompts/sections.ts +302 -0
  705. package/src/prompts/system-prompt.ts +72 -154
  706. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  707. package/src/prompts/templates/system-sections.ts +173 -0
  708. package/src/prompts/update-bulletin-job.ts +61 -73
  709. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  710. package/src/providers/__tests__/inference.test.ts +303 -0
  711. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  712. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  713. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  714. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  715. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  716. package/src/providers/anthropic/client.ts +123 -54
  717. package/src/providers/call-site-routing.ts +94 -16
  718. package/src/providers/connection-resolution.ts +170 -0
  719. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  720. package/src/providers/inference/adapter-factory.ts +210 -0
  721. package/src/providers/inference/auth.ts +112 -0
  722. package/src/providers/inference/backfill.ts +196 -0
  723. package/src/providers/inference/connections.ts +401 -0
  724. package/src/providers/inference/resolve-auth.ts +73 -0
  725. package/src/providers/model-catalog.ts +386 -6
  726. package/src/providers/openai/chat-completions-provider.ts +10 -2
  727. package/src/providers/openai/responses-provider.ts +4 -2
  728. package/src/providers/openrouter/client.ts +7 -0
  729. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  730. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  731. package/src/providers/provider-availability.ts +17 -2
  732. package/src/providers/provider-catalog-visibility.ts +36 -0
  733. package/src/providers/provider-env-vars.ts +17 -7
  734. package/src/providers/provider-secret-catalog.ts +49 -30
  735. package/src/providers/provider-send-message.ts +41 -20
  736. package/src/providers/registry.ts +151 -159
  737. package/src/providers/retry.ts +65 -11
  738. package/src/providers/search-provider-catalog.ts +121 -0
  739. package/src/runtime/AGENTS.md +18 -5
  740. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  741. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  742. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  743. package/src/runtime/actor-trust-resolver.ts +32 -10
  744. package/src/runtime/agent-wake.ts +64 -7
  745. package/src/runtime/assistant-event-hub.ts +3 -85
  746. package/src/runtime/auth/route-policy.ts +311 -9
  747. package/src/runtime/auth/same-actor.ts +2 -0
  748. package/src/runtime/background-job-runner.ts +339 -0
  749. package/src/runtime/btw-sidechain.ts +3 -0
  750. package/src/runtime/http-router.ts +36 -1
  751. package/src/runtime/http-server.ts +31 -5
  752. package/src/runtime/http-types.ts +21 -0
  753. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  754. package/src/runtime/middleware/request-logger.ts +62 -1
  755. package/src/runtime/migrations/origin-mode.ts +1 -1
  756. package/src/runtime/pending-interactions.ts +1 -0
  757. package/src/runtime/pre-first-message-gate.ts +83 -0
  758. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  759. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +268 -0
  760. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  761. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +319 -0
  762. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
  763. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  764. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  765. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  766. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  767. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  768. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  769. package/src/runtime/routes/__tests__/tts-routes.test.ts +70 -3
  770. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  771. package/src/runtime/routes/acp-routes.ts +12 -8
  772. package/src/runtime/routes/app-management-routes.ts +228 -3
  773. package/src/runtime/routes/approval-routes.ts +0 -18
  774. package/src/runtime/routes/audit-routes.ts +43 -0
  775. package/src/runtime/routes/auth-routes.ts +72 -0
  776. package/src/runtime/routes/avatar-routes.ts +273 -20
  777. package/src/runtime/routes/backup-routes.ts +406 -2
  778. package/src/runtime/routes/bookmark-routes.ts +156 -0
  779. package/src/runtime/routes/btw-routes.ts +5 -1
  780. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  781. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  782. package/src/runtime/routes/contact-routes.ts +0 -160
  783. package/src/runtime/routes/conversation-cli-routes.ts +233 -0
  784. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  785. package/src/runtime/routes/conversation-management-routes.ts +47 -85
  786. package/src/runtime/routes/conversation-query-routes.ts +350 -97
  787. package/src/runtime/routes/conversation-routes.ts +121 -21
  788. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  789. package/src/runtime/routes/credential-routes.ts +540 -0
  790. package/src/runtime/routes/debug-routes.ts +2 -2
  791. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  792. package/src/runtime/routes/documents-routes.ts +25 -86
  793. package/src/runtime/routes/domain-routes.ts +167 -0
  794. package/src/runtime/routes/email-routes.ts +603 -0
  795. package/src/runtime/routes/errors.ts +2 -2
  796. package/src/runtime/routes/events-routes.ts +192 -0
  797. package/src/runtime/routes/group-routes.ts +5 -0
  798. package/src/runtime/routes/home-feed-routes.ts +6 -78
  799. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  800. package/src/runtime/routes/host-browser-routes.ts +103 -22
  801. package/src/runtime/routes/http-adapter.ts +2 -0
  802. package/src/runtime/routes/identity-routes.ts +5 -0
  803. package/src/runtime/routes/image-generation-routes.ts +99 -0
  804. package/src/runtime/routes/inbound-conversation.ts +28 -8
  805. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  806. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
  807. package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
  808. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  809. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  810. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  811. package/src/runtime/routes/index.ts +42 -0
  812. package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
  813. package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
  814. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  815. package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
  816. package/src/runtime/routes/inference-send-routes.ts +115 -0
  817. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  818. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  819. package/src/runtime/routes/integrations/twilio.ts +7 -13
  820. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  821. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  822. package/src/runtime/routes/notification-routes.ts +3 -1
  823. package/src/runtime/routes/oauth-apps.ts +112 -7
  824. package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
  825. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  826. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  827. package/src/runtime/routes/oauth-providers.ts +298 -8
  828. package/src/runtime/routes/platform-routes.ts +336 -0
  829. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  830. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  831. package/src/runtime/routes/playground/state.ts +2 -1
  832. package/src/runtime/routes/publish-routes.ts +221 -0
  833. package/src/runtime/routes/question-routes.ts +259 -0
  834. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  835. package/src/runtime/routes/schedule-routes.ts +79 -0
  836. package/src/runtime/routes/sequence-routes.ts +291 -0
  837. package/src/runtime/routes/settings-routes.ts +2 -10
  838. package/src/runtime/routes/skills-routes.ts +31 -1
  839. package/src/runtime/routes/stt-routes.ts +240 -3
  840. package/src/runtime/routes/subagents-routes.ts +57 -18
  841. package/src/runtime/routes/surface-action-routes.ts +43 -7
  842. package/src/runtime/routes/telemetry-routes.ts +27 -0
  843. package/src/runtime/routes/tts-routes.ts +93 -1
  844. package/src/runtime/routes/types.ts +32 -0
  845. package/src/runtime/routes/user-routes-cli.ts +243 -0
  846. package/src/runtime/routes/webhook-routes.ts +165 -0
  847. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  848. package/src/runtime/routes/workspace-routes.ts +28 -0
  849. package/src/runtime/services/conversation-serializer.ts +39 -7
  850. package/src/runtime/sync/resource-sync-events.ts +117 -0
  851. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  852. package/src/runtime/sync/sync-publisher.ts +21 -0
  853. package/src/schedule/schedule-store.ts +27 -2
  854. package/src/schedule/scheduler.ts +208 -123
  855. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  856. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  857. package/src/security/secret-patterns.ts +3 -0
  858. package/src/security/untrusted-content.ts +93 -8
  859. package/src/sequence/engine.ts +38 -40
  860. package/src/skills/catalog-files.ts +1 -1
  861. package/src/skills/catalog-install.ts +233 -116
  862. package/src/skills/clawhub.ts +70 -13
  863. package/src/skills/managed-store.ts +4 -119
  864. package/src/skills/skillssh-registry.ts +27 -48
  865. package/src/subagent/manager.ts +28 -15
  866. package/src/telemetry/types.ts +113 -1
  867. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  868. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  869. package/src/tools/apps/executors.ts +58 -7
  870. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  871. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  872. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  873. package/src/tools/browser/browser-execution.ts +29 -14
  874. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  875. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  876. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  877. package/src/tools/browser/cdp-client/factory.ts +66 -5
  878. package/src/tools/browser/runtime-check.ts +77 -0
  879. package/src/tools/computer-use/definitions.ts +3 -3
  880. package/src/tools/credentials/vault.ts +1 -1
  881. package/src/tools/document/document-tool.ts +124 -1
  882. package/src/tools/filesystem/edit.ts +1 -1
  883. package/src/tools/filesystem/list.ts +1 -1
  884. package/src/tools/filesystem/read.ts +1 -1
  885. package/src/tools/filesystem/write.ts +5 -2
  886. package/src/tools/host-filesystem/transfer.ts +1 -1
  887. package/src/tools/host-terminal/host-shell.ts +1 -1
  888. package/src/tools/memory/register.test.ts +3 -3
  889. package/src/tools/memory/register.ts +9 -1
  890. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  891. package/src/tools/network/web-search.ts +280 -37
  892. package/src/tools/permission-checker.ts +14 -6
  893. package/src/tools/registry.ts +17 -7
  894. package/src/tools/schedule/create.ts +2 -2
  895. package/src/tools/schema-transforms.ts +7 -2
  896. package/src/tools/side-effects.ts +1 -0
  897. package/src/tools/skills/delete-managed.ts +4 -4
  898. package/src/tools/skills/execute.ts +1 -1
  899. package/src/tools/skills/scaffold-managed.ts +3 -2
  900. package/src/tools/subagent/notify-parent.ts +1 -1
  901. package/src/tools/subagent/spawn.ts +3 -3
  902. package/src/tools/system/request-permission.ts +2 -2
  903. package/src/tools/terminal/safe-env.ts +60 -1
  904. package/src/tools/terminal/shell.ts +44 -0
  905. package/src/tools/tool-manifest.ts +2 -0
  906. package/src/tools/types.ts +72 -21
  907. package/src/tools/ui-surface/definitions.ts +6 -5
  908. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  909. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  910. package/src/types/onboarding-context.ts +2 -0
  911. package/src/usage/attribution.ts +3 -2
  912. package/src/util/errors.ts +17 -0
  913. package/src/util/platform.ts +10 -0
  914. package/src/util/pricing.ts +86 -160
  915. package/src/watcher/__tests__/engine.test.ts +323 -0
  916. package/src/watcher/constants.ts +7 -0
  917. package/src/watcher/engine.ts +94 -90
  918. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  919. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  920. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +94 -5
  921. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  922. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
  923. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -0
  924. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  925. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  926. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  927. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  928. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  929. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  930. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  931. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  932. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  933. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  934. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  935. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  936. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  937. package/src/workspace/migrations/registry.ts +30 -0
  938. package/src/workspace/migrations/runner.ts +46 -5
  939. package/src/workspace/migrations/types.ts +17 -3
  940. package/src/workspace/provider-commit-message-generator.ts +3 -2
  941. package/examples/plugins/echo/bun.lock +0 -25
  942. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  943. package/src/__tests__/context-window-manager.test.ts +0 -2093
  944. package/src/__tests__/credentials-cli.test.ts +0 -1225
  945. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  946. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  947. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  948. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  949. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  950. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  951. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  952. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  953. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  954. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  955. package/src/cli/commands/autonomy.ts +0 -365
  956. package/src/cli/commands/memory.ts +0 -424
  957. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  958. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  959. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  960. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  961. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  962. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  963. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  964. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  965. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  966. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  967. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  968. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  969. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  970. package/src/context/prompts/compact.md +0 -26
  971. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  972. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  973. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  974. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  975. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  976. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  977. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  978. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  979. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  980. package/src/home/assistant-feed-authoring.ts +0 -135
  981. package/src/home/emit-feed-event.ts +0 -169
  982. package/src/home/feed-scheduler.ts +0 -281
  983. package/src/home/platform-gmail-digest.ts +0 -163
  984. package/src/home/rewrite-command-preview.ts +0 -66
  985. package/src/home/rewrite-feed-title.ts +0 -58
  986. package/src/home/rollup-producer.ts +0 -426
  987. package/src/memory/admin.ts +0 -326
  988. package/src/memory/context-search/sources/pkb.ts +0 -476
  989. package/src/memory/graph/compaction.ts +0 -299
  990. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  991. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -1,36 +1,52 @@
1
1
  import type { Command } from "commander";
2
2
 
3
- import {
4
- getAssistantContactMetadata,
5
- getChannelById,
6
- getContact,
7
- listContacts,
8
- mergeContacts,
9
- searchContacts,
10
- updateChannelStatus,
11
- upsertContact,
12
- } from "../../contacts/contact-store.js";
13
- import type {
14
- AssistantContactMetadata,
15
- ChannelPolicy,
16
- ChannelStatus,
17
- ContactChannel,
18
- ContactRole,
19
- ContactType,
20
- ContactWithChannels,
21
- } from "../../contacts/types.js";
22
- import { cliIpcCall } from "../../ipc/cli-client.js";
23
- import { getDb } from "../../memory/db-connection.js";
24
- import {
25
- createIngressInvite,
26
- listIngressInvites,
27
- redeemIngressInvite,
28
- redeemVoiceInviteCode,
29
- revokeIngressInvite,
30
- } from "../../runtime/invite-service.js";
31
- import type { ContactPromptResult } from "../../runtime/routes/contact-prompt-routes.js";
3
+ import { cliIpcCall, exitFromIpcResult } from "../../ipc/cli-client.js";
4
+ import { registerCommand } from "../lib/register-command.js";
32
5
  import { shouldOutputJson, writeOutput } from "../output.js";
33
6
 
7
+ // ---------------------------------------------------------------------------
8
+ // IPC response shapes
9
+ // ---------------------------------------------------------------------------
10
+
11
+ interface ContactChannel {
12
+ id: string;
13
+ contactId: string;
14
+ type: string;
15
+ address: string;
16
+ status: string;
17
+ policy: string;
18
+ isPrimary?: boolean;
19
+ revokedReason?: string | null;
20
+ blockedReason?: string | null;
21
+ }
22
+
23
+ interface ContactWithChannels {
24
+ id: string;
25
+ displayName: string;
26
+ role: string;
27
+ contactType: string;
28
+ notes?: string;
29
+ principalId?: string;
30
+ createdAt: string | number;
31
+ updatedAt: string | number;
32
+ interactionCount: number;
33
+ channels: ContactChannel[];
34
+ }
35
+
36
+ interface AssistantContactMetadata {
37
+ species: string;
38
+ metadata?: Record<string, unknown> & { assistantId?: string };
39
+ }
40
+
41
+ interface ContactPromptResult {
42
+ ok: boolean;
43
+ error?: string;
44
+ channelType?: string;
45
+ address?: string;
46
+ channelId?: string;
47
+ contactId?: string;
48
+ }
49
+
34
50
  // ---------------------------------------------------------------------------
35
51
  // Human-readable formatters
36
52
  // ---------------------------------------------------------------------------
@@ -129,20 +145,6 @@ function formatContactDetail(
129
145
  return lines.join("\n");
130
146
  }
131
147
 
132
- function formatChannelDetail(ch: ContactChannel): string {
133
- const lines: string[] = [];
134
- lines.push(`ID: ${ch.id}`);
135
- lines.push(`Contact: ${ch.contactId}`);
136
- lines.push(`Type: ${ch.type}`);
137
- lines.push(`Address: ${ch.address}`);
138
- lines.push(`Status: ${ch.status}`);
139
- lines.push(`Policy: ${ch.policy}`);
140
- if (ch.isPrimary) lines.push(`Primary: yes`);
141
- if (ch.revokedReason) lines.push(`Revoked: ${ch.revokedReason}`);
142
- if (ch.blockedReason) lines.push(`Blocked: ${ch.blockedReason}`);
143
- return lines.join("\n");
144
- }
145
-
146
148
  function writeError(cmd: Command, message: string): void {
147
149
  if (shouldOutputJson(cmd)) {
148
150
  writeOutput(cmd, { ok: false, error: message });
@@ -152,14 +154,16 @@ function writeError(cmd: Command, message: string): void {
152
154
  }
153
155
 
154
156
  export function registerContactsCommand(program: Command): void {
155
- const contacts = program
156
- .command("contacts")
157
- .description("Manage and query the contact graph")
158
- .option("--json", "Machine-readable compact JSON output");
159
-
160
- contacts.addHelpText(
161
- "after",
162
- `
157
+ registerCommand(program, {
158
+ name: "contacts",
159
+ transport: "ipc",
160
+ description: "Manage and query the contact graph",
161
+ build: (contacts) => {
162
+ contacts.option("--json", "Machine-readable compact JSON output");
163
+
164
+ contacts.addHelpText(
165
+ "after",
166
+ `
163
167
  Contacts represent people and entities the assistant interacts with. Each
164
168
  contact is identified by a UUID, has a role (contact or guardian), and
165
169
  can be linked to external identifiers — phone numbers,
@@ -169,28 +173,33 @@ is the source of truth for identity resolution across all channels.
169
173
  Examples:
170
174
  $ assistant contacts list
171
175
  $ assistant contacts get abc-123
172
- $ assistant contacts upsert --display-name "Alice"
173
- $ assistant contacts merge keep-id merge-id
174
176
  $ assistant contacts invites list`,
175
- );
176
-
177
- contacts
178
- .command("list")
179
- .description("List contacts")
180
- .option("--role <role>", "Filter by role (contact, guardian, or omit for all)")
181
- .option("--limit <limit>", "Maximum number of contacts to return")
182
- .option("--query <query>", "Search query to filter contacts")
183
- .option(
184
- "--channel-address <address>",
185
- "Search by channel address (email, phone, handle)",
186
- )
187
- .option(
188
- "--channel-type <channelType>",
189
- "Filter by channel type (email, telegram, phone, whatsapp, slack)",
190
- )
191
- .addHelpText(
192
- "after",
193
- `
177
+ );
178
+
179
+ // -----------------------------------------------------------------------
180
+ // list
181
+ // -----------------------------------------------------------------------
182
+
183
+ contacts
184
+ .command("list")
185
+ .description("List contacts")
186
+ .option(
187
+ "--role <role>",
188
+ "Filter by role (contact, guardian, or omit for all)",
189
+ )
190
+ .option("--limit <limit>", "Maximum number of contacts to return")
191
+ .option("--query <query>", "Search query to filter contacts")
192
+ .option(
193
+ "--channel-address <address>",
194
+ "Search by channel address (email, phone, handle)",
195
+ )
196
+ .option(
197
+ "--channel-type <channelType>",
198
+ "Filter by channel type (email, telegram, phone, whatsapp, slack)",
199
+ )
200
+ .addHelpText(
201
+ "after",
202
+ `
194
203
  Lists contacts with optional filtering. The --role flag accepts: contact
195
204
  or guardian (omit to show all). The --limit flag sets
196
205
  the maximum number of results (defaults to 50).
@@ -210,59 +219,61 @@ Examples:
210
219
  $ assistant contacts list --channel-type telegram
211
220
  $ assistant contacts list --query "alice" --channel-type email
212
221
  $ assistant contacts list --role guardian --json`,
213
- )
214
- .action(
215
- async (
216
- opts: {
217
- role?: string;
218
- limit?: string;
219
- query?: string;
220
- channelAddress?: string;
221
- channelType?: string;
222
- },
223
- cmd: Command,
224
- ) => {
225
- try {
226
- getDb();
227
- const role = opts.role as ContactRole | undefined;
228
- const limit = opts.limit ? Number(opts.limit) : undefined;
229
-
230
- const effectiveLimit = limit ?? 50;
231
-
232
- const hasSearchParams =
233
- opts.query || opts.channelAddress || opts.channelType;
234
- const results = hasSearchParams
235
- ? searchContacts({
236
- query: opts.query,
237
- channelAddress: opts.channelAddress,
238
- channelType: opts.channelType,
239
- role,
240
- limit: effectiveLimit,
241
- })
242
- : listContacts(effectiveLimit, role);
222
+ )
223
+ .action(
224
+ async (
225
+ opts: {
226
+ role?: string;
227
+ limit?: string;
228
+ query?: string;
229
+ channelAddress?: string;
230
+ channelType?: string;
231
+ },
232
+ cmd: Command,
233
+ ) => {
234
+ const r = await cliIpcCall<{
235
+ ok: boolean;
236
+ contacts: ContactWithChannels[];
237
+ }>("listContacts", {
238
+ queryParams: {
239
+ ...(opts.role && { role: opts.role }),
240
+ ...(opts.limit && { limit: opts.limit }),
241
+ ...(opts.query && { query: opts.query }),
242
+ ...(opts.channelAddress && {
243
+ channelAddress: opts.channelAddress,
244
+ }),
245
+ ...(opts.channelType && { channelType: opts.channelType }),
246
+ },
247
+ });
243
248
 
244
- if (shouldOutputJson(cmd)) {
245
- writeOutput(cmd, { ok: true, contacts: results });
246
- } else if (results.length === 0) {
247
- process.stdout.write("No contacts found.\n");
248
- } else {
249
- process.stdout.write(formatContactTable(results) + "\n");
250
- process.stdout.write(`\n${results.length} contact(s)\n`);
251
- }
252
- } catch (err) {
253
- const message = err instanceof Error ? err.message : String(err);
254
- writeError(cmd, message);
255
- process.exitCode = 1;
256
- }
257
- },
258
- );
249
+ if (!r.ok)
250
+ return exitFromIpcResult(
251
+ r as { ok: false; error?: string; statusCode?: number },
252
+ cmd,
253
+ );
259
254
 
260
- contacts
261
- .command("get <id>")
262
- .description("Get a contact by ID")
263
- .addHelpText(
264
- "after",
265
- `
255
+ const results = r.result!.contacts;
256
+ if (shouldOutputJson(cmd)) {
257
+ writeOutput(cmd, { ok: true, contacts: results });
258
+ } else if (results.length === 0) {
259
+ process.stdout.write("No contacts found.\n");
260
+ } else {
261
+ process.stdout.write(formatContactTable(results) + "\n");
262
+ process.stdout.write(`\n${results.length} contact(s)\n`);
263
+ }
264
+ },
265
+ );
266
+
267
+ // -----------------------------------------------------------------------
268
+ // get
269
+ // -----------------------------------------------------------------------
270
+
271
+ contacts
272
+ .command("get <id>")
273
+ .description("Get a contact by ID")
274
+ .addHelpText(
275
+ "after",
276
+ `
266
277
  Arguments:
267
278
  id UUID of the contact to retrieve. Run 'assistant contacts list' to find IDs.
268
279
 
@@ -273,259 +284,144 @@ For assistant-type contacts, additional assistant metadata is included.
273
284
  Examples:
274
285
  $ assistant contacts get 7a3b1c2d-4e5f-6789-abcd-ef0123456789
275
286
  $ assistant contacts get abc-123 --json`,
276
- )
277
- .action(async (id: string, _opts: unknown, cmd: Command) => {
278
- try {
279
- getDb();
280
- const contact = getContact(id);
281
- if (!contact) {
282
- writeError(cmd, "Contact not found");
283
- process.exitCode = 1;
284
- return;
285
- }
286
- const assistantMeta =
287
- contact.contactType === "assistant"
288
- ? getAssistantContactMetadata(contact.id)
289
- : undefined;
290
- if (shouldOutputJson(cmd)) {
291
- writeOutput(cmd, {
292
- ok: true,
293
- contact,
294
- assistantMetadata: assistantMeta ?? undefined,
287
+ )
288
+ .action(async (id: string, _opts: unknown, cmd: Command) => {
289
+ const r = await cliIpcCall<{
290
+ ok: boolean;
291
+ contact: ContactWithChannels;
292
+ assistantMetadata?: AssistantContactMetadata;
293
+ }>("getContact", {
294
+ pathParams: { id },
295
295
  });
296
- } else {
297
- process.stdout.write(
298
- formatContactDetail(contact, assistantMeta ?? undefined) + "\n",
299
- );
300
- }
301
- } catch (err) {
302
- const message = err instanceof Error ? err.message : String(err);
303
- writeError(cmd, message);
304
- process.exitCode = 1;
305
- }
306
- });
307
-
308
- contacts
309
- .command("merge <keepId> <mergeId>")
310
- .description("Merge two contacts")
311
- .addHelpText(
312
- "after",
313
- `
314
- Arguments:
315
- keepId UUID of the surviving contact that will absorb the other.
316
- Run 'assistant contacts list' to find IDs.
317
- mergeId UUID of the contact to be merged and deleted
318
296
 
319
- All channel memberships, conversation history, and metadata from mergeId
320
- are transferred to keepId. After the merge, mergeId is permanently deleted.
321
- This operation is irreversible.
297
+ if (!r.ok)
298
+ return exitFromIpcResult(
299
+ r as { ok: false; error?: string; statusCode?: number },
300
+ cmd,
301
+ );
322
302
 
323
- Examples:
324
- $ assistant contacts merge 7a3b1c2d-4e5f-6789-abcd-ef0123456789 9f8e7d6c-5b4a-3210-fedc-ba9876543210
325
- $ assistant contacts merge keep-id merge-id --json`,
326
- )
327
- .action(
328
- async (keepId: string, mergeId: string, _opts: unknown, cmd: Command) => {
329
- try {
330
- getDb();
331
- const contact = mergeContacts(keepId, mergeId);
303
+ const { contact, assistantMetadata } = r.result!;
332
304
  if (shouldOutputJson(cmd)) {
333
- writeOutput(cmd, { ok: true, contact });
305
+ writeOutput(cmd, {
306
+ ok: true,
307
+ contact,
308
+ assistantMetadata: assistantMetadata ?? undefined,
309
+ });
334
310
  } else {
335
311
  process.stdout.write(
336
- `Merged ${mergeId} into ${keepId}\n` +
337
- formatContactDetail(contact) +
312
+ formatContactDetail(contact, assistantMetadata ?? undefined) +
338
313
  "\n",
339
314
  );
340
315
  }
341
- } catch (err) {
342
- const message = err instanceof Error ? err.message : String(err);
343
- writeError(cmd, message);
344
- process.exitCode = 1;
345
- }
346
- },
347
- );
316
+ });
317
+
318
+ // -----------------------------------------------------------------------
319
+ // prompt
320
+ // -----------------------------------------------------------------------
321
+
322
+ contacts
323
+ .command("prompt")
324
+ .description(
325
+ "Prompt user to register a contact channel via the app UI",
326
+ )
327
+ .option(
328
+ "--channel <channel>",
329
+ "Suggested channel type hint (e.g. phone, email, telegram)",
330
+ )
331
+ .option(
332
+ "--placeholder <placeholder>",
333
+ "Placeholder text for the address input field",
334
+ )
335
+ .option(
336
+ "--role <role>",
337
+ "Intended role: guardian, trusted-contact, or unknown (default: unknown)",
338
+ )
339
+ .option("--label <label>", "Display label shown in the prompt UI")
340
+ .option(
341
+ "--description <description>",
342
+ "Longer description shown in the prompt UI",
343
+ )
344
+ .option(
345
+ "--timeout <ms>",
346
+ "How long to wait for the user to submit (ms). Defaults to match the server-side prompt timeout.",
347
+ String(310_000),
348
+ )
349
+ .addHelpText(
350
+ "after",
351
+ `
352
+ Opens a contact address prompt in the user's app. The user enters a channel
353
+ address (phone number, email, Telegram ID, etc.). The address is saved with
354
+ status "unverified". Verification is a separate step.
355
+
356
+ Run \`assistant contacts prompt --help\` for full option details.`,
357
+ )
358
+ .action(
359
+ async (
360
+ opts: {
361
+ channel?: string;
362
+ placeholder?: string;
363
+ role?: string;
364
+ label?: string;
365
+ description?: string;
366
+ timeout?: string;
367
+ },
368
+ cmd: Command,
369
+ ) => {
370
+ const timeoutMs = opts.timeout ? parseInt(opts.timeout, 10) : 310_000;
371
+ const r = await cliIpcCall<ContactPromptResult>(
372
+ "contacts_prompt",
373
+ {
374
+ body: {
375
+ channel: opts.channel,
376
+ placeholder: opts.placeholder,
377
+ role: opts.role ?? "unknown",
378
+ label: opts.label,
379
+ description: opts.description,
380
+ },
381
+ },
382
+ { timeoutMs },
383
+ );
348
384
 
349
- contacts
350
- .command("upsert")
351
- .description("Create or update a contact")
352
- .requiredOption("--display-name <name>", "Display name for the contact")
353
- .option("--id <id>", "Contact ID — provide to update an existing contact")
354
- .option("--notes <notes>", "Free-text notes about the contact")
355
- .option(
356
- "--role <role>",
357
- "Contact role: contact or guardian (default: contact for new contacts)",
358
- )
359
- .option(
360
- "--contact-type <type>",
361
- "Contact type: human or assistant (default: human for new contacts)",
362
- )
363
- .option(
364
- "--channels <json>",
365
- "JSON array of channel objects, each with type, address, and optional isPrimary, externalUserId, externalChatId, status, policy",
366
- )
367
- .addHelpText(
368
- "after",
369
- `
370
- Creates a new contact or updates an existing one. When --id is provided and
371
- matches an existing contact, that contact is updated. When --id is omitted,
372
- a new contact is created with a generated UUID.
373
-
374
- The --channels flag accepts a JSON array of channel objects. Each object must
375
- have "type" (e.g. telegram, phone, email, whatsapp) and "address" fields.
376
- Optional channel fields: isPrimary (boolean), externalUserId, externalChatId,
377
- status (active, revoked, blocked), policy (allow, deny).
385
+ if (!r.ok)
386
+ return exitFromIpcResult(
387
+ r as { ok: false; error?: string; statusCode?: number },
388
+ cmd,
389
+ );
378
390
 
379
- Examples:
380
- $ assistant contacts upsert --display-name "Alice" --json
381
- $ assistant contacts upsert --display-name "Alice" --id abc-123 --notes "Updated notes" --json
382
- $ assistant contacts upsert --display-name "Bob" --role guardian --json
383
- $ assistant contacts upsert --display-name "Bob" --channels '[{"type":"telegram","address":"12345","externalUserId":"12345","status":"active","policy":"allow"}]' --json`,
384
- )
385
- .action(
386
- async (
387
- opts: {
388
- displayName: string;
389
- id?: string;
390
- notes?: string;
391
- role?: string;
392
- contactType?: string;
393
- channels?: string;
394
- },
395
- cmd: Command,
396
- ) => {
397
- try {
398
- getDb();
399
-
400
- let channels: unknown[] | undefined;
401
- if (opts.channels) {
402
- try {
403
- channels = JSON.parse(opts.channels);
404
- if (!Array.isArray(channels)) {
405
- writeError(cmd, "--channels must be a JSON array");
406
- process.exitCode = 1;
407
- return;
408
- }
409
- } catch {
391
+ if (!r.result?.ok) {
410
392
  writeError(
411
393
  cmd,
412
- `Invalid JSON for --channels: ${opts.channels}`,
394
+ r.result?.error ?? "Contact prompt failed",
413
395
  );
414
396
  process.exitCode = 1;
415
397
  return;
416
398
  }
417
- }
418
399
 
419
- const result = upsertContact({
420
- id: opts.id,
421
- displayName: opts.displayName,
422
- notes: opts.notes,
423
- role: opts.role as ContactRole | undefined,
424
- contactType: opts.contactType as ContactType | undefined,
425
- channels: channels as
426
- | {
427
- type: string;
428
- address: string;
429
- isPrimary?: boolean;
430
- externalUserId?: string;
431
- externalChatId?: string;
432
- status?: ChannelStatus;
433
- policy?: ChannelPolicy;
434
- }[]
435
- | undefined,
436
- });
437
-
438
- if (shouldOutputJson(cmd)) {
439
- writeOutput(cmd, { ok: true, contact: result });
440
- } else {
441
- process.stdout.write(formatContactDetail(result) + "\n");
442
- }
443
- } catch (err) {
444
- const message = err instanceof Error ? err.message : String(err);
445
- writeError(cmd, message);
446
- process.exitCode = 1;
447
- }
448
- },
449
- );
450
-
451
- contacts
452
- .command("prompt")
453
- .description("Prompt user to register a contact channel via the app UI")
454
- .option("--channel <channel>", "Suggested channel type hint (e.g. phone, email, telegram)")
455
- .option("--placeholder <placeholder>", "Placeholder text for the address input field")
456
- .option("--role <role>", "Intended role: guardian, trusted-contact, or unknown (default: unknown)")
457
- .option("--label <label>", "Display label shown in the prompt UI")
458
- .option("--description <description>", "Longer description shown in the prompt UI")
459
- .option("--timeout <ms>", "How long to wait for the user to submit (ms). Defaults to match the server-side prompt timeout.", String(310_000))
460
- .addHelpText(
461
- "after",
462
- `
463
- Opens a contact address prompt in the user's app. The user enters a channel
464
- address (phone number, email, Telegram ID, etc.). The address is saved with
465
- status "unverified". Verification is a separate step.
466
-
467
- Run \`assistant contacts prompt --help\` for full option details.`,
468
- )
469
- .action(
470
- async (
471
- opts: {
472
- channel?: string;
473
- placeholder?: string;
474
- role?: string;
475
- label?: string;
476
- description?: string;
477
- timeout?: string;
478
- },
479
- cmd: Command,
480
- ) => {
481
- try {
482
- const timeoutMs = opts.timeout ? parseInt(opts.timeout, 10) : 310_000;
483
- const ipc = await cliIpcCall<ContactPromptResult>(
484
- "contacts_prompt",
485
- {
486
- body: {
487
- channel: opts.channel,
488
- placeholder: opts.placeholder,
489
- role: opts.role ?? "unknown",
490
- label: opts.label,
491
- description: opts.description,
492
- },
493
- },
494
- { timeoutMs },
495
- );
496
-
497
- if (!ipc.ok || !ipc.result?.ok) {
498
- writeError(cmd, ipc.error ?? ipc.result?.error ?? "Contact prompt failed");
499
- process.exitCode = 1;
500
- return;
501
- }
400
+ const result = r.result;
401
+ if (shouldOutputJson(cmd)) {
402
+ writeOutput(cmd, result);
403
+ } else {
404
+ process.stdout.write(
405
+ `Registered ${result.channelType} channel: ${result.address}\n` +
406
+ ` Channel ID: ${result.channelId}\n` +
407
+ ` Contact ID: ${result.contactId}\n` +
408
+ ` Status: unverified\n`,
409
+ );
410
+ }
411
+ },
412
+ );
502
413
 
503
- const result = ipc.result;
504
- if (shouldOutputJson(cmd)) {
505
- writeOutput(cmd, result);
506
- } else {
507
- process.stdout.write(
508
- `Registered ${result.channelType} channel: ${result.address}\n` +
509
- ` Channel ID: ${result.channelId}\n` +
510
- ` Contact ID: ${result.contactId}\n` +
511
- ` Status: unverified\n`,
512
- );
513
- }
514
- } catch (err) {
515
- const message = err instanceof Error ? err.message : String(err);
516
- writeError(cmd, message);
517
- process.exitCode = 1;
518
- }
519
- },
520
- );
414
+ // -----------------------------------------------------------------------
415
+ // channels
416
+ // -----------------------------------------------------------------------
521
417
 
522
- const channelsCmds = contacts
523
- .command("channels")
524
- .description("Manage contact channels");
418
+ const channelsCmds = contacts
419
+ .command("channels")
420
+ .description("Manage contact channels");
525
421
 
526
- channelsCmds.addHelpText(
527
- "after",
528
- `
422
+ channelsCmds.addHelpText(
423
+ "after",
424
+ `
529
425
  Channels represent external communication endpoints linked to contacts —
530
426
  phone numbers, Telegram IDs, email addresses, etc. Each channel has a
531
427
  status (active, pending, revoked, blocked, unverified) and a policy
@@ -535,20 +431,23 @@ from that channel.
535
431
  Examples:
536
432
  $ assistant contacts channels update-status <channelId> --status revoked --reason "No longer needed"
537
433
  $ assistant contacts channels update-status <channelId> --policy deny`,
538
- );
539
-
540
- channelsCmds
541
- .command("update-status <channelId>")
542
- .description("Update a channel's status or policy")
543
- .option(
544
- "--status <status>",
545
- "New channel status: active, revoked, or blocked",
546
- )
547
- .option("--policy <policy>", "New channel policy: allow, deny, or escalate")
548
- .option("--reason <reason>", "Reason for the status change")
549
- .addHelpText(
550
- "after",
551
- `
434
+ );
435
+
436
+ channelsCmds
437
+ .command("update-status <channelId>")
438
+ .description("Update a channel's status or policy")
439
+ .option(
440
+ "--status <status>",
441
+ "New channel status: active, revoked, or blocked",
442
+ )
443
+ .option(
444
+ "--policy <policy>",
445
+ "New channel policy: allow, deny, or escalate",
446
+ )
447
+ .option("--reason <reason>", "Reason for the status change")
448
+ .addHelpText(
449
+ "after",
450
+ `
552
451
  Arguments:
553
452
  channelId UUID of the contact channel to update. Run 'assistant contacts get <contactId>'
554
453
  to see a contact's channel IDs.
@@ -568,85 +467,65 @@ Examples:
568
467
  $ assistant contacts channels update-status abc-123 --status blocked --reason "Spam" --json
569
468
  $ assistant contacts channels update-status abc-123 --policy deny --json
570
469
  $ assistant contacts channels update-status abc-123 --status active --policy allow --json`,
571
- )
572
- .action(
573
- async (
574
- channelId: string,
575
- opts: {
576
- status?: string;
577
- policy?: string;
578
- reason?: string;
579
- },
580
- cmd: Command,
581
- ) => {
582
- try {
583
- if (!opts.status && !opts.policy) {
584
- writeError(
585
- cmd,
586
- "At least one of --status or --policy must be provided",
587
- );
588
- process.exitCode = 1;
589
- return;
590
- }
591
-
592
- getDb();
593
-
594
- const existing = getChannelById(channelId);
595
- if (!existing) {
596
- writeError(cmd, `Channel not found: ${channelId}`);
597
- process.exitCode = 1;
598
- return;
599
- }
600
-
601
- const status = opts.status as ChannelStatus | undefined;
602
- const policy = opts.policy as ChannelPolicy | undefined;
470
+ )
471
+ .action(
472
+ async (
473
+ channelId: string,
474
+ opts: {
475
+ status?: string;
476
+ policy?: string;
477
+ reason?: string;
478
+ },
479
+ cmd: Command,
480
+ ) => {
481
+ if (!opts.status && !opts.policy) {
482
+ writeError(
483
+ cmd,
484
+ "At least one of --status or --policy must be provided",
485
+ );
486
+ process.exitCode = 1;
487
+ return;
488
+ }
603
489
 
604
- const revokedReason: string | null | undefined =
605
- status !== undefined
606
- ? status === "revoked"
607
- ? (opts.reason ?? null)
608
- : null
609
- : undefined;
610
- const blockedReason: string | null | undefined =
611
- status !== undefined
612
- ? status === "blocked"
613
- ? (opts.reason ?? null)
614
- : null
615
- : undefined;
490
+ const r = await cliIpcCall<{
491
+ ok: boolean;
492
+ contact?: ContactWithChannels;
493
+ }>("updateContactChannel", {
494
+ pathParams: { contactChannelId: channelId },
495
+ body: {
496
+ status: opts.status,
497
+ policy: opts.policy,
498
+ reason: opts.reason,
499
+ },
500
+ });
616
501
 
617
- const result = updateChannelStatus(channelId, {
618
- status,
619
- policy,
620
- revokedReason,
621
- blockedReason,
622
- });
502
+ if (!r.ok)
503
+ return exitFromIpcResult(
504
+ r as { ok: false; error?: string; statusCode?: number },
505
+ cmd,
506
+ );
623
507
 
624
- if (!result) {
625
- writeError(cmd, `Failed to update channel: ${channelId}`);
626
- process.exitCode = 1;
627
- return;
628
- }
508
+ if (shouldOutputJson(cmd)) {
509
+ writeOutput(cmd, r.result);
510
+ } else {
511
+ process.stdout.write(
512
+ `Updated channel ${channelId}\n`,
513
+ );
514
+ }
515
+ },
516
+ );
629
517
 
630
- if (shouldOutputJson(cmd)) {
631
- writeOutput(cmd, { ok: true, channel: result });
632
- } else {
633
- process.stdout.write(formatChannelDetail(result) + "\n");
634
- }
635
- } catch (err) {
636
- const message = err instanceof Error ? err.message : String(err);
637
- writeError(cmd, message);
638
- process.exitCode = 1;
639
- }
640
- },
641
- );
518
+ // -----------------------------------------------------------------------
519
+ // invites
520
+ // -----------------------------------------------------------------------
642
521
 
643
- const invites = contacts
644
- .command("invites")
645
- .description("Manage contact invites");
522
+ const invites = contacts
523
+ .command("invites")
524
+ .description("Manage contact invites");
646
525
 
647
- invites.addHelpText(
648
- "after",
649
- `
526
+ invites.addHelpText(
527
+ "after",
528
+ `
650
529
  Invites are tokens that grant channel access when redeemed. Each invite is
651
530
  tied to a source channel (telegram, phone, email, whatsapp) and can
652
531
  optionally have usage limits, expiration, and notes. When redeemed, the
@@ -658,16 +537,16 @@ Examples:
658
537
  $ assistant contacts invites create --source-channel telegram
659
538
  $ assistant contacts invites revoke abc-123
660
539
  $ assistant contacts invites redeem --token xyz-789 --source-channel telegram --external-user-id 12345`,
661
- );
662
-
663
- invites
664
- .command("list", { isDefault: true })
665
- .description("List invites")
666
- .option("--source-channel <sourceChannel>", "Filter by source channel")
667
- .option("--status <status>", "Filter by invite status")
668
- .addHelpText(
669
- "after",
670
- `
540
+ );
541
+
542
+ invites
543
+ .command("list", { isDefault: true })
544
+ .description("List invites")
545
+ .option("--source-channel <sourceChannel>", "Filter by source channel")
546
+ .option("--status <status>", "Filter by invite status")
547
+ .addHelpText(
548
+ "after",
549
+ `
671
550
  Lists all invites with optional filtering by source channel or status.
672
551
  Returns invite tokens, their source channels, usage counts, and expiration.
673
552
 
@@ -676,29 +555,42 @@ Examples:
676
555
  $ assistant contacts invites list --source-channel telegram
677
556
  $ assistant contacts invites list --status active
678
557
  $ assistant contacts invites list --source-channel phone --json`,
679
- )
680
- .action(
681
- async (
682
- opts: { sourceChannel?: string; status?: string },
683
- cmd: Command,
684
- ) => {
685
- try {
686
- getDb();
687
- const result = listIngressInvites({
688
- sourceChannel: opts.sourceChannel,
689
- status: opts.status,
690
- });
691
- if (!result.ok) {
692
- writeError(cmd, (result as { error?: string }).error ?? "Failed");
693
- process.exitCode = 1;
694
- return;
695
- }
696
- if (shouldOutputJson(cmd)) {
697
- writeOutput(cmd, { ok: true, invites: result.data });
698
- } else if (result.data.length === 0) {
699
- process.stdout.write("No invites found.\n");
700
- } else {
701
- for (const inv of result.data) {
558
+ )
559
+ .action(
560
+ async (
561
+ opts: { sourceChannel?: string; status?: string },
562
+ cmd: Command,
563
+ ) => {
564
+ const r = await cliIpcCall<{
565
+ ok: boolean;
566
+ invites: Array<{
567
+ id: string;
568
+ sourceChannel: string;
569
+ status: string;
570
+ token?: string;
571
+ }>;
572
+ }>("invites_list", {
573
+ queryParams: {
574
+ ...(opts.sourceChannel && {
575
+ sourceChannel: opts.sourceChannel,
576
+ }),
577
+ ...(opts.status && { status: opts.status }),
578
+ },
579
+ });
580
+
581
+ if (!r.ok)
582
+ return exitFromIpcResult(
583
+ r as { ok: false; error?: string; statusCode?: number },
584
+ cmd,
585
+ );
586
+
587
+ const invitesList = r.result!.invites;
588
+ if (shouldOutputJson(cmd)) {
589
+ writeOutput(cmd, { ok: true, invites: invitesList });
590
+ } else if (invitesList.length === 0) {
591
+ process.stdout.write("No invites found.\n");
592
+ } else {
593
+ for (const inv of invitesList) {
702
594
  const parts = [
703
595
  inv.id,
704
596
  inv.sourceChannel,
@@ -707,43 +599,44 @@ Examples:
707
599
  ].filter(Boolean);
708
600
  process.stdout.write(parts.join(" ") + "\n");
709
601
  }
710
- process.stdout.write(`\n${result.data.length} invite(s)\n`);
602
+ process.stdout.write(`\n${invitesList.length} invite(s)\n`);
711
603
  }
712
- } catch (err) {
713
- const message = err instanceof Error ? err.message : String(err);
714
- writeError(cmd, message);
715
- process.exitCode = 1;
716
- }
717
- },
718
- );
719
-
720
- invites
721
- .command("create")
722
- .description("Create a new invite")
723
- .requiredOption(
724
- "--source-channel <channel>",
725
- "Source channel (e.g. telegram, phone, email, whatsapp)",
726
- )
727
- .option("--note <note>", "Optional note")
728
- .option("--max-uses <n>", "Max redemptions")
729
- .option("--expires-in-ms <ms>", "Expiry duration in milliseconds")
730
- .option(
731
- "--contact-name <name>",
732
- "Contact name for personalizing instructions",
733
- )
734
- .option(
735
- "--expected-external-user-id <id>",
736
- "E.164 phone number (required for voice invites)",
737
- )
738
- .option("--friend-name <name>", "Friend name (required for voice invites)")
739
- .option(
740
- "--guardian-name <name>",
741
- "Guardian name (required for voice invites)",
742
- )
743
- .requiredOption("--contact-id <id>", "Contact ID to bind the invite to")
744
- .addHelpText(
745
- "after",
746
- `
604
+ },
605
+ );
606
+
607
+ invites
608
+ .command("create")
609
+ .description("Create a new invite")
610
+ .requiredOption(
611
+ "--source-channel <channel>",
612
+ "Source channel (e.g. telegram, phone, email, whatsapp)",
613
+ )
614
+ .option("--note <note>", "Optional note")
615
+ .option("--max-uses <n>", "Max redemptions")
616
+ .option("--expires-in-ms <ms>", "Expiry duration in milliseconds")
617
+ .option(
618
+ "--contact-name <name>",
619
+ "Contact name for personalizing instructions",
620
+ )
621
+ .option(
622
+ "--expected-external-user-id <id>",
623
+ "E.164 phone number (required for voice invites)",
624
+ )
625
+ .option(
626
+ "--friend-name <name>",
627
+ "Friend name (required for voice invites)",
628
+ )
629
+ .option(
630
+ "--guardian-name <name>",
631
+ "Guardian name (required for voice invites)",
632
+ )
633
+ .requiredOption(
634
+ "--contact-id <id>",
635
+ "Contact ID to bind the invite to",
636
+ )
637
+ .addHelpText(
638
+ "after",
639
+ `
747
640
  Creates a new invite token for the specified source channel. The --source-channel
748
641
  flag is required and must be one of: telegram, phone, email, whatsapp.
749
642
 
@@ -761,86 +654,89 @@ Voice invites require three additional fields:
761
654
  Examples:
762
655
  $ assistant contacts invites create --source-channel telegram --note "For Alice" --max-uses 1
763
656
  $ assistant contacts invites create --source-channel phone --expected-external-user-id "+15551234567" --friend-name "Alice" --guardian-name "Bob" --contact-name "Alice Smith"`,
764
- )
765
- .action(
766
- async (
767
- opts: {
768
- sourceChannel: string;
769
- note?: string;
770
- maxUses?: string;
771
- expiresInMs?: string;
772
- contactName?: string;
773
- expectedExternalUserId?: string;
774
- friendName?: string;
775
- guardianName?: string;
776
- contactId: string;
777
- },
778
- cmd: Command,
779
- ) => {
780
- try {
781
- const maxUses = opts.maxUses ? Number(opts.maxUses) : undefined;
782
- if (maxUses !== undefined && !Number.isFinite(maxUses)) {
783
- writeError(
784
- cmd,
785
- `--max-uses must be a number, got: ${opts.maxUses}`,
786
- );
787
- process.exitCode = 1;
788
- return;
789
- }
790
- const expiresInMs = opts.expiresInMs
791
- ? Number(opts.expiresInMs)
792
- : undefined;
793
- if (expiresInMs !== undefined && !Number.isFinite(expiresInMs)) {
794
- writeError(
795
- cmd,
796
- `--expires-in-ms must be a number, got: ${opts.expiresInMs}`,
797
- );
798
- process.exitCode = 1;
799
- return;
800
- }
801
- getDb();
802
- const result = await createIngressInvite({
803
- sourceChannel: opts.sourceChannel,
804
- note: opts.note,
805
- maxUses,
806
- expiresInMs,
807
- contactName: opts.contactName,
808
- expectedExternalUserId: opts.expectedExternalUserId,
809
- friendName: opts.friendName,
810
- guardianName: opts.guardianName,
811
- contactId: opts.contactId,
812
- });
813
- if (!result.ok) {
814
- writeError(
815
- cmd,
816
- (result as { error?: string }).error ?? "Failed",
817
- );
818
- process.exitCode = 1;
819
- return;
820
- }
821
- if (shouldOutputJson(cmd)) {
822
- writeOutput(cmd, { ok: true, invite: result.data });
657
+ )
658
+ .action(
659
+ async (
660
+ opts: {
661
+ sourceChannel: string;
662
+ note?: string;
663
+ maxUses?: string;
664
+ expiresInMs?: string;
665
+ contactName?: string;
666
+ expectedExternalUserId?: string;
667
+ friendName?: string;
668
+ guardianName?: string;
669
+ contactId: string;
670
+ },
671
+ cmd: Command,
672
+ ) => {
673
+ const maxUses = opts.maxUses ? Number(opts.maxUses) : undefined;
674
+ if (maxUses !== undefined && !Number.isFinite(maxUses)) {
675
+ writeError(
676
+ cmd,
677
+ `--max-uses must be a number, got: ${opts.maxUses}`,
678
+ );
679
+ process.exitCode = 1;
680
+ return;
681
+ }
682
+ const expiresInMs = opts.expiresInMs
683
+ ? Number(opts.expiresInMs)
684
+ : undefined;
685
+ if (expiresInMs !== undefined && !Number.isFinite(expiresInMs)) {
686
+ writeError(
687
+ cmd,
688
+ `--expires-in-ms must be a number, got: ${opts.expiresInMs}`,
689
+ );
690
+ process.exitCode = 1;
691
+ return;
692
+ }
693
+
694
+ const r = await cliIpcCall<{
695
+ ok: boolean;
696
+ invite: {
697
+ id: string;
698
+ sourceChannel: string;
699
+ token?: string;
700
+ };
701
+ }>("invites_create", {
702
+ body: {
703
+ sourceChannel: opts.sourceChannel,
704
+ note: opts.note,
705
+ maxUses,
706
+ expiresInMs,
707
+ contactName: opts.contactName,
708
+ expectedExternalUserId: opts.expectedExternalUserId,
709
+ friendName: opts.friendName,
710
+ guardianName: opts.guardianName,
711
+ contactId: opts.contactId,
712
+ },
713
+ });
714
+
715
+ if (!r.ok)
716
+ return exitFromIpcResult(
717
+ r as { ok: false; error?: string; statusCode?: number },
718
+ cmd,
719
+ );
720
+
721
+ const { invite } = r.result!;
722
+ if (shouldOutputJson(cmd)) {
723
+ writeOutput(cmd, { ok: true, invite });
823
724
  } else {
824
725
  process.stdout.write(
825
- `Created invite ${result.data.id} (${result.data.sourceChannel})\n`,
726
+ `Created invite ${invite.id} (${invite.sourceChannel})\n`,
826
727
  );
827
- if (result.data.token)
828
- process.stdout.write(`Token: ${result.data.token}\n`);
728
+ if (invite.token)
729
+ process.stdout.write(`Token: ${invite.token}\n`);
829
730
  }
830
- } catch (err) {
831
- const message = err instanceof Error ? err.message : String(err);
832
- writeError(cmd, message);
833
- process.exitCode = 1;
834
- }
835
- },
836
- );
837
-
838
- invites
839
- .command("revoke <inviteId>")
840
- .description("Revoke an active invite")
841
- .addHelpText(
842
- "after",
843
- `
731
+ },
732
+ );
733
+
734
+ invites
735
+ .command("revoke <inviteId>")
736
+ .description("Revoke an active invite")
737
+ .addHelpText(
738
+ "after",
739
+ `
844
740
  Arguments:
845
741
  inviteId UUID of the invite to revoke. Run 'assistant contacts invites list' to find IDs.
846
742
 
@@ -850,47 +746,47 @@ channel memberships are not affected. Returns the updated invite record.
850
746
  Examples:
851
747
  $ assistant contacts invites revoke 7a3b1c2d-4e5f-6789-abcd-ef0123456789
852
748
  $ assistant contacts invites revoke abc-123 --json`,
853
- )
854
- .action(async (inviteId: string, _opts: unknown, cmd: Command) => {
855
- try {
856
- getDb();
857
- const result = revokeIngressInvite(inviteId);
858
- if (!result.ok) {
859
- writeError(
860
- cmd,
861
- (result as { error?: string }).error ?? "Failed",
862
- );
863
- process.exitCode = 1;
864
- return;
865
- }
866
- if (shouldOutputJson(cmd)) {
867
- writeOutput(cmd, { ok: true, invite: result.data });
868
- } else {
869
- process.stdout.write(`Revoked invite ${inviteId}\n`);
870
- }
871
- } catch (err) {
872
- const message = err instanceof Error ? err.message : String(err);
873
- writeError(cmd, message);
874
- process.exitCode = 1;
875
- }
876
- });
877
-
878
- invites
879
- .command("redeem")
880
- .description("Redeem an invite via token or voice code")
881
- .option("--token <token>", "Invite token")
882
- .option("--source-channel <channel>", "Channel for redemption")
883
- .option("--external-user-id <id>", "External user ID")
884
- .option("--external-chat-id <id>", "External chat ID")
885
- .option("--code <code>", "6-digit voice code")
886
- .option(
887
- "--caller-external-user-id <phone>",
888
- "E.164 phone number for voice code redemption",
889
- )
890
- .option("--assistant-id <id>", "Assistant ID for voice code redemption")
891
- .addHelpText(
892
- "after",
893
- `
749
+ )
750
+ .action(async (inviteId: string, _opts: unknown, cmd: Command) => {
751
+ const r = await cliIpcCall<{
752
+ ok: boolean;
753
+ invite: unknown;
754
+ }>("invites_revoke", {
755
+ pathParams: { id: inviteId },
756
+ });
757
+
758
+ if (!r.ok)
759
+ return exitFromIpcResult(
760
+ r as { ok: false; error?: string; statusCode?: number },
761
+ cmd,
762
+ );
763
+
764
+ if (shouldOutputJson(cmd)) {
765
+ writeOutput(cmd, { ok: true, invite: r.result!.invite });
766
+ } else {
767
+ process.stdout.write(`Revoked invite ${inviteId}\n`);
768
+ }
769
+ });
770
+
771
+ invites
772
+ .command("redeem")
773
+ .description("Redeem an invite via token or voice code")
774
+ .option("--token <token>", "Invite token")
775
+ .option("--source-channel <channel>", "Channel for redemption")
776
+ .option("--external-user-id <id>", "External user ID")
777
+ .option("--external-chat-id <id>", "External chat ID")
778
+ .option("--code <code>", "6-digit voice code")
779
+ .option(
780
+ "--caller-external-user-id <phone>",
781
+ "E.164 phone number for voice code redemption",
782
+ )
783
+ .option(
784
+ "--assistant-id <id>",
785
+ "Assistant ID for voice code redemption",
786
+ )
787
+ .addHelpText(
788
+ "after",
789
+ `
894
790
  Two redemption modes:
895
791
 
896
792
  1. Token-based redemption: Provide --token, --source-channel, and at
@@ -905,24 +801,21 @@ Examples:
905
801
  $ assistant contacts invites redeem --token xyz-789 --source-channel telegram --external-user-id 12345
906
802
  $ assistant contacts invites redeem --code 123456 --caller-external-user-id "+15551234567"
907
803
  $ assistant contacts invites redeem --code 654321 --caller-external-user-id "+15559876543" --assistant-id asst-abc --json`,
908
- )
909
- .action(
910
- async (
911
- opts: {
912
- token?: string;
913
- sourceChannel?: string;
914
- externalUserId?: string;
915
- externalChatId?: string;
916
- code?: string;
917
- callerExternalUserId?: string;
918
- assistantId?: string;
919
- },
920
- cmd: Command,
921
- ) => {
922
- try {
923
- getDb();
924
- if (opts.code) {
925
- if (!opts.callerExternalUserId) {
804
+ )
805
+ .action(
806
+ async (
807
+ opts: {
808
+ token?: string;
809
+ sourceChannel?: string;
810
+ externalUserId?: string;
811
+ externalChatId?: string;
812
+ code?: string;
813
+ callerExternalUserId?: string;
814
+ assistantId?: string;
815
+ },
816
+ cmd: Command,
817
+ ) => {
818
+ if (opts.code && !opts.callerExternalUserId) {
926
819
  writeError(
927
820
  cmd,
928
821
  "--caller-external-user-id is required for voice code redemption",
@@ -930,61 +823,47 @@ Examples:
930
823
  process.exitCode = 1;
931
824
  return;
932
825
  }
933
- const result = redeemVoiceInviteCode({
934
- code: opts.code,
935
- callerExternalUserId: opts.callerExternalUserId,
936
- sourceChannel: "phone",
937
- ...(opts.assistantId ? { assistantId: opts.assistantId } : {}),
938
- });
939
- if (result.ok) {
940
- if (shouldOutputJson(cmd)) {
941
- writeOutput(cmd, {
942
- ok: true,
943
- type: result.type,
944
- memberId: result.memberId,
945
- ...(result.type === "redeemed"
946
- ? { inviteId: result.inviteId }
947
- : {}),
948
- });
949
- } else {
950
- process.stdout.write(
951
- `Redeemed (${result.type}), member: ${result.memberId}\n`,
952
- );
953
- }
954
- } else {
955
- writeError(cmd, result.reason);
956
- process.exitCode = 1;
957
- }
958
- } else {
959
- const result = redeemIngressInvite({
960
- token: opts.token,
961
- sourceChannel: opts.sourceChannel,
962
- ...(opts.externalUserId
963
- ? { externalUserId: opts.externalUserId }
964
- : {}),
965
- ...(opts.externalChatId
966
- ? { externalChatId: opts.externalChatId }
967
- : {}),
826
+
827
+ const r = await cliIpcCall<{
828
+ ok: boolean;
829
+ // Token path
830
+ invite?: unknown;
831
+ // Voice path
832
+ type?: string;
833
+ memberId?: string;
834
+ inviteId?: string;
835
+ }>("invites_redeem", {
836
+ body: {
837
+ token: opts.token,
838
+ sourceChannel: opts.sourceChannel,
839
+ externalUserId: opts.externalUserId,
840
+ externalChatId: opts.externalChatId,
841
+ code: opts.code,
842
+ callerExternalUserId: opts.callerExternalUserId,
843
+ assistantId: opts.assistantId,
844
+ },
968
845
  });
969
- if (!result.ok) {
970
- writeError(
846
+
847
+ if (!r.ok)
848
+ return exitFromIpcResult(
849
+ r as { ok: false; error?: string; statusCode?: number },
971
850
  cmd,
972
- (result as { error?: string }).error ?? "Failed",
973
851
  );
974
- process.exitCode = 1;
975
- return;
976
- }
852
+
853
+ const result = r.result!;
977
854
  if (shouldOutputJson(cmd)) {
978
- writeOutput(cmd, { ok: true, invite: result.data });
855
+ writeOutput(cmd, result);
856
+ } else if (result.type) {
857
+ // Voice code path
858
+ process.stdout.write(
859
+ `Redeemed (${result.type}), member: ${result.memberId}\n`,
860
+ );
979
861
  } else {
862
+ // Token path
980
863
  process.stdout.write("Invite redeemed.\n");
981
864
  }
982
- }
983
- } catch (err) {
984
- const message = err instanceof Error ? err.message : String(err);
985
- writeError(cmd, message);
986
- process.exitCode = 1;
987
- }
988
- },
989
- );
865
+ },
866
+ );
867
+ },
868
+ });
990
869
  }