@vellumai/assistant 0.11.6 → 0.11.7-staging.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 (478) hide show
  1. package/ARCHITECTURE.md +31 -19
  2. package/Dockerfile +1 -0
  3. package/docs/architecture/security.md +3 -3
  4. package/docs/flux-turn-detection-spike.md +8 -7
  5. package/docs/runbook-trusted-contacts.md +14 -0
  6. package/docs/stt-provider-onboarding.md +8 -4
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/avatar-manifest/package.json +18 -0
  9. package/node_modules/@vellumai/avatar-manifest/src/__tests__/manifest.test.ts +173 -0
  10. package/node_modules/@vellumai/avatar-manifest/src/__tests__/read.test.ts +114 -0
  11. package/node_modules/@vellumai/avatar-manifest/src/index.ts +29 -0
  12. package/node_modules/@vellumai/avatar-manifest/src/layout.ts +18 -0
  13. package/node_modules/@vellumai/avatar-manifest/src/manifest.ts +156 -0
  14. package/node_modules/@vellumai/avatar-manifest/src/read.ts +109 -0
  15. package/node_modules/@vellumai/avatar-manifest/tsconfig.json +20 -0
  16. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  17. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  18. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  19. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  20. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  21. package/node_modules/@vellumai/ces-client/src/http-credentials.ts +161 -0
  22. package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
  23. package/node_modules/@vellumai/environments/package.json +2 -1
  24. package/node_modules/@vellumai/environments/src/shell.test.ts +56 -0
  25. package/node_modules/@vellumai/environments/src/shell.ts +65 -0
  26. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  27. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  28. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  29. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  30. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  31. package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +32 -0
  32. package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +1 -0
  33. package/node_modules/@vellumai/gateway-client/src/__tests__/inbound-event-kind.test.ts +82 -0
  34. package/node_modules/@vellumai/gateway-client/src/__tests__/plugin-admission-denied-contract.test.ts +56 -0
  35. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +18 -0
  36. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +5 -11
  37. package/node_modules/@vellumai/gateway-client/src/channel-permission-contract.ts +3 -1
  38. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +9 -0
  39. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +4 -0
  40. package/node_modules/@vellumai/gateway-client/src/inbound-event-kind.ts +75 -0
  41. package/node_modules/@vellumai/gateway-client/src/index.ts +17 -0
  42. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +8 -0
  43. package/node_modules/@vellumai/gateway-client/src/plugin-admission-denied-contract.ts +47 -0
  44. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +11 -0
  45. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +37 -0
  46. package/node_modules/@vellumai/service-contracts/src/__tests__/remote-web-pairing.test.ts +389 -0
  47. package/node_modules/@vellumai/service-contracts/src/ingress.ts +22 -0
  48. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +508 -18
  49. package/node_modules/@vellumai/service-contracts/src/rpc.ts +174 -0
  50. package/openapi.yaml +419 -55
  51. package/package.json +4 -1
  52. package/scripts/sync-llm-catalog.ts +6 -0
  53. package/src/__tests__/approval-card-edit-inbound-handoff.test.ts +199 -0
  54. package/src/__tests__/approval-card-edit.test.ts +153 -0
  55. package/src/__tests__/attachments-store-heic-normalize.test.ts +1 -1
  56. package/src/__tests__/available-skills.test.ts +54 -0
  57. package/src/__tests__/avatar-identity-sync.test.ts +5 -1
  58. package/src/__tests__/catalog-install-normalize.test.ts +9 -1
  59. package/src/__tests__/channel-policy.test.ts +1 -3
  60. package/src/__tests__/channel-readiness-discord.test.ts +9 -70
  61. package/src/__tests__/compactor-call-site-logging.test.ts +61 -0
  62. package/src/__tests__/config-loader-backfill.test.ts +69 -0
  63. package/src/__tests__/config-schema.test.ts +2 -3
  64. package/src/__tests__/conversation-agent-loop.test.ts +238 -0
  65. package/src/__tests__/conversation-attachments.test.ts +0 -1
  66. package/src/__tests__/conversation-error.test.ts +44 -0
  67. package/src/__tests__/conversation-evictor.test.ts +19 -0
  68. package/src/__tests__/conversation-fork-referential.test.ts +73 -63
  69. package/src/__tests__/conversation-fork-retrospective.test.ts +99 -74
  70. package/src/__tests__/conversation-runtime-assembly.test.ts +23 -0
  71. package/src/__tests__/conversation-slash.test.ts +9 -0
  72. package/src/__tests__/conversation-title-service.test.ts +97 -0
  73. package/src/__tests__/conversation-tool-setup-attribution.test.ts +16 -0
  74. package/src/__tests__/credential-broker-server-use.test.ts +0 -218
  75. package/src/__tests__/credential-broker.test.ts +43 -420
  76. package/src/__tests__/credential-record-write-through.test.ts +78 -0
  77. package/src/__tests__/credential-routes.test.ts +17 -1
  78. package/src/__tests__/credential-security-invariants.test.ts +8 -9
  79. package/src/__tests__/default-profile-catalog-fallback.test.ts +289 -0
  80. package/src/__tests__/delete-propagation.test.ts +92 -2
  81. package/src/__tests__/discord-callback-round-trip.test.ts +93 -0
  82. package/src/__tests__/discord-channel-config.test.ts +237 -0
  83. package/src/__tests__/edit-propagation.test.ts +42 -2
  84. package/src/__tests__/evict-conversations-for-reload.test.ts +51 -1
  85. package/src/__tests__/fallback-breaker.test.ts +1335 -0
  86. package/src/__tests__/gateway-threshold-reader-mock.ts +6 -0
  87. package/src/__tests__/guardian-card-withdrawal.test.ts +30 -0
  88. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -2
  89. package/src/__tests__/image-conversion.test.ts +38 -4
  90. package/src/__tests__/install-skill-routing.test.ts +25 -0
  91. package/src/__tests__/llm-catalog-parity.test.ts +4 -0
  92. package/src/__tests__/llm-resolver.test.ts +74 -0
  93. package/src/__tests__/llm-schema-fallback-profile.test.ts +359 -0
  94. package/src/__tests__/managed-fallback-dispatch.test.ts +430 -0
  95. package/src/__tests__/managed-profile-guard.test.ts +28 -0
  96. package/src/__tests__/managed-speech-defaults.test.ts +196 -1
  97. package/src/__tests__/mcp-cli.test.ts +23 -1
  98. package/src/__tests__/mcp-tool-annotations-risk.test.ts +43 -34
  99. package/src/__tests__/media-stream-stt-session.test.ts +2 -0
  100. package/src/__tests__/notification-decision-fallback.test.ts +106 -0
  101. package/src/__tests__/notification-discord-adapter.test.ts +162 -0
  102. package/src/__tests__/oauth-connect-orchestrator.test.ts +95 -0
  103. package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -8
  104. package/src/__tests__/persist-unsendable-image.test.ts +3 -3
  105. package/src/__tests__/platform.test.ts +19 -1
  106. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
  107. package/src/__tests__/provider-catalog-visibility.test.ts +17 -0
  108. package/src/__tests__/provider-platform-proxy-integration.test.ts +8 -1
  109. package/src/__tests__/provider-usage-tracking.test.ts +56 -0
  110. package/src/__tests__/require-fresh-approval.test.ts +5 -2
  111. package/src/__tests__/retry-fallback-escalation.test.ts +1093 -0
  112. package/src/__tests__/schedule-retry.test.ts +183 -4
  113. package/src/__tests__/scheduler-reuse-conversation.test.ts +6 -6
  114. package/src/__tests__/secret-routes-platform-proxy.test.ts +55 -0
  115. package/src/__tests__/skill-load-tool.test.ts +34 -0
  116. package/src/__tests__/skill-tool-factory.test.ts +6 -1
  117. package/src/__tests__/skill-tool-manifest.test.ts +20 -0
  118. package/src/__tests__/skills.test.ts +25 -0
  119. package/src/__tests__/subagent-manager-notify.test.ts +38 -0
  120. package/src/__tests__/terminal-tools.test.ts +2 -0
  121. package/src/__tests__/tool-approval-handler.test.ts +146 -2
  122. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +108 -2
  123. package/src/__tests__/tool-audit.test.ts +111 -40
  124. package/src/__tests__/tool-executor-lifecycle-events.test.ts +228 -18
  125. package/src/__tests__/ui-shape-teaching.test.ts +1 -1
  126. package/src/__tests__/verification-control-plane-policy.test.ts +6 -2
  127. package/src/__tests__/voice-config-update.test.ts +43 -0
  128. package/src/__tests__/workspace-migration-147-rename-colliding-backup-profile-names.test.ts +480 -0
  129. package/src/__tests__/workspace-migration-148-strip-unsupported-fallback-profiles.test.ts +167 -0
  130. package/src/__tests__/workspace-migration-149-repoint-backup-profile-selections.test.ts +144 -0
  131. package/src/agent/loop.ts +31 -2
  132. package/src/approvals/guardian-card-withdrawal.ts +22 -0
  133. package/src/avatar/__tests__/ensure-raster.test.ts +291 -0
  134. package/src/avatar/avatar-manifest.ts +48 -100
  135. package/src/avatar/avatar-store.ts +7 -7
  136. package/src/avatar/ensure-raster.ts +146 -0
  137. package/src/avatar/resvg-lazy.test.ts +0 -1
  138. package/src/avatar/traits-png-sync.ts +9 -10
  139. package/src/background-wake/wake-intent-hooks.test.ts +0 -1
  140. package/src/backup/__tests__/paths.test.ts +6 -2
  141. package/src/backup/paths.ts +6 -4
  142. package/src/bundler/app-compiler.ts +2 -2
  143. package/src/bundler/compiler-tools.test.ts +36 -0
  144. package/src/bundler/compiler-tools.ts +54 -18
  145. package/src/calls/__tests__/telephony-synthesis-language.test.ts +81 -0
  146. package/src/calls/__tests__/voice-session-bridge.test.ts +57 -0
  147. package/src/calls/media-stream-stt-session.ts +2 -1
  148. package/src/calls/telephony-synthesis-language.ts +13 -5
  149. package/src/calls/voice-session-bridge.ts +19 -4
  150. package/src/channels/config.ts +23 -12
  151. package/src/cli/AGENTS.md +3 -1
  152. package/src/cli/commands/backup.help.ts +10 -13
  153. package/src/cli/commands/contacts.help.ts +16 -4
  154. package/src/cli/commands/contacts.ts +5 -1
  155. package/src/cli/commands/credentials.help.ts +1 -1
  156. package/src/cli/commands/inference-providers.ts +18 -53
  157. package/src/cli/commands/mcp.help.ts +6 -5
  158. package/src/cli/commands/mcp.ts +1 -1
  159. package/src/cli/commands/memory/memory-retrospective.ts +1 -0
  160. package/src/cli/commands/stt.help.ts +2 -2
  161. package/src/config/__tests__/backup-schema.test.ts +1 -1
  162. package/src/config/__tests__/default-profile-catalog.test.ts +83 -2
  163. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +1 -1
  164. package/src/config/__tests__/memory-retrospective-schema.test.ts +12 -15
  165. package/src/config/bundled-skills/computer-use/SKILL.md +6 -6
  166. package/src/config/bundled-skills/computer-use/TOOLS.json +9 -6
  167. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +3 -1
  168. package/src/config/bundled-skills/media-processing/services/preprocess.ts +1 -1
  169. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  170. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +16 -15
  171. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +2 -1
  172. package/src/config/bundled-skills/settings/TOOLS.json +11 -5
  173. package/src/config/bundled-skills/settings/tools/open-system-settings.test.ts +85 -0
  174. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +33 -8
  175. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +54 -3
  176. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +1 -1
  177. package/src/config/default-profile-catalog.ts +195 -10
  178. package/src/config/default-profile-names.ts +41 -0
  179. package/src/config/feature-flag-registry.json +34 -2
  180. package/src/config/inference-profile-validation.ts +11 -2
  181. package/src/config/llm-resolver.ts +25 -0
  182. package/src/config/loader.ts +3 -0
  183. package/src/config/managed-speech-defaults.ts +160 -10
  184. package/src/config/schema.ts +2 -0
  185. package/src/config/schemas/__tests__/live-voice.test.ts +7 -6
  186. package/src/config/schemas/__tests__/stt.test.ts +94 -0
  187. package/src/config/schemas/backup.ts +1 -1
  188. package/src/config/schemas/channels.ts +32 -0
  189. package/src/config/schemas/live-voice.ts +13 -4
  190. package/src/config/schemas/llm.ts +263 -15
  191. package/src/config/schemas/mcp.ts +10 -2
  192. package/src/config/schemas/memory-retrospective.ts +1 -19
  193. package/src/config/schemas/services.ts +24 -0
  194. package/src/config/schemas/stt.ts +128 -5
  195. package/src/config/seed-inference-profiles.ts +32 -3
  196. package/src/config/skill-state.ts +5 -0
  197. package/src/config/skills.ts +21 -0
  198. package/src/contacts/notify-contacts-changed.ts +5 -2
  199. package/src/context/compactor.ts +74 -1
  200. package/src/daemon/__tests__/conversation-tool-setup.test.ts +138 -1
  201. package/src/daemon/config-watcher.ts +2 -1
  202. package/src/daemon/conversation-agent-loop-handlers.ts +27 -0
  203. package/src/daemon/conversation-agent-loop.ts +86 -10
  204. package/src/daemon/conversation-error.ts +25 -0
  205. package/src/daemon/conversation-evictor.ts +2 -4
  206. package/src/daemon/conversation-runtime-assembly.ts +19 -7
  207. package/src/daemon/conversation-skill-tools.ts +5 -1
  208. package/src/daemon/conversation-slash.ts +2 -2
  209. package/src/daemon/conversation-store.ts +8 -1
  210. package/src/daemon/conversation-tool-setup.ts +37 -0
  211. package/src/daemon/conversation.ts +0 -4
  212. package/src/daemon/handlers/channel-config-result.ts +30 -0
  213. package/src/daemon/handlers/config-discord-channel.ts +301 -0
  214. package/src/daemon/handlers/config-ingress.ts +9 -0
  215. package/src/daemon/handlers/config-slack-channel.ts +13 -15
  216. package/src/daemon/handlers/config-telegram.ts +2 -5
  217. package/src/daemon/handlers/conversations.ts +0 -2
  218. package/src/daemon/handlers/skills.ts +25 -7
  219. package/src/daemon/lifecycle.ts +3 -1
  220. package/src/daemon/message-types/messages.ts +0 -2
  221. package/src/daemon/tool-setup-types.ts +5 -3
  222. package/src/daemon/trust-context-types.test.ts +33 -0
  223. package/src/heartbeat/__tests__/heartbeat-service.test.ts +0 -1
  224. package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +58 -4
  225. package/src/live-voice/__tests__/live-voice-managed-speech-fallback.test.ts +8 -3
  226. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +73 -11
  227. package/src/live-voice/__tests__/live-voice-session-preflight.test.ts +148 -2
  228. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +64 -0
  229. package/src/live-voice/__tests__/live-voice-stt.test.ts +3 -0
  230. package/src/live-voice/__tests__/live-voice-text-turn.test.ts +391 -0
  231. package/src/live-voice/__tests__/protocol.test.ts +224 -0
  232. package/src/live-voice/live-voice-credential-preflight.ts +5 -1
  233. package/src/live-voice/live-voice-session-manager.ts +39 -2
  234. package/src/live-voice/live-voice-session.ts +224 -9
  235. package/src/live-voice/protocol.ts +187 -1
  236. package/src/messaging/providers/discord/api.ts +2 -1
  237. package/src/messaging/providers/discord/withdraw.ts +62 -0
  238. package/src/messaging/read-provider-metadata.ts +32 -0
  239. package/src/monitoring/__tests__/file-descriptors.test.ts +32 -0
  240. package/src/monitoring/__tests__/process-memory.test.ts +34 -1
  241. package/src/monitoring/db-integrity-sample.ts +1 -0
  242. package/src/monitoring/file-descriptors.ts +39 -6
  243. package/src/monitoring/process-memory.ts +37 -5
  244. package/src/monitoring/resource-sampler.ts +25 -8
  245. package/src/notifications/__tests__/activity-failed-dedupe.test.ts +161 -0
  246. package/src/notifications/__tests__/background-failure-signal.test.ts +107 -0
  247. package/src/notifications/__tests__/connected-channels.test.ts +12 -0
  248. package/src/notifications/__tests__/copy-composer.test.ts +83 -0
  249. package/src/notifications/__tests__/destination-resolver.test.ts +38 -0
  250. package/src/notifications/activity-failed-dedupe.ts +95 -0
  251. package/src/notifications/adapters/discord.ts +132 -0
  252. package/src/notifications/adapters/shared.ts +16 -0
  253. package/src/notifications/adapters/slack.ts +6 -1
  254. package/src/notifications/adapters/telegram.ts +5 -8
  255. package/src/notifications/approval-card-data.ts +94 -1
  256. package/src/notifications/background-failure-signal.ts +116 -0
  257. package/src/notifications/broadcaster.ts +3 -9
  258. package/src/notifications/copy-composer.ts +41 -8
  259. package/src/notifications/decision-engine.ts +55 -0
  260. package/src/notifications/destination-resolver.ts +45 -5
  261. package/src/notifications/emit-signal.ts +19 -5
  262. package/src/notifications/guardian-question-mode.ts +57 -0
  263. package/src/notifications/types.ts +2 -8
  264. package/src/oauth/__tests__/seed-providers-managed.test.ts +18 -0
  265. package/src/oauth/connect-orchestrator.ts +16 -0
  266. package/src/oauth/seed-providers.ts +262 -0
  267. package/src/permissions/checker.test.ts +21 -0
  268. package/src/permissions/checker.ts +6 -0
  269. package/src/permissions/gateway-threshold-reader.test.ts +184 -0
  270. package/src/permissions/gateway-threshold-reader.ts +144 -10
  271. package/src/permissions/prompter.ts +0 -6
  272. package/src/permissions/types.ts +5 -4
  273. package/src/persistence/__tests__/bulk-write-gate.test.ts +0 -38
  274. package/src/persistence/bulk-write-gate.ts +9 -10
  275. package/src/persistence/conversation-crud.ts +88 -134
  276. package/src/persistence/conversation-title-service.ts +43 -29
  277. package/src/persistence/embeddings/embedding-local.ts +14 -85
  278. package/src/persistence/embeddings/embedding-runtime-manager.ts +1 -0
  279. package/src/persistence/lifecycle-events-store.test.ts +50 -0
  280. package/src/persistence/lifecycle-events-store.ts +75 -5
  281. package/src/platform/platform-patch-queue.test.ts +368 -0
  282. package/src/platform/platform-patch-queue.ts +190 -0
  283. package/src/platform/sync-avatar.test.ts +527 -0
  284. package/src/platform/sync-avatar.ts +209 -0
  285. package/src/platform/sync-identity.test.ts +75 -0
  286. package/src/platform/sync-identity.ts +17 -110
  287. package/src/plugin-api/model-profiles.test.ts +2 -2
  288. package/src/plugin-api/model-profiles.ts +7 -7
  289. package/src/plugin-api/transcription-session.ts +1 -1
  290. package/src/plugins/defaults/compaction/window-manager.ts +4 -0
  291. package/src/plugins/defaults/image-recovery/recover.ts +2 -2
  292. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +133 -34
  293. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +21 -31
  294. package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +13 -9
  295. package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +31 -4
  296. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +0 -11
  297. package/src/plugins/defaults/memory/memory-retrospective-fork-boundary.ts +27 -13
  298. package/src/plugins/defaults/memory/memory-retrospective-job.ts +183 -113
  299. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +13 -13
  300. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +2 -2
  301. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +1 -1
  302. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +4 -2
  303. package/src/plugins/defaults/memory/substrate/sweep-job.ts +9 -42
  304. package/src/plugins/defaults/memory/v2/rerank-local.ts +1 -0
  305. package/src/plugins/defaults/memory/worker.ts +7 -0
  306. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  307. package/src/providers/__tests__/retry-callsite.test.ts +55 -0
  308. package/src/providers/__tests__/vellum-connection-routing.test.ts +21 -3
  309. package/src/providers/connection-resolution.ts +2 -17
  310. package/src/providers/fallback-breaker.ts +389 -0
  311. package/src/providers/inference/__tests__/adapter-factory-opencode.test.ts +92 -0
  312. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +16 -0
  313. package/src/providers/inference/__tests__/base-url-security.test.ts +12 -0
  314. package/src/providers/inference/adapter-factory.ts +246 -3
  315. package/src/providers/inference/auth.ts +15 -14
  316. package/src/providers/inference/chatgpt-subscription-auth.ts +70 -0
  317. package/src/providers/inference/chatgpt-subscription-credentials.ts +84 -0
  318. package/src/providers/inference/resolve-auth.ts +1 -1
  319. package/src/providers/media-resolve.ts +2 -3
  320. package/src/providers/model-catalog.ts +100 -0
  321. package/src/providers/openai/__tests__/api-error-normalization.test.ts +22 -0
  322. package/src/providers/openai/__tests__/chat-template-flatten.test.ts +198 -0
  323. package/src/providers/openai/api-error-normalization.ts +13 -0
  324. package/src/providers/openai/chat-completions-provider.ts +84 -0
  325. package/src/providers/opencode/client.test.ts +150 -0
  326. package/src/providers/opencode/client.ts +61 -0
  327. package/src/providers/platform-proxy/constants.ts +5 -0
  328. package/src/providers/provider-resolvability.ts +20 -0
  329. package/src/providers/provider-secret-catalog.ts +3 -2
  330. package/src/providers/retry.ts +956 -68
  331. package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +42 -0
  332. package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +136 -0
  333. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +120 -0
  334. package/src/providers/speech-to-text/__tests__/resolve.test.ts +316 -12
  335. package/src/providers/speech-to-text/deepgram-flux-frames.ts +83 -3
  336. package/src/providers/speech-to-text/deepgram-flux-realtime.ts +132 -4
  337. package/src/providers/speech-to-text/provider-catalog.ts +191 -3
  338. package/src/providers/speech-to-text/resolve.ts +132 -24
  339. package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +296 -0
  340. package/src/providers/types.ts +39 -0
  341. package/src/providers/usage-tracking.ts +12 -1
  342. package/src/providers/vellum/client.ts +29 -0
  343. package/src/providers/vellum-model-routing.test.ts +2 -0
  344. package/src/providers/vellum-model-routing.ts +3 -3
  345. package/src/runtime/AGENTS.md +1 -2
  346. package/src/runtime/__tests__/agent-wake.test.ts +105 -3
  347. package/src/runtime/__tests__/background-job-runner.test.ts +89 -3
  348. package/src/runtime/agent-wake.ts +44 -5
  349. package/src/runtime/background-job-runner.ts +68 -50
  350. package/src/runtime/channel-readiness-service.ts +0 -39
  351. package/src/runtime/http-server.ts +12 -4
  352. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +18 -18
  353. package/src/runtime/routes/__tests__/backup-routes.test.ts +9 -5
  354. package/src/runtime/routes/__tests__/chatgpt-subscription-auth-routes.test.ts +372 -0
  355. package/src/runtime/routes/__tests__/contact-routes.test.ts +7 -0
  356. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +96 -0
  357. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +37 -0
  358. package/src/runtime/routes/__tests__/ingress-status-routes.test.ts +2 -1
  359. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +87 -0
  360. package/src/runtime/routes/acp-claude-auth-routes.ts +25 -54
  361. package/src/runtime/routes/approval-routes.ts +0 -12
  362. package/src/runtime/routes/avatar-routes.ts +17 -30
  363. package/src/runtime/routes/backup-routes.ts +2 -2
  364. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +296 -113
  365. package/src/runtime/routes/contact-prompt-routes.ts +65 -6
  366. package/src/runtime/routes/contact-routes.ts +20 -15
  367. package/src/runtime/routes/conversation-query-routes.ts +98 -10
  368. package/src/runtime/routes/conversation-routes.ts +2 -2
  369. package/src/runtime/routes/credential-routes.ts +2 -1
  370. package/src/runtime/routes/guardian-approval-interception.ts +12 -9
  371. package/src/runtime/routes/inbound-message-handler.ts +47 -48
  372. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +18 -13
  373. package/src/runtime/routes/inbound-stages/admission-policy.ts +2 -2
  374. package/src/runtime/routes/inbound-stages/edit-intercept.ts +20 -2
  375. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +9 -8
  376. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -1
  377. package/src/runtime/routes/index.ts +2 -0
  378. package/src/runtime/routes/inference-profile-session-handler.ts +2 -2
  379. package/src/runtime/routes/inference-profiles-routes.ts +12 -7
  380. package/src/runtime/routes/inference-provider-connection-routes.ts +2 -2
  381. package/src/runtime/routes/inference-send-routes.ts +2 -2
  382. package/src/runtime/routes/ingress-status-routes.ts +2 -2
  383. package/src/runtime/routes/integrations/discord.ts +119 -0
  384. package/src/runtime/routes/llm-call-sites-routes.ts +2 -2
  385. package/src/runtime/routes/mcp-auth-routes.ts +12 -6
  386. package/src/runtime/routes/migration-routes.ts +3 -1
  387. package/src/runtime/routes/oauth-pending-flows.ts +136 -0
  388. package/src/runtime/routes/secret-routes.ts +7 -0
  389. package/src/runtime/routes/stt-routes.ts +38 -6
  390. package/src/runtime/routes/wake-conversation-routes.ts +8 -1
  391. package/src/runtime/routes/watch-routes.ts +9 -5
  392. package/src/runtime/sync/resource-sync-events.ts +2 -0
  393. package/src/runtime/trust-verdict-consumer.ts +3 -3
  394. package/src/schedule/__tests__/worker-feature-flags.test.ts +58 -0
  395. package/src/schedule/retry-policy.ts +8 -8
  396. package/src/schedule/run-script.ts +14 -23
  397. package/src/schedule/schedule-recovery.ts +0 -1
  398. package/src/schedule/scheduler.ts +89 -51
  399. package/src/schedule/worker.ts +57 -0
  400. package/src/security/__tests__/openai-device-auth.test.ts +355 -0
  401. package/src/security/ces-rpc-record-backend.ts +123 -0
  402. package/src/security/oauth2.ts +7 -0
  403. package/src/security/openai-device-auth.ts +364 -0
  404. package/src/security/secure-keys.ts +15 -0
  405. package/src/skills/available-skills.ts +10 -1
  406. package/src/skills/catalog-install.ts +19 -1
  407. package/src/skills/inline-command-runner.ts +6 -2
  408. package/src/skills/platform-compatibility.test.ts +49 -0
  409. package/src/skills/platform-compatibility.ts +65 -0
  410. package/src/skills/tool-manifest.ts +20 -0
  411. package/src/stt/__tests__/roles.test.ts +152 -0
  412. package/src/stt/daemon-batch-transcriber.ts +4 -1
  413. package/src/stt/roles.ts +180 -0
  414. package/src/stt/stt-stream-session.ts +3 -2
  415. package/src/stt/types.ts +33 -3
  416. package/src/subagent/manager.ts +12 -0
  417. package/src/telemetry/__tests__/live-voice-funnel.test.ts +34 -0
  418. package/src/telemetry/live-voice-funnel.ts +12 -2
  419. package/src/telemetry/telemetry-wire.generated.ts +6 -0
  420. package/src/telemetry/tool-audit.ts +83 -30
  421. package/src/telemetry/tool-executed-events-store.test.ts +0 -1
  422. package/src/telemetry/turn-outcome.ts +75 -4
  423. package/src/tools/client-os.ts +115 -0
  424. package/src/tools/computer-use/definitions.ts +11 -7
  425. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -2
  426. package/src/tools/credentials/broker-types.ts +0 -71
  427. package/src/tools/credentials/broker.ts +6 -201
  428. package/src/tools/credentials/metadata-store.ts +65 -16
  429. package/src/tools/credentials/store.ts +2 -0
  430. package/src/tools/executor.ts +2 -8
  431. package/src/tools/host-shell.test.ts +75 -0
  432. package/src/tools/host-shell.ts +24 -0
  433. package/src/tools/host-terminal/host-shell.ts +15 -44
  434. package/src/tools/mcp/mcp-tool-factory.ts +44 -9
  435. package/src/tools/permission-checker.ts +73 -21
  436. package/src/tools/policy-context.ts +1 -0
  437. package/src/tools/shared/filesystem/image-read.ts +1 -1
  438. package/src/tools/skills/find-similar-skills.ts +10 -2
  439. package/src/tools/skills/load.ts +41 -6
  440. package/src/tools/skills/sandbox-runner.ts +8 -16
  441. package/src/tools/skills/skill-tool-factory.ts +1 -0
  442. package/src/tools/terminal/__tests__/safe-env.test.ts +64 -1
  443. package/src/tools/terminal/safe-env.ts +39 -9
  444. package/src/tools/terminal/shell.ts +12 -31
  445. package/src/tools/tool-approval-handler.ts +64 -10
  446. package/src/tools/tool-types.ts +10 -0
  447. package/src/tools/types.ts +19 -3
  448. package/src/tools/ui-surface/surface-shape-docs.ts +4 -3
  449. package/src/tools/workflows/manage-workflows.ts +2 -2
  450. package/src/tools/workflows/run-workflow.test.ts +2 -1
  451. package/src/util/__tests__/file-use.test.ts +61 -0
  452. package/src/util/__tests__/process-table.test.ts +66 -0
  453. package/src/util/__tests__/process-tree.test.ts +46 -0
  454. package/src/util/errors.ts +1 -0
  455. package/src/util/file-use.ts +91 -0
  456. package/src/util/host-process.test.ts +17 -0
  457. package/src/util/host-process.ts +75 -0
  458. package/src/util/image-conversion.ts +39 -7
  459. package/src/util/platform.ts +32 -13
  460. package/src/util/process-table.ts +249 -0
  461. package/src/util/process-tree.ts +85 -129
  462. package/src/util/provider-error-patterns.ts +20 -0
  463. package/src/util/spawn.ts +9 -2
  464. package/src/watch/__tests__/watch-retro.test.ts +48 -1
  465. package/src/watch/watch-retro.ts +46 -4
  466. package/src/workspace/git-service.ts +4 -14
  467. package/src/workspace/migrations/147-rename-colliding-backup-profile-names.ts +360 -0
  468. package/src/workspace/migrations/148-strip-unsupported-fallback-profiles.ts +117 -0
  469. package/src/workspace/migrations/149-repoint-backup-profile-selections.ts +204 -0
  470. package/src/workspace/migrations/150-stt-flux-provider-to-model-family.ts +139 -0
  471. package/src/workspace/migrations/__tests__/150-stt-flux-provider-to-model-family.test.ts +160 -0
  472. package/src/workspace/migrations/registry.ts +8 -0
  473. package/src/__tests__/permission-types.test.ts +0 -17
  474. package/src/channels/gateway-discord-admission.ts +0 -32
  475. package/src/persistence/fork-message-copy.ts +0 -239
  476. package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +0 -221
  477. package/src/security/__tests__/oauth2-device-code.test.ts +0 -431
  478. package/src/security/oauth2-device-code.ts +0 -312
@@ -7,10 +7,12 @@
7
7
  *
8
8
  * - `recordToolExecuted` / `recordToolError` / `recordToolDenied` write the
9
9
  * always-on `tool_invocations` audit row (redacting secrets from the
10
- * stored input/result), and — for prompted calls — the consent-gated
11
- * `permission_decided` lifecycle-telemetry row.
12
- * - `recordToolPermissionPrompted` writes the consent-gated
13
- * `permission_prompt` lifecycle-telemetry row.
10
+ * stored input/result).
11
+ * - `recordToolPermissionPrompted` / `recordToolPermissionDecided` write the
12
+ * consent-gated `permission_prompt` and `permission_decided`
13
+ * lifecycle-telemetry rows. Both are called from the one site that owns an
14
+ * interactive prompt (`tools/permission-checker.ts`), so every prompt has
15
+ * exactly one decision and the two series reconcile.
14
16
  * - `logToolFailure` emits the operator-facing failure log.
15
17
  *
16
18
  * The telemetry-only columns (payload sizes + model attribution) are the
@@ -24,8 +26,10 @@
24
26
  * are unaffected — `tool_invocations` is a local always-on audit log.
25
27
  */
26
28
 
27
- import { isAllowDecision, type UserDecision } from "../permissions/types.js";
28
- import { recordLifecycleEvent } from "../persistence/lifecycle-events-store.js";
29
+ import {
30
+ type LifecycleEventAttributes,
31
+ recordLifecycleEvent,
32
+ } from "../persistence/lifecycle-events-store.js";
29
33
  import { getRawShareAnalytics } from "../platform/consent-cache.js";
30
34
  import { redactJsonStringLeaves } from "../security/redact-json.js";
31
35
  import { redactSensitiveFields } from "../security/redaction.js";
@@ -62,8 +66,6 @@ interface ExecutedAuditEntry {
62
66
  durationMs: number;
63
67
  /** Model attribution at invocation time; `null` when unavailable. */
64
68
  attribution: UsageAttributionSnapshot | null;
65
- /** True when this call was interactively approved via a permission prompt. */
66
- wasPrompted: boolean;
67
69
  }
68
70
 
69
71
  interface ErrorAuditEntry {
@@ -90,8 +92,6 @@ interface DeniedAuditEntry {
90
92
  riskLevel: string;
91
93
  matchedTrustRuleId?: string;
92
94
  durationMs: number;
93
- /** True when the denial followed an interactive permission prompt. */
94
- wasPrompted: boolean;
95
95
  }
96
96
 
97
97
  /** Record an audit row for a tool that ran to completion. */
@@ -111,10 +111,6 @@ export function recordToolExecuted(entry: ExecutedAuditEntry): void {
111
111
  durationMs: entry.durationMs,
112
112
  ...telemetryColumns(entry.attribution, rawInput, entry.resultBytes),
113
113
  });
114
-
115
- if (entry.wasPrompted && isAllowDecision(entry.decision as UserDecision)) {
116
- recordToolPermissionDecided(entry.toolName, entry.decision);
117
- }
118
114
  }
119
115
 
120
116
  /** Record an audit row and operator log for a tool that failed. */
@@ -156,32 +152,89 @@ export function recordToolDenied(entry: DeniedAuditEntry): void {
156
152
  // No telemetry columns: the tool never executed, and denied rows are
157
153
  // filtered out of the tool_executed projection anyway.
158
154
  });
155
+ }
159
156
 
160
- if (entry.wasPrompted) {
161
- recordToolPermissionDecided(entry.toolName, "deny");
162
- }
157
+ /**
158
+ * How an interactive permission prompt ended.
159
+ *
160
+ * `allow` / `deny` are answers a human gave. `abandoned` covers every way a
161
+ * prompt stops without one: it timed out, a new user message superseded it,
162
+ * the turn was cancelled, or the prompter was disposed (client disconnect /
163
+ * conversation teardown). The daemon resolves all of those to a deny for the
164
+ * agent loop, so without this bucket they are indistinguishable from a human
165
+ * saying no.
166
+ */
167
+ export type PermissionPromptOutcome = "allow" | "deny" | "abandoned";
168
+
169
+ /**
170
+ * Grouping dimensions recorded on both halves of a permission-prompt pair.
171
+ * The tool and its risk are always known at the prompt site, so they tighten
172
+ * to required; the rest are the lifecycle attributes as declared. Metadata
173
+ * only: never a file path, a command string, or any tool input.
174
+ */
175
+ export interface PermissionPromptTelemetry extends LifecycleEventAttributes {
176
+ toolName: string;
177
+ riskLevel: string;
163
178
  }
164
179
 
165
- /** Record the consent-gated telemetry row for an interactive permission prompt. */
166
- export function recordToolPermissionPrompted(toolName: string): void {
167
- try {
168
- recordLifecycleEvent(`permission_prompt:${toolName}`);
169
- } catch (err) {
170
- log.warn({ err, toolName }, "Failed to record permission prompt telemetry");
171
- }
180
+ /**
181
+ * Server bounds on the lifecycle `event_name` and `tool_name`. A field over
182
+ * its bound fails validation, and a failed event is acked and discarded rather
183
+ * than retried, so both are clamped here. `event_name` has one variable-length
184
+ * part (the tool name, which can be a long `mcp__server__tool` id) and is much
185
+ * the tighter of the two, which is why `tool_name` carries the full-length
186
+ * value consumers join a prompt to its decision on.
187
+ */
188
+ const LIFECYCLE_EVENT_NAME_LIMIT = 64;
189
+ const LIFECYCLE_TOOL_NAME_LIMIT = 255;
190
+
191
+ function permissionEventName(
192
+ prefix: string,
193
+ toolName: string,
194
+ suffix: string,
195
+ ): string {
196
+ const budget = LIFECYCLE_EVENT_NAME_LIMIT - prefix.length - suffix.length;
197
+ return `${prefix}${toolName.slice(0, Math.max(budget, 0))}${suffix}`;
172
198
  }
173
199
 
174
- function recordToolPermissionDecided(toolName: string, decision: string): void {
200
+ function recordPermissionLifecycleEvent(
201
+ eventName: string,
202
+ entry: PermissionPromptTelemetry,
203
+ failureMessage: string,
204
+ ): void {
175
205
  try {
176
- recordLifecycleEvent(`permission_decided:${toolName}:${decision}`);
206
+ recordLifecycleEvent(eventName, {
207
+ ...entry,
208
+ toolName: entry.toolName.slice(0, LIFECYCLE_TOOL_NAME_LIMIT),
209
+ });
177
210
  } catch (err) {
178
- log.warn(
179
- { err, toolName, decision },
180
- "Failed to record permission decision telemetry",
181
- );
211
+ log.warn({ err, eventName, toolName: entry.toolName }, failureMessage);
182
212
  }
183
213
  }
184
214
 
215
+ /** Record the consent-gated telemetry row for an interactive permission prompt. */
216
+ export function recordToolPermissionPrompted(
217
+ entry: PermissionPromptTelemetry,
218
+ ): void {
219
+ recordPermissionLifecycleEvent(
220
+ permissionEventName("permission_prompt:", entry.toolName, ""),
221
+ entry,
222
+ "Failed to record permission prompt telemetry",
223
+ );
224
+ }
225
+
226
+ /** Record the consent-gated telemetry row for how that prompt ended. */
227
+ export function recordToolPermissionDecided(
228
+ entry: PermissionPromptTelemetry,
229
+ outcome: PermissionPromptOutcome,
230
+ ): void {
231
+ recordPermissionLifecycleEvent(
232
+ permissionEventName("permission_decided:", entry.toolName, `:${outcome}`),
233
+ entry,
234
+ "Failed to record permission decision telemetry",
235
+ );
236
+ }
237
+
185
238
  /** Operator-facing failure log: warn for expected failures, error otherwise. */
186
239
  function logToolFailure(entry: ErrorAuditEntry): void {
187
240
  const meta = {
@@ -123,7 +123,6 @@ describe("tool-executed-events-store", () => {
123
123
  riskLevel: "low",
124
124
  durationMs: 5,
125
125
  attribution: null,
126
- wasPrompted: false,
127
126
  });
128
127
 
129
128
  recordExecuted("t-opted-in-before");
@@ -31,6 +31,26 @@ export interface TurnOutcomeExtras {
31
31
  batchedInto?: string;
32
32
  /** For `"failed"`: stable classified error code (never free-form text). */
33
33
  failureCode?: string;
34
+ /**
35
+ * For `"failed"`: the classification's authored user-facing message
36
+ * (`classifyConversationError(...).userMessage`), so downstream failure
37
+ * reporting (background-job alerts) can render the actionable prose the
38
+ * chat banner shows instead of reconstructing degraded text from the code.
39
+ */
40
+ failureMessage?: string;
41
+ /** For `"failed"`: the classification's machine-readable category. */
42
+ failureCategory?: string;
43
+ /**
44
+ * For `"failed"`: name of the `provider_connections` row in play when the
45
+ * failure occurred, when the classifier had it in scope.
46
+ */
47
+ failureConnection?: string;
48
+ /**
49
+ * For `"failed"`: the resolved profile key the failing call ran under,
50
+ * when the classifier had it in scope. This is dispatch's own attribution,
51
+ * so consumers scope failure identity by it instead of re-resolving.
52
+ */
53
+ failureProfile?: string;
34
54
  }
35
55
 
36
56
  /**
@@ -49,10 +69,25 @@ export function stampTurnOutcome(
49
69
  extras: TurnOutcomeExtras = {},
50
70
  ): void {
51
71
  try {
72
+ // The failure* keys are read back by `readTurnFailure` only; the turn
73
+ // telemetry projection (`queryUnreportedTurnEvents`) extracts none of
74
+ // them, so nothing here changes the platform wire contract.
52
75
  updateMessageMetadata(userMessageId, {
53
76
  turnOutcome: outcome,
54
77
  ...(extras.batchedInto ? { turnBatchedInto: extras.batchedInto } : {}),
55
78
  ...(extras.failureCode ? { turnFailureCode: extras.failureCode } : {}),
79
+ ...(extras.failureMessage
80
+ ? { turnFailureMessage: extras.failureMessage }
81
+ : {}),
82
+ ...(extras.failureCategory
83
+ ? { turnFailureCategory: extras.failureCategory }
84
+ : {}),
85
+ ...(extras.failureConnection
86
+ ? { turnFailureConnection: extras.failureConnection }
87
+ : {}),
88
+ ...(extras.failureProfile
89
+ ? { turnFailureProfile: extras.failureProfile }
90
+ : {}),
56
91
  });
57
92
  } catch (err) {
58
93
  log.warn(
@@ -75,6 +110,14 @@ export function stampTurnOutcome(
75
110
  export interface TurnFailure {
76
111
  /** Stable classified error code (never free-form text). */
77
112
  failureCode?: string;
113
+ /** The classification's authored user-facing message, when stamped. */
114
+ userMessage?: string;
115
+ /** The classification's machine-readable category, when stamped. */
116
+ errorCategory?: string;
117
+ /** Connection row in play when the failure occurred, when stamped. */
118
+ connectionName?: string;
119
+ /** Resolved profile key the failing call ran under, when stamped. */
120
+ profileName?: string;
78
121
  }
79
122
 
80
123
  /**
@@ -106,11 +149,39 @@ export function readTurnFailure(userMessageId: string): TurnFailure | null {
106
149
  if (typeof parsed !== "object" || parsed === null) {
107
150
  return null;
108
151
  }
109
- const meta = parsed as { turnOutcome?: unknown; turnFailureCode?: unknown };
152
+ const meta = parsed as {
153
+ turnOutcome?: unknown;
154
+ turnFailureCode?: unknown;
155
+ turnFailureMessage?: unknown;
156
+ turnFailureCategory?: unknown;
157
+ turnFailureConnection?: unknown;
158
+ turnFailureProfile?: unknown;
159
+ };
110
160
  if (meta.turnOutcome !== "failed") {
111
161
  return null;
112
162
  }
113
- return typeof meta.turnFailureCode === "string"
114
- ? { failureCode: meta.turnFailureCode }
115
- : {};
163
+ const str = (value: unknown): string | undefined =>
164
+ typeof value === "string" ? value : undefined;
165
+ const failure: TurnFailure = {};
166
+ const failureCode = str(meta.turnFailureCode);
167
+ if (failureCode !== undefined) {
168
+ failure.failureCode = failureCode;
169
+ }
170
+ const userMessage = str(meta.turnFailureMessage);
171
+ if (userMessage !== undefined) {
172
+ failure.userMessage = userMessage;
173
+ }
174
+ const errorCategory = str(meta.turnFailureCategory);
175
+ if (errorCategory !== undefined) {
176
+ failure.errorCategory = errorCategory;
177
+ }
178
+ const connectionName = str(meta.turnFailureConnection);
179
+ if (connectionName !== undefined) {
180
+ failure.connectionName = connectionName;
181
+ }
182
+ const profileName = str(meta.turnFailureProfile);
183
+ if (profileName !== undefined) {
184
+ failure.profileName = profileName;
185
+ }
186
+ return failure;
116
187
  }
@@ -0,0 +1,115 @@
1
+ import {
2
+ type ClientOs,
3
+ type HostProxyCapability,
4
+ type InterfaceId,
5
+ parseClientOs,
6
+ supportsHostProxy,
7
+ } from "../channels/types.js";
8
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
9
+
10
+ interface HostClientContext {
11
+ clientOs?: ClientOs;
12
+ transportInterface?: InterfaceId;
13
+ sourceActorPrincipalId?: string;
14
+ }
15
+
16
+ export function supportsClientOs(
17
+ supportedClientOs: readonly ClientOs[] | undefined,
18
+ clientOs: ClientOs | undefined,
19
+ ): boolean {
20
+ return (
21
+ clientOs === undefined ||
22
+ supportedClientOs === undefined ||
23
+ supportedClientOs.includes(clientOs)
24
+ );
25
+ }
26
+
27
+ export function getSkillToolHostCapability(
28
+ toolName: string,
29
+ ): HostProxyCapability | undefined {
30
+ if (toolName.startsWith("computer_use_")) {
31
+ return "host_cu";
32
+ }
33
+ if (toolName.startsWith("app_control_")) {
34
+ return "host_app_control";
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ export function getEligibleHostClientOs(
40
+ capability: HostProxyCapability,
41
+ context: HostClientContext,
42
+ ): Set<ClientOs> {
43
+ const eligible = new Set<ClientOs>();
44
+ const sourceClientOs =
45
+ context.transportInterface === "macos" ||
46
+ context.transportInterface === "windows"
47
+ ? context.transportInterface
48
+ : context.clientOs;
49
+ if (
50
+ sourceClientOs !== undefined &&
51
+ context.transportInterface !== undefined &&
52
+ supportsHostProxy(context.transportInterface, capability)
53
+ ) {
54
+ eligible.add(sourceClientOs);
55
+ }
56
+
57
+ if (context.sourceActorPrincipalId !== undefined) {
58
+ for (const client of assistantEventHub.listClientsByCapability(
59
+ capability,
60
+ )) {
61
+ if (client.actorPrincipalId !== context.sourceActorPrincipalId) {
62
+ continue;
63
+ }
64
+ const clientOs = parseClientOs(client.interfaceId);
65
+ if (clientOs !== null) {
66
+ eligible.add(clientOs);
67
+ }
68
+ }
69
+ }
70
+ return eligible;
71
+ }
72
+
73
+ export function supportsClientOsForSkillTool(
74
+ supportedClientOs: readonly ClientOs[] | undefined,
75
+ toolName: string,
76
+ context: HostClientContext,
77
+ ): boolean {
78
+ if (supportedClientOs === undefined) {
79
+ return true;
80
+ }
81
+ const capability = getSkillToolHostCapability(toolName);
82
+ if (capability === undefined) {
83
+ return supportsClientOs(supportedClientOs, context.clientOs);
84
+ }
85
+ const eligible = getEligibleHostClientOs(capability, context);
86
+ if (eligible.size === 0) {
87
+ return supportsClientOs(supportedClientOs, context.clientOs);
88
+ }
89
+ for (const clientOs of eligible) {
90
+ if (supportedClientOs.includes(clientOs)) {
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ }
96
+
97
+ export function resolveInvocationHostClientOs(
98
+ capability: HostProxyCapability,
99
+ input: Record<string, unknown>,
100
+ context: HostClientContext,
101
+ ): ClientOs | undefined {
102
+ const targetClientId =
103
+ typeof input.target_client_id === "string" && input.target_client_id !== ""
104
+ ? input.target_client_id
105
+ : undefined;
106
+ if (targetClientId !== undefined) {
107
+ const client = assistantEventHub.getClientById(targetClientId);
108
+ return client?.capabilities.includes(capability)
109
+ ? (parseClientOs(client.interfaceId) ?? undefined)
110
+ : undefined;
111
+ }
112
+
113
+ const eligible = getEligibleHostClientOs(capability, context);
114
+ return eligible.size === 1 ? eligible.values().next().value : undefined;
115
+ }
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Computer-use tool definitions.
3
3
  *
4
- * These tools mirror the macOS client's ToolDefinitions.swift schemas, prefixed
4
+ * These tools mirror the desktop client's computer-use schemas, prefixed
5
5
  * with `computer_use_` to avoid collisions with existing daemon tools. They are all
6
- * proxy tools - execution is forwarded to a connected macOS client and never
6
+ * proxy tools. Execution is forwarded to a connected desktop client and never
7
7
  * handled locally by the daemon.
8
8
  */
9
9
 
@@ -19,7 +19,7 @@ import type {
19
19
  // ---------------------------------------------------------------------------
20
20
 
21
21
  /**
22
- * Forward execution to the connected macOS client via the request-bound
22
+ * Forward execution to the connected desktop client via the request-bound
23
23
  * `proxyToolResolver`. Returns a structured error when no resolver is
24
24
  * configured (e.g. no client connected) so callers see a normal tool
25
25
  * failure rather than an unhandled throw.
@@ -31,7 +31,7 @@ function proxyExecute(toolName: string) {
31
31
  ): Promise<ToolExecutionResult> => {
32
32
  if (!context.proxyToolResolver) {
33
33
  return {
34
- content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires an external resolver (e.g. a connected macOS client for computer-use tools).`,
34
+ content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires a connected desktop client.`,
35
35
  isError: true,
36
36
  };
37
37
  }
@@ -131,7 +131,7 @@ export const computerUseTypeTextTool = {
131
131
  export const computerUseKeyTool = {
132
132
  name: "computer_use_key",
133
133
  description:
134
- "Press a key or keyboard shortcut. Supported: enter, tab, escape, backspace, delete, up, down, left, right, space, cmd+a, cmd+c, cmd+v, cmd+z, cmd+tab, cmd+w, shift+tab, option+tab",
134
+ "Press a key or keyboard shortcut. Supported: enter, tab, escape, backspace, delete, up, down, left, right, space, cmd+a, cmd+c, cmd+v, cmd+z, cmd+tab, cmd+w, shift+tab, option+tab. On Windows use ctrl/alt in place of cmd/option.",
135
135
  category: "computer-use",
136
136
  defaultRiskLevel: RiskLevel.Low,
137
137
  executionTarget: "host",
@@ -141,7 +141,8 @@ export const computerUseKeyTool = {
141
141
  properties: {
142
142
  key: {
143
143
  type: "string",
144
- description: "Key or shortcut to press (e.g. enter, tab, cmd+c, cmd+v)",
144
+ description:
145
+ "Key or shortcut to press (e.g. enter, tab, ctrl+c, cmd+c)",
145
146
  },
146
147
  reasoning: {
147
148
  type: "string",
@@ -223,6 +224,7 @@ export const computerUseDragTool = {
223
224
  category: "computer-use",
224
225
  defaultRiskLevel: RiskLevel.Low,
225
226
  executionTarget: "host",
227
+ supportedClientOs: ["macos", "windows"],
226
228
 
227
229
  input_schema: {
228
230
  type: "object",
@@ -311,10 +313,11 @@ export const computerUseWaitTool = {
311
313
  export const computerUseOpenAppTool = {
312
314
  name: "computer_use_open_app",
313
315
  description:
314
- "Open or switch to a macOS application by name. Preferred over cmd+tab for switching apps - more reliable and explicit.",
316
+ "Open or switch to a desktop application by name. Preferred over cmd+tab / alt+tab for switching apps - more reliable and explicit.",
315
317
  category: "computer-use",
316
318
  defaultRiskLevel: RiskLevel.Low,
317
319
  executionTarget: "host",
320
+ supportedClientOs: ["macos", "windows"],
318
321
 
319
322
  input_schema: {
320
323
  type: "object",
@@ -352,6 +355,7 @@ export const computerUseRunAppleScriptTool = {
352
355
  category: "computer-use",
353
356
  defaultRiskLevel: RiskLevel.Low,
354
357
  executionTarget: "host",
358
+ supportedClientOs: ["macos"],
355
359
 
356
360
  input_schema: {
357
361
  type: "object",
@@ -2,7 +2,7 @@
2
2
  * Shared helper for computer-use skill wrapper scripts.
3
3
  *
4
4
  * Each wrapper calls forwardComputerUseProxyTool() to delegate execution to
5
- * the proxy resolver, which forwards the call to the connected macOS client.
5
+ * the proxy resolver, which forwards the call to the connected desktop client.
6
6
  */
7
7
 
8
8
  import type { ToolContext, ToolExecutionResult } from "../types.js";
@@ -20,7 +20,7 @@ export function forwardComputerUseProxyTool(
20
20
  ): Promise<ToolExecutionResult> {
21
21
  if (!context.proxyToolResolver) {
22
22
  return Promise.resolve({
23
- content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected macOS client.`,
23
+ content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected desktop client.`,
24
24
  isError: true,
25
25
  });
26
26
  }
@@ -1,51 +1,3 @@
1
- /** Opaque token representing a policy-checked authorization to use a credential. */
2
- import type { CredentialInjectionTemplate } from "./policy-types.js";
3
- export interface UsageToken {
4
- tokenId: string;
5
- credentialId: string;
6
- service: string;
7
- field: string;
8
- toolName: string;
9
- /** Timestamp (epoch ms) when this token was created. */
10
- createdAt: number;
11
- /** Whether this token has been consumed (single-use). */
12
- consumed: boolean;
13
- }
14
-
15
- /** Request to authorize the use of a credential. */
16
- export interface AuthorizeRequest {
17
- service: string;
18
- field: string;
19
- toolName: string;
20
- /** Optional domain for domain-policy checking (used by browser tools). */
21
- domain?: string;
22
- }
23
-
24
- /** Successful authorization result. */
25
- export interface AuthorizeSuccess {
26
- authorized: true;
27
- token: UsageToken;
28
- }
29
-
30
- /** Denied authorization result. */
31
- export interface AuthorizeDenied {
32
- authorized: false;
33
- reason: string;
34
- }
35
-
36
- export type AuthorizeResult = AuthorizeSuccess | AuthorizeDenied;
37
-
38
- /** Result of consuming a token. */
39
- export interface ConsumeResult {
40
- success: boolean;
41
- /** The storage key to read the secret from (only present on success). */
42
- storageKey?: string;
43
- /** The resolved value when a transient (one-time) credential was consumed. */
44
- value?: string;
45
- /** Error reason if consumption failed. */
46
- reason?: string;
47
- }
48
-
49
1
  /** Request for the broker to fill a browser field without exposing plaintext. */
50
2
  export interface BrowserFillRequest {
51
3
  service: string;
@@ -83,26 +35,3 @@ export interface ServerUseResult<T> {
83
35
  result?: T;
84
36
  reason?: string;
85
37
  }
86
-
87
- /** Request to look up a credential by ID for proxy injection (no secret exposed). */
88
- export interface ServerUseByIdRequest {
89
- credentialId: string;
90
- requestingTool: string;
91
- }
92
-
93
- /** Successful by-id lookup result - metadata + injection templates, never plaintext. */
94
- export interface ServerUseByIdSuccess {
95
- success: true;
96
- credentialId: string;
97
- service: string;
98
- field: string;
99
- injectionTemplates: CredentialInjectionTemplate[];
100
- }
101
-
102
- /** Denied or not-found by-id lookup result. */
103
- export interface ServerUseByIdDenied {
104
- success: false;
105
- reason: string;
106
- }
107
-
108
- export type ServerUseByIdResult = ServerUseByIdSuccess | ServerUseByIdDenied;