@vellumai/assistant 0.4.41 → 0.4.43

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 (843) hide show
  1. package/.env.example +1 -6
  2. package/.prettierignore +3 -0
  3. package/ARCHITECTURE.md +131 -393
  4. package/Dockerfile +0 -1
  5. package/README.md +73 -83
  6. package/bun.lock +8 -2
  7. package/docs/architecture/integrations.md +16 -21
  8. package/docs/architecture/memory.md +1 -1
  9. package/docs/architecture/scheduling.md +63 -63
  10. package/docs/architecture/security.md +3 -3
  11. package/docs/runbook-trusted-contacts.md +11 -12
  12. package/docs/trusted-contact-access.md +39 -39
  13. package/package.json +5 -8
  14. package/src/__tests__/access-request-decision.test.ts +4 -4
  15. package/src/__tests__/active-skill-tools.test.ts +49 -34
  16. package/src/__tests__/actor-token-service.test.ts +55 -85
  17. package/src/__tests__/amazon-cdp-integration.test.ts +14 -26
  18. package/src/__tests__/app-bundler.test.ts +14 -368
  19. package/src/__tests__/app-compiler.test.ts +0 -1
  20. package/src/__tests__/app-executors.test.ts +10 -1
  21. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
  22. package/src/__tests__/approval-primitive.test.ts +2 -4
  23. package/src/__tests__/approval-routes-http.test.ts +1 -1
  24. package/src/__tests__/asset-materialize-tool.test.ts +1 -4
  25. package/src/__tests__/asset-search-tool.test.ts +1 -4
  26. package/src/__tests__/assistant-attachments.test.ts +23 -0
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +4 -8
  28. package/src/__tests__/assistant-id-boundary-guard.test.ts +5 -5
  29. package/src/__tests__/attachments-store.test.ts +1 -4
  30. package/src/__tests__/avatar-e2e.test.ts +43 -23
  31. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  32. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -9
  33. package/src/__tests__/call-controller.test.ts +4 -8
  34. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  35. package/src/__tests__/call-domain.test.ts +250 -8
  36. package/src/__tests__/call-pointer-message-composer.test.ts +14 -14
  37. package/src/__tests__/call-pointer-messages.test.ts +7 -11
  38. package/src/__tests__/call-recovery.test.ts +47 -0
  39. package/src/__tests__/call-routes-http.test.ts +13 -0
  40. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  41. package/src/__tests__/callback-handoff-copy.test.ts +5 -5
  42. package/src/__tests__/canonical-guardian-store.test.ts +3 -3
  43. package/src/__tests__/channel-approval-routes.test.ts +101 -134
  44. package/src/__tests__/channel-approval.test.ts +0 -201
  45. package/src/__tests__/channel-approvals.test.ts +2 -2
  46. package/src/__tests__/channel-delivery-store.test.ts +16 -24
  47. package/src/__tests__/channel-guardian.test.ts +641 -740
  48. package/src/__tests__/channel-invite-transport.test.ts +1 -2
  49. package/src/__tests__/channel-policy.test.ts +9 -12
  50. package/src/__tests__/channel-readiness-service.test.ts +156 -45
  51. package/src/__tests__/channel-reply-delivery.test.ts +3 -3
  52. package/src/__tests__/channel-retry-sweep.test.ts +7 -7
  53. package/src/__tests__/checker.test.ts +10 -7
  54. package/src/__tests__/chrome-cdp.test.ts +57 -17
  55. package/src/__tests__/cli-help-reference-sync.test.ts +26 -0
  56. package/src/__tests__/compaction.benchmark.test.ts +25 -5
  57. package/src/__tests__/computer-use-session-lifecycle.test.ts +1 -1
  58. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  59. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
  60. package/src/__tests__/config-loader-backfill.test.ts +310 -0
  61. package/src/__tests__/config-watcher.test.ts +1 -5
  62. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +3 -5
  63. package/src/__tests__/connection-policy.test.ts +3 -62
  64. package/src/__tests__/contacts-tools.test.ts +0 -2
  65. package/src/__tests__/context-memory-e2e.test.ts +11 -7
  66. package/src/__tests__/context-overflow-policy.test.ts +2 -2
  67. package/src/__tests__/context-window-manager.test.ts +220 -61
  68. package/src/__tests__/conversation-attention-store.test.ts +178 -2
  69. package/src/__tests__/conversation-attention-telegram.test.ts +8 -11
  70. package/src/__tests__/conversation-pairing.test.ts +14 -14
  71. package/src/__tests__/conversation-routes-guardian-reply.test.ts +1 -1
  72. package/src/__tests__/conversation-store.test.ts +2 -2
  73. package/src/__tests__/conversation-unread-route.test.ts +155 -0
  74. package/src/__tests__/credential-metadata-store.test.ts +0 -2
  75. package/src/__tests__/credential-security-invariants.test.ts +9 -16
  76. package/src/__tests__/credentials-cli.test.ts +49 -5
  77. package/src/__tests__/daemon-assistant-events.test.ts +4 -22
  78. package/src/__tests__/db-migration-rollback.test.ts +2 -2
  79. package/src/__tests__/deterministic-verification-control-plane.test.ts +19 -19
  80. package/src/__tests__/dictation-mode-detection.test.ts +1 -1
  81. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  82. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -6
  83. package/src/__tests__/email-cli.test.ts +12 -12
  84. package/src/__tests__/email-service-config-fallback.test.ts +1 -1
  85. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -18
  86. package/src/__tests__/event-bus.test.ts +0 -1
  87. package/src/__tests__/followup-tools.test.ts +0 -2
  88. package/src/__tests__/gateway-client-managed-outbound.test.ts +6 -6
  89. package/src/__tests__/gateway-only-enforcement.test.ts +13 -77
  90. package/src/__tests__/gateway-only-guard.test.ts +5 -0
  91. package/src/__tests__/guardian-action-conversation-turn.test.ts +3 -3
  92. package/src/__tests__/guardian-action-followup-executor.test.ts +29 -94
  93. package/src/__tests__/guardian-action-followup-store.test.ts +2 -12
  94. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +48 -194
  95. package/src/__tests__/guardian-action-late-reply.test.ts +12 -12
  96. package/src/__tests__/guardian-action-store.test.ts +2 -2
  97. package/src/__tests__/guardian-action-sweep.test.ts +5 -5
  98. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -3
  99. package/src/__tests__/guardian-dispatch.test.ts +5 -46
  100. package/src/__tests__/guardian-grant-minting.test.ts +5 -44
  101. package/src/__tests__/guardian-outbound-http.test.ts +95 -114
  102. package/src/__tests__/guardian-question-mode.test.ts +1 -4
  103. package/src/__tests__/guardian-routing-invariants.test.ts +5 -13
  104. package/src/__tests__/guardian-routing-state.test.ts +3 -3
  105. package/src/__tests__/guardian-verification-voice-binding.test.ts +64 -7
  106. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  107. package/src/__tests__/handle-user-message-secret-resume.test.ts +3 -5
  108. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +16 -34
  109. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  110. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  111. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  112. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  113. package/src/__tests__/heartbeat-service.test.ts +1 -1
  114. package/src/__tests__/home-base-bootstrap.test.ts +0 -2
  115. package/src/__tests__/host-shell-tool.test.ts +3 -12
  116. package/src/__tests__/inbound-invite-redemption.test.ts +2 -2
  117. package/src/__tests__/ingress-url-consistency.test.ts +0 -64
  118. package/src/__tests__/integration-status.test.ts +8 -8
  119. package/src/__tests__/intent-routing.test.ts +9 -13
  120. package/src/__tests__/invite-redemption-service.test.ts +4 -4
  121. package/src/__tests__/invite-routes-http.test.ts +10 -10
  122. package/src/__tests__/llm-usage-store.test.ts +45 -9
  123. package/src/__tests__/local-gateway-health.test.ts +209 -0
  124. package/src/__tests__/managed-avatar-client.test.ts +23 -12
  125. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -2
  126. package/src/__tests__/managed-store.test.ts +29 -12
  127. package/src/__tests__/managed-twitter-guardrails.test.ts +353 -0
  128. package/src/__tests__/mcp-cli.test.ts +1 -1
  129. package/src/__tests__/mcp-health-check.test.ts +1 -1
  130. package/src/__tests__/media-generate-image.test.ts +1 -1
  131. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -4
  132. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +9 -6
  133. package/src/__tests__/memory-regressions.test.ts +1 -166
  134. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  135. package/src/__tests__/migration-export-http.test.ts +2 -2
  136. package/src/__tests__/migration-transport.test.ts +44 -0
  137. package/src/__tests__/non-member-access-request.test.ts +49 -36
  138. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  139. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  140. package/src/__tests__/notification-decision-strategy.test.ts +4 -4
  141. package/src/__tests__/notification-deep-link.test.ts +3 -3
  142. package/src/__tests__/notification-guardian-path.test.ts +6 -44
  143. package/src/__tests__/notification-routing-intent.test.ts +11 -7
  144. package/src/__tests__/oauth-cli.test.ts +1 -1
  145. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -6
  146. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  147. package/src/__tests__/platform.test.ts +168 -5
  148. package/src/__tests__/playbook-execution.test.ts +0 -2
  149. package/src/__tests__/playbook-tools.test.ts +0 -2
  150. package/src/__tests__/pricing.test.ts +125 -0
  151. package/src/__tests__/provider-error-scenarios.test.ts +9 -3
  152. package/src/__tests__/recording-handler.test.ts +46 -80
  153. package/src/__tests__/recording-state-machine.test.ts +112 -183
  154. package/src/__tests__/registry.test.ts +1 -1
  155. package/src/__tests__/relay-server.test.ts +69 -71
  156. package/src/__tests__/reminder-store.test.ts +3 -3
  157. package/src/__tests__/request-file-tool.test.ts +2 -2
  158. package/src/__tests__/ride-shotgun-handler.test.ts +2 -33
  159. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -3
  160. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +4 -4
  162. package/src/__tests__/schedule-store.test.ts +13 -4
  163. package/src/__tests__/schedule-tools.test.ts +0 -2
  164. package/src/__tests__/scheduler-recurrence.test.ts +3 -4
  165. package/src/__tests__/scoped-approval-grants.test.ts +3 -5
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +6 -8
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +1 -1
  168. package/src/__tests__/secret-response-routing.test.ts +1 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  170. package/src/__tests__/sequence-store.test.ts +0 -2
  171. package/src/__tests__/server-history-render.test.ts +2 -199
  172. package/src/__tests__/session-abort-tool-results.test.ts +9 -3
  173. package/src/__tests__/session-agent-loop.test.ts +107 -3
  174. package/src/__tests__/session-confirmation-signals.test.ts +10 -4
  175. package/src/__tests__/session-conflict-gate.test.ts +9 -3
  176. package/src/__tests__/session-init.benchmark.test.ts +22 -13
  177. package/src/__tests__/session-load-history-repair.test.ts +6 -3
  178. package/src/__tests__/session-pre-run-repair.test.ts +9 -3
  179. package/src/__tests__/session-profile-injection.test.ts +9 -3
  180. package/src/__tests__/session-provider-retry-repair.test.ts +10 -4
  181. package/src/__tests__/session-queue.test.ts +10 -4
  182. package/src/__tests__/session-runtime-assembly.test.ts +28 -18
  183. package/src/__tests__/session-skill-tools.test.ts +2 -3
  184. package/src/__tests__/session-slash-known.test.ts +11 -4
  185. package/src/__tests__/session-slash-queue.test.ts +11 -4
  186. package/src/__tests__/session-slash-unknown.test.ts +12 -4
  187. package/src/__tests__/session-surfaces-deselection.test.ts +2 -2
  188. package/src/__tests__/session-surfaces-task-progress.test.ts +3 -3
  189. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -1
  190. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
  191. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
  192. package/src/__tests__/session-usage.test.ts +180 -0
  193. package/src/__tests__/session-workspace-cache-state.test.ts +8 -2
  194. package/src/__tests__/session-workspace-injection.test.ts +8 -2
  195. package/src/__tests__/session-workspace-tool-tracking.test.ts +8 -2
  196. package/src/__tests__/skill-feature-flags-integration.test.ts +5 -11
  197. package/src/__tests__/skill-feature-flags.test.ts +1 -0
  198. package/src/__tests__/skill-include-graph.test.ts +1 -0
  199. package/src/__tests__/skill-load-feature-flag.test.ts +3 -9
  200. package/src/__tests__/skill-load-tool.test.ts +90 -12
  201. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -15
  202. package/src/__tests__/skills-uninstall.test.ts +131 -0
  203. package/src/__tests__/skills.test.ts +32 -16
  204. package/src/__tests__/slack-block-formatting.test.ts +1 -1
  205. package/src/__tests__/slack-channel-config.test.ts +71 -12
  206. package/src/__tests__/slack-inbound-verification.test.ts +7 -7
  207. package/src/__tests__/slack-share-routes.test.ts +1 -1
  208. package/src/__tests__/slack-skill.test.ts +2 -2
  209. package/src/__tests__/slash-commands-catalog.test.ts +1 -0
  210. package/src/__tests__/slash-commands-resolver.test.ts +1 -0
  211. package/src/__tests__/starter-task-flow.test.ts +1 -1
  212. package/src/__tests__/subagent-manager-notify.test.ts +1 -1
  213. package/src/__tests__/subagent-tools.test.ts +2 -2
  214. package/src/__tests__/system-prompt.test.ts +4 -8
  215. package/src/__tests__/task-compiler.test.ts +0 -2
  216. package/src/__tests__/task-management-tools.test.ts +0 -2
  217. package/src/__tests__/task-runner.test.ts +0 -2
  218. package/src/__tests__/task-scheduler.test.ts +2 -2
  219. package/src/__tests__/telegram-bot-username-resolution.test.ts +46 -44
  220. package/src/__tests__/terminal-tools.test.ts +1 -11
  221. package/src/__tests__/thread-seed-composer.test.ts +3 -1
  222. package/src/__tests__/tool-approval-handler.test.ts +5 -7
  223. package/src/__tests__/tool-executor.test.ts +2 -2
  224. package/src/__tests__/tool-grant-request-escalation.test.ts +3 -5
  225. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  226. package/src/__tests__/tool-profiling-listener.test.ts +1 -1
  227. package/src/__tests__/tool-trace-listener.test.ts +1 -2
  228. package/src/__tests__/trace-emitter.test.ts +1 -1
  229. package/src/__tests__/trust-context-guards.test.ts +1 -1
  230. package/src/__tests__/trust-store.test.ts +44 -395
  231. package/src/__tests__/trusted-contact-approval-notifier.test.ts +6 -8
  232. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +5 -7
  233. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +6 -6
  234. package/src/__tests__/trusted-contact-multichannel.test.ts +54 -47
  235. package/src/__tests__/trusted-contact-verification.test.ts +12 -12
  236. package/src/__tests__/twilio-config.test.ts +11 -2
  237. package/src/__tests__/twilio-provider.test.ts +6 -4
  238. package/src/__tests__/twilio-routes.test.ts +408 -86
  239. package/src/__tests__/twitter-platform-proxy-client.test.ts +450 -0
  240. package/src/__tests__/update-bulletin-format.test.ts +1 -1
  241. package/src/__tests__/update-bulletin-state.test.ts +1 -1
  242. package/src/__tests__/update-bulletin.test.ts +4 -8
  243. package/src/__tests__/update-template-contract.test.ts +1 -1
  244. package/src/__tests__/usage-cache-backfill-migration.test.ts +406 -0
  245. package/src/__tests__/usage-routes.test.ts +23 -5
  246. package/src/__tests__/user-reference.test.ts +1 -1
  247. package/src/__tests__/{guardian-control-plane-policy.test.ts → verification-control-plane-policy.test.ts} +142 -170
  248. package/src/__tests__/{guardian-verification-intent-routing.test.ts → verification-session-intent-routing.test.ts} +16 -16
  249. package/src/__tests__/view-image-tool.test.ts +0 -2
  250. package/src/__tests__/voice-ingress-preflight.test.ts +36 -0
  251. package/src/__tests__/voice-invite-redemption.test.ts +18 -18
  252. package/src/__tests__/voice-scoped-grant-consumer.test.ts +7 -7
  253. package/src/__tests__/voice-session-bridge.test.ts +14 -16
  254. package/src/__tests__/workspace-policy.test.ts +1 -1
  255. package/src/approvals/AGENTS.md +4 -4
  256. package/src/approvals/approval-primitive.ts +2 -2
  257. package/src/approvals/guardian-decision-primitive.ts +1 -1
  258. package/src/approvals/guardian-request-resolvers.ts +3 -4
  259. package/src/bundler/app-bundler.ts +29 -217
  260. package/src/bundler/app-compiler.ts +131 -103
  261. package/src/bundler/compiler-tools.ts +248 -0
  262. package/src/calls/active-call-lease.ts +207 -0
  263. package/src/calls/call-constants.ts +0 -7
  264. package/src/calls/call-controller.ts +1 -1
  265. package/src/calls/call-conversation-messages.ts +6 -6
  266. package/src/calls/call-domain.ts +73 -38
  267. package/src/calls/call-pointer-message-composer.ts +6 -6
  268. package/src/calls/call-pointer-messages.ts +14 -13
  269. package/src/calls/call-recovery.ts +2 -0
  270. package/src/calls/call-store.ts +21 -28
  271. package/src/calls/guardian-action-sweep.ts +6 -8
  272. package/src/calls/guardian-dispatch.ts +2 -6
  273. package/src/calls/relay-access-wait.ts +4 -4
  274. package/src/calls/relay-server.ts +69 -80
  275. package/src/calls/relay-setup-router.ts +16 -21
  276. package/src/calls/relay-verification.ts +27 -28
  277. package/src/calls/twilio-config.ts +28 -3
  278. package/src/calls/twilio-provider.ts +5 -5
  279. package/src/calls/twilio-rest.ts +26 -27
  280. package/src/calls/twilio-routes.ts +67 -54
  281. package/src/calls/types.ts +8 -8
  282. package/src/calls/voice-ingress-preflight.ts +110 -0
  283. package/src/calls/voice-session-bridge.ts +7 -7
  284. package/src/channels/config.ts +1 -10
  285. package/src/{config/channel-permission-profiles.ts → channels/permission-profiles.ts} +1 -1
  286. package/src/channels/types.ts +2 -13
  287. package/src/cli/__tests__/notifications.test.ts +1 -1
  288. package/src/{amazon → cli/commands/amazon}/client.ts +99 -42
  289. package/src/cli/{amazon.ts → commands/amazon/index.ts} +12 -17
  290. package/src/{amazon → cli/commands/amazon}/request-extractor.ts +39 -3
  291. package/src/cli/commands/amazon/session.ts +116 -0
  292. package/src/cli/{audit.ts → commands/audit.ts} +2 -4
  293. package/src/cli/{autonomy.ts → commands/autonomy.ts} +1 -3
  294. package/src/cli/commands/browser-relay.ts +520 -0
  295. package/src/cli/commands/channel-verification-sessions.ts +442 -0
  296. package/src/cli/{completions.ts → commands/completions.ts} +1 -3
  297. package/src/cli/{config.ts → commands/config.ts} +3 -5
  298. package/src/cli/{contacts.ts → commands/contacts.ts} +263 -16
  299. package/src/cli/{credentials.ts → commands/credentials.ts} +9 -10
  300. package/src/cli/{default-action.ts → commands/default-action.ts} +3 -3
  301. package/src/cli/{dev.ts → commands/dev.ts} +4 -6
  302. package/src/cli/{doctor.ts → commands/doctor.ts} +36 -60
  303. package/src/cli/{email.ts → commands/email.ts} +2 -2
  304. package/src/cli/{keys.ts → commands/keys.ts} +6 -6
  305. package/src/cli/{map.ts → commands/map.ts} +85 -93
  306. package/src/cli/{mcp.ts → commands/mcp.ts} +5 -7
  307. package/src/cli/{memory.ts → commands/memory.ts} +6 -7
  308. package/src/cli/{notifications.ts → commands/notifications.ts} +8 -10
  309. package/src/cli/{oauth.ts → commands/oauth.ts} +2 -2
  310. package/src/cli/commands/platform.ts +176 -0
  311. package/src/cli/{sequence.ts → commands/sequence.ts} +3 -3
  312. package/src/cli/{sessions.ts → commands/sessions.ts} +32 -52
  313. package/src/cli/commands/skills.ts +498 -0
  314. package/src/cli/{trust.ts → commands/trust.ts} +2 -4
  315. package/src/{__tests__/twitter-cli-error-shaping.test.ts → cli/commands/twitter/__tests__/cli-error-shaping.test.ts} +43 -2
  316. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +483 -0
  317. package/src/{__tests__/twitter-cli-routing.test.ts → cli/commands/twitter/__tests__/cli-routing.test.ts} +130 -4
  318. package/src/{__tests__/twitter-oauth-client.test.ts → cli/commands/twitter/__tests__/oauth-client.test.ts} +2 -2
  319. package/src/{twitter → cli/commands/twitter}/client.ts +17 -7
  320. package/src/cli/{twitter.ts → commands/twitter/index.ts} +322 -273
  321. package/src/cli/commands/twitter/router.ts +396 -0
  322. package/src/cli/commands/twitter/session.ts +121 -0
  323. package/src/cli/db.ts +1 -0
  324. package/src/cli/http-client.ts +87 -0
  325. package/src/cli/logger.ts +6 -0
  326. package/src/cli/main-screen.tsx +4 -3
  327. package/src/cli/output.ts +19 -0
  328. package/src/cli/program.ts +29 -27
  329. package/src/cli/reference.ts +27 -37
  330. package/src/cli.ts +452 -240
  331. package/src/config/assistant-feature-flags.ts +3 -15
  332. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +3 -6
  333. package/src/config/bundled-skills/agentmail/SKILL.md +4 -4
  334. package/src/config/bundled-skills/amazon/SKILL.md +15 -5
  335. package/src/config/bundled-skills/api-mapping/SKILL.md +4 -4
  336. package/src/config/bundled-skills/app-builder/SKILL.md +21 -6
  337. package/src/config/bundled-skills/browser/SKILL.md +4 -5
  338. package/src/config/bundled-skills/chatgpt-import/SKILL.md +4 -4
  339. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  340. package/src/config/bundled-skills/claude-code/SKILL.md +4 -4
  341. package/src/config/bundled-skills/cli-discover/SKILL.md +4 -4
  342. package/src/config/bundled-skills/computer-use/SKILL.md +4 -4
  343. package/src/config/bundled-skills/contacts/SKILL.md +87 -229
  344. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +4 -4
  345. package/src/config/bundled-skills/document/SKILL.md +4 -3
  346. package/src/config/bundled-skills/document-writer/SKILL.md +4 -4
  347. package/src/config/bundled-skills/doordash/SKILL.md +4 -11
  348. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +8 -16
  349. package/src/config/bundled-skills/doordash/doordash-cli.ts +120 -86
  350. package/src/config/bundled-skills/doordash/lib/session.ts +1 -2
  351. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +26 -9
  352. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +140 -0
  353. package/src/config/bundled-skills/email-setup/SKILL.md +4 -4
  354. package/src/config/bundled-skills/followups/SKILL.md +4 -3
  355. package/src/config/bundled-skills/frontend-design/SKILL.md +2 -0
  356. package/src/config/bundled-skills/google-calendar/SKILL.md +4 -4
  357. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +4 -6
  358. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +26 -41
  359. package/src/config/bundled-skills/image-studio/SKILL.md +4 -5
  360. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -1
  361. package/src/config/bundled-skills/influencer/SKILL.md +19 -19
  362. package/src/{influencer → config/bundled-skills/influencer/scripts}/client.ts +73 -56
  363. package/src/config/bundled-skills/influencer/scripts/influencer.ts +267 -0
  364. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -2
  365. package/src/config/bundled-skills/macos-automation/SKILL.md +4 -5
  366. package/src/config/bundled-skills/mcp-setup/SKILL.md +4 -4
  367. package/src/config/bundled-skills/media-processing/SKILL.md +3 -2
  368. package/src/config/bundled-skills/messaging/SKILL.md +6 -33
  369. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -5
  370. package/src/config/bundled-skills/notifications/SKILL.md +4 -4
  371. package/src/config/bundled-skills/notion/SKILL.md +4 -4
  372. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +4 -5
  373. package/src/config/bundled-skills/oauth-setup/SKILL.md +4 -5
  374. package/src/config/bundled-skills/phone-calls/SKILL.md +24 -458
  375. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +83 -0
  376. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +57 -0
  377. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +67 -0
  378. package/src/config/bundled-skills/playbooks/SKILL.md +4 -3
  379. package/src/config/bundled-skills/public-ingress/SKILL.md +65 -14
  380. package/src/config/bundled-skills/reminder/SKILL.md +4 -3
  381. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +4 -6
  382. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  383. package/src/config/bundled-skills/screen-recording/SKILL.md +4 -3
  384. package/src/config/bundled-skills/self-upgrade/SKILL.md +4 -4
  385. package/src/config/bundled-skills/skills-catalog/SKILL.md +4 -4
  386. package/src/config/bundled-skills/slack/SKILL.md +4 -8
  387. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +1 -1
  388. package/src/config/bundled-skills/slack-app-setup/SKILL.md +66 -88
  389. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +4 -5
  390. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +4 -5
  391. package/src/config/bundled-skills/start-the-day/SKILL.md +4 -4
  392. package/src/config/bundled-skills/subagent/SKILL.md +4 -3
  393. package/src/config/bundled-skills/tasks/SKILL.md +4 -3
  394. package/src/config/bundled-skills/telegram-setup/SKILL.md +63 -112
  395. package/src/config/bundled-skills/time-based-actions/SKILL.md +4 -3
  396. package/src/config/bundled-skills/transcribe/SKILL.md +4 -3
  397. package/src/config/bundled-skills/twilio-setup/SKILL.md +23 -50
  398. package/src/config/bundled-skills/twitter/SKILL.md +56 -14
  399. package/src/config/bundled-skills/typescript-eval/SKILL.md +4 -4
  400. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +4 -5
  401. package/src/config/bundled-skills/voice-setup/SKILL.md +19 -45
  402. package/src/config/bundled-skills/watcher/SKILL.md +4 -3
  403. package/src/config/env-registry.ts +1 -10
  404. package/src/config/feature-flag-registry.json +0 -16
  405. package/src/config/loader.ts +78 -38
  406. package/src/config/schema.ts +143 -106
  407. package/src/config/schemas/channels.ts +80 -0
  408. package/src/config/schemas/heartbeat.ts +51 -0
  409. package/src/config/schemas/inference.ts +136 -0
  410. package/src/config/schemas/ingress.ts +81 -0
  411. package/src/config/schemas/logging.ts +21 -0
  412. package/src/config/schemas/memory-lifecycle.ts +67 -0
  413. package/src/config/schemas/memory-processing.ts +215 -0
  414. package/src/config/schemas/memory-retrieval.ts +222 -0
  415. package/src/config/schemas/memory-storage.ts +83 -0
  416. package/src/config/schemas/memory.ts +58 -0
  417. package/src/config/schemas/platform.ts +64 -0
  418. package/src/config/schemas/security.ts +54 -0
  419. package/src/config/schemas/swarm.ts +50 -0
  420. package/src/config/schemas/timeouts.ts +47 -0
  421. package/src/config/{agent-schema.ts → schemas/workspace-git.ts} +0 -97
  422. package/src/config/skill-state.ts +3 -13
  423. package/src/config/skills.ts +233 -75
  424. package/src/config/types.ts +1 -20
  425. package/src/contacts/contact-store.ts +12 -49
  426. package/src/contacts/contacts-write.ts +1 -5
  427. package/src/contacts/index.ts +0 -2
  428. package/src/contacts/types.ts +0 -8
  429. package/src/context/window-manager.ts +73 -14
  430. package/src/daemon/assistant-attachments.ts +9 -0
  431. package/src/daemon/computer-use-session.ts +3 -3
  432. package/src/daemon/connection-policy.ts +6 -21
  433. package/src/daemon/context-overflow-policy.ts +1 -1
  434. package/src/daemon/daemon-control.ts +46 -54
  435. package/src/daemon/doordash-steps.ts +1 -1
  436. package/src/daemon/handlers/config-channels.ts +407 -71
  437. package/src/daemon/handlers/config-ingress.ts +17 -85
  438. package/src/daemon/handlers/config-model.ts +145 -123
  439. package/src/daemon/handlers/config-slack-channel.ts +43 -29
  440. package/src/daemon/handlers/config-telegram.ts +32 -27
  441. package/src/daemon/handlers/config-voice.ts +1 -4
  442. package/src/daemon/handlers/dictation.ts +11 -16
  443. package/src/daemon/handlers/identity.ts +5 -6
  444. package/src/daemon/handlers/pairing.ts +5 -13
  445. package/src/daemon/handlers/recording.ts +97 -199
  446. package/src/daemon/handlers/session-history.ts +110 -96
  447. package/src/daemon/handlers/session-user-message.ts +29 -57
  448. package/src/daemon/handlers/sessions.ts +240 -137
  449. package/src/daemon/handlers/shared.ts +62 -95
  450. package/src/daemon/handlers/skills.ts +492 -543
  451. package/src/daemon/lifecycle.ts +168 -55
  452. package/src/daemon/main.ts +1 -0
  453. package/src/daemon/{ipc-contract.ts → message-protocol.ts} +49 -49
  454. package/src/daemon/{ipc-contract → message-types}/computer-use.ts +0 -3
  455. package/src/daemon/{ipc-contract → message-types}/diagnostics.ts +0 -16
  456. package/src/daemon/{ipc-contract → message-types}/integrations.ts +29 -13
  457. package/src/daemon/{ipc-contract → message-types}/memory.ts +8 -0
  458. package/src/daemon/{ipc-contract → message-types}/notifications.ts +15 -1
  459. package/src/daemon/{ipc-contract → message-types}/sessions.ts +1 -0
  460. package/src/daemon/{ipc-contract → message-types}/shared.ts +0 -8
  461. package/src/daemon/{ipc-contract → message-types}/workspace.ts +2 -2
  462. package/src/daemon/providers-setup.ts +0 -5
  463. package/src/daemon/recording-executor.ts +0 -7
  464. package/src/daemon/ride-shotgun-handler.ts +9 -13
  465. package/src/daemon/server.ts +136 -510
  466. package/src/daemon/session-agent-loop-handlers.ts +22 -7
  467. package/src/daemon/session-agent-loop.ts +86 -24
  468. package/src/daemon/session-attachments.ts +1 -1
  469. package/src/daemon/session-error.ts +1 -1
  470. package/src/daemon/session-history.ts +20 -15
  471. package/src/daemon/session-lifecycle.ts +9 -7
  472. package/src/daemon/session-memory.ts +15 -1
  473. package/src/daemon/session-messaging.ts +10 -6
  474. package/src/daemon/session-notifiers.ts +10 -8
  475. package/src/daemon/session-process.ts +34 -25
  476. package/src/daemon/session-queue-manager.ts +1 -1
  477. package/src/daemon/session-runtime-assembly.ts +6 -25
  478. package/src/daemon/session-surfaces.ts +2 -2
  479. package/src/daemon/session-tool-setup.ts +1 -1
  480. package/src/daemon/session-usage.ts +119 -18
  481. package/src/daemon/session.ts +13 -9
  482. package/src/daemon/tool-side-effects.ts +6 -5
  483. package/src/daemon/trace-emitter.ts +1 -1
  484. package/src/daemon/{guardian-verification-intent.ts → verification-session-intent.ts} +16 -16
  485. package/src/daemon/watch-handler.ts +2 -5
  486. package/src/email/service.ts +8 -8
  487. package/src/events/domain-events.ts +0 -1
  488. package/src/events/tool-notification-listener.ts +1 -1
  489. package/src/followups/followup-store.ts +1 -2
  490. package/src/followups/types.ts +0 -6
  491. package/src/heartbeat/heartbeat-service.ts +1 -1
  492. package/src/inbound/platform-callback-registration.ts +1 -1
  493. package/src/inbound/public-ingress-urls.ts +0 -8
  494. package/src/index.ts +12 -0
  495. package/src/mcp/client.ts +1 -1
  496. package/src/mcp/manager.ts +1 -1
  497. package/src/memory/app-store.ts +1 -42
  498. package/src/memory/{guardian-verification.ts → channel-verification-sessions.ts} +110 -93
  499. package/src/memory/conversation-attention-store.ts +154 -0
  500. package/src/memory/conversation-bootstrap.ts +1 -1
  501. package/src/memory/conversation-crud.ts +53 -1
  502. package/src/memory/conversation-display-order-migration.ts +2 -3
  503. package/src/memory/conversation-queries.ts +1 -29
  504. package/src/memory/conversation-title-service.ts +26 -21
  505. package/src/memory/db-connection.ts +1 -8
  506. package/src/memory/db-init.ts +20 -0
  507. package/src/memory/delivery-crud.ts +4 -34
  508. package/src/memory/external-conversation-store.ts +1 -1
  509. package/src/memory/format-recall.ts +47 -0
  510. package/src/memory/guardian-action-store.ts +4 -5
  511. package/src/memory/guardian-rate-limits.ts +0 -3
  512. package/src/memory/invite-store.ts +1 -1
  513. package/src/memory/job-handlers/backfill.ts +9 -2
  514. package/src/memory/job-handlers/extraction.ts +2 -7
  515. package/src/memory/job-handlers/summarization.ts +1 -1
  516. package/src/memory/llm-usage-store.ts +11 -0
  517. package/src/memory/migrations/114-notifications.ts +12 -40
  518. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +357 -0
  519. package/src/memory/migrations/141-rename-verification-table.ts +55 -0
  520. package/src/memory/migrations/142-rename-verification-session-id-column.ts +32 -0
  521. package/src/memory/migrations/143-rename-guardian-verification-values.ts +48 -0
  522. package/src/memory/migrations/144-rename-voice-to-phone.ts +147 -0
  523. package/src/memory/migrations/index.ts +5 -0
  524. package/src/memory/migrations/registry.ts +30 -0
  525. package/src/memory/qdrant-circuit-breaker.ts +5 -0
  526. package/src/memory/retriever.test.ts +707 -0
  527. package/src/memory/retriever.ts +120 -116
  528. package/src/memory/schema/calls.ts +3 -7
  529. package/src/memory/schema/guardian.ts +2 -2
  530. package/src/memory/search/lexical.ts +4 -1
  531. package/src/memory/search/query-expansion.test.ts +70 -0
  532. package/src/memory/search/query-expansion.ts +118 -0
  533. package/src/memory/search/types.ts +18 -17
  534. package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
  535. package/src/messaging/providers/whatsapp/adapter.ts +1 -4
  536. package/src/messaging/registry.ts +0 -1
  537. package/src/notifications/README.md +13 -22
  538. package/src/notifications/adapters/macos.ts +1 -1
  539. package/src/notifications/conversation-pairing.ts +2 -2
  540. package/src/notifications/copy-composer.ts +2 -2
  541. package/src/notifications/decision-engine.ts +1 -10
  542. package/src/notifications/destination-resolver.ts +2 -3
  543. package/src/notifications/emit-signal.ts +2 -8
  544. package/src/notifications/guardian-question-mode.ts +5 -8
  545. package/src/notifications/signal.ts +1 -2
  546. package/src/notifications/types.ts +1 -1
  547. package/src/oauth/token-persistence.ts +25 -1
  548. package/src/permissions/checker.ts +4 -29
  549. package/src/permissions/defaults.ts +6 -6
  550. package/src/permissions/prompter.ts +1 -1
  551. package/src/permissions/secret-prompter.ts +1 -1
  552. package/src/permissions/shell-identity.ts +1 -1
  553. package/src/permissions/trust-store.ts +13 -76
  554. package/src/permissions/workspace-policy.ts +1 -1
  555. package/src/{config → prompts}/computer-use-prompt.ts +1 -1
  556. package/src/{config → prompts}/system-prompt.ts +40 -21
  557. package/src/runtime/AGENTS.md +6 -8
  558. package/src/runtime/access-request-helper.ts +36 -55
  559. package/src/runtime/actor-trust-resolver.ts +1 -24
  560. package/src/runtime/approval-message-composer.ts +6 -2
  561. package/src/runtime/assistant-event.ts +1 -1
  562. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +1 -1
  563. package/src/runtime/auth/__tests__/subject.test.ts +32 -0
  564. package/src/runtime/auth/route-policy.ts +140 -24
  565. package/src/runtime/auth/subject.ts +9 -0
  566. package/src/runtime/auth/token-service.ts +11 -0
  567. package/src/runtime/auth/types.ts +1 -1
  568. package/src/runtime/channel-approval-types.ts +1 -1
  569. package/src/runtime/channel-approvals.ts +1 -1
  570. package/src/runtime/channel-invite-transport.ts +0 -2
  571. package/src/runtime/channel-invite-transports/slack.ts +5 -19
  572. package/src/runtime/channel-invite-transports/telegram.ts +17 -34
  573. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  574. package/src/runtime/channel-readiness-service.ts +24 -159
  575. package/src/runtime/channel-readiness-types.ts +5 -1
  576. package/src/runtime/channel-reply-delivery.ts +43 -3
  577. package/src/runtime/channel-retry-sweep.ts +14 -22
  578. package/src/runtime/{channel-guardian-service.ts → channel-verification-service.ts} +50 -53
  579. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -3
  580. package/src/runtime/gateway-client.ts +12 -15
  581. package/src/runtime/guardian-action-followup-executor.ts +8 -73
  582. package/src/runtime/guardian-action-grant-minter.ts +45 -61
  583. package/src/runtime/guardian-action-message-composer.ts +4 -4
  584. package/src/runtime/guardian-reply-router.ts +3 -3
  585. package/src/runtime/http-server.ts +133 -24
  586. package/src/runtime/http-types.ts +34 -1
  587. package/src/runtime/invite-instruction-generator.ts +1 -3
  588. package/src/runtime/invite-redemption-service.ts +5 -5
  589. package/src/runtime/invite-service.ts +7 -7
  590. package/src/runtime/local-actor-identity.ts +28 -2
  591. package/src/runtime/local-gateway-health.ts +275 -0
  592. package/src/runtime/middleware/twilio-validation.ts +3 -3
  593. package/src/runtime/migrations/migration-transport.ts +18 -3
  594. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  595. package/src/runtime/nl-approval-parser.ts +2 -3
  596. package/src/runtime/routes/access-request-decision.ts +2 -2
  597. package/src/runtime/routes/app-management-routes.ts +921 -0
  598. package/src/runtime/routes/approval-routes.ts +76 -7
  599. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +38 -203
  600. package/src/runtime/routes/channel-delivery-routes.ts +5 -4
  601. package/src/runtime/routes/channel-route-shared.ts +1 -3
  602. package/src/runtime/routes/channel-routes.ts +1 -4
  603. package/src/runtime/routes/channel-verification-routes.ts +257 -0
  604. package/src/runtime/routes/computer-use-routes.ts +595 -0
  605. package/src/runtime/routes/contact-routes.ts +1 -317
  606. package/src/runtime/routes/conversation-attention-routes.ts +6 -5
  607. package/src/runtime/routes/conversation-routes.ts +11 -18
  608. package/src/runtime/routes/debug-routes.ts +1 -1
  609. package/src/runtime/routes/diagnostics-routes.ts +813 -0
  610. package/src/runtime/routes/documents-routes.ts +227 -0
  611. package/src/runtime/routes/guardian-approval-interception.ts +25 -48
  612. package/src/runtime/routes/guardian-bootstrap-routes.ts +3 -3
  613. package/src/runtime/routes/guardian-expiry-sweep.ts +2 -2
  614. package/src/runtime/routes/guardian-refresh-routes.ts +11 -6
  615. package/src/runtime/routes/inbound-conversation.ts +3 -10
  616. package/src/runtime/routes/inbound-message-handler.ts +7 -6
  617. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +22 -22
  618. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +44 -0
  619. package/src/runtime/routes/inbound-stages/background-dispatch.ts +140 -22
  620. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +4 -4
  621. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
  622. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +3 -3
  623. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  624. package/src/runtime/routes/inbound-stages/verification-intercept.ts +13 -14
  625. package/src/runtime/routes/integrations/slack/channel.ts +72 -0
  626. package/src/runtime/routes/{slack-share-routes.ts → integrations/slack/share.ts} +9 -9
  627. package/src/runtime/routes/integrations/telegram.ts +111 -0
  628. package/src/runtime/routes/integrations/twilio.ts +451 -0
  629. package/src/runtime/routes/invite-routes.ts +2 -2
  630. package/src/runtime/routes/pairing-routes.ts +1 -1
  631. package/src/runtime/routes/recording-routes.ts +332 -0
  632. package/src/{daemon/handlers/config-scheduling.ts → runtime/routes/schedule-routes.ts} +91 -106
  633. package/src/runtime/routes/session-management-routes.ts +167 -0
  634. package/src/runtime/routes/session-query-routes.ts +204 -0
  635. package/src/runtime/routes/settings-routes.ts +977 -0
  636. package/src/runtime/routes/skills-routes.ts +266 -0
  637. package/src/runtime/routes/subagents-routes.ts +246 -0
  638. package/src/runtime/routes/surface-action-routes.ts +100 -10
  639. package/src/runtime/routes/surface-content-routes.ts +1 -1
  640. package/src/runtime/routes/work-items-routes.ts +809 -0
  641. package/src/runtime/routes/workspace-routes.test.ts +778 -0
  642. package/src/runtime/routes/workspace-routes.ts +410 -0
  643. package/src/runtime/routes/workspace-utils.ts +88 -0
  644. package/src/runtime/telegram-streaming-delivery.test.ts +597 -0
  645. package/src/runtime/telegram-streaming-delivery.ts +380 -0
  646. package/src/runtime/tool-grant-request-helper.ts +1 -2
  647. package/src/runtime/trust-context-resolver.ts +0 -1
  648. package/src/runtime/{guardian-outbound-actions.ts → verification-outbound-actions.ts} +23 -188
  649. package/src/runtime/verification-rate-limiter.ts +2 -2
  650. package/src/runtime/{guardian-verification-templates.ts → verification-templates.ts} +2 -28
  651. package/src/schedule/integration-status.ts +2 -2
  652. package/src/schedule/schedule-store.ts +7 -9
  653. package/src/sequence/engine.ts +1 -1
  654. package/src/skills/active-skill-tools.ts +0 -8
  655. package/src/skills/clawhub.ts +1 -10
  656. package/src/skills/managed-store.ts +14 -4
  657. package/src/skills/slash-commands.ts +1 -1
  658. package/src/subagent/manager.ts +1 -1
  659. package/src/subagent/types.ts +1 -1
  660. package/src/tasks/SPEC.md +10 -10
  661. package/src/tasks/task-scheduler.ts +1 -1
  662. package/src/telegram/bot-username.ts +13 -0
  663. package/src/tools/assets/materialize.ts +1 -1
  664. package/src/tools/assets/search.ts +1 -1
  665. package/src/tools/browser/browser-execution.ts +2 -2
  666. package/src/tools/browser/browser-manager.ts +88 -11
  667. package/src/tools/browser/browser-screencast.ts +1 -1
  668. package/src/tools/browser/headless-browser.ts +0 -17
  669. package/src/tools/browser/jit-auth.ts +1 -1
  670. package/src/tools/browser/recording-store.ts +19 -1
  671. package/src/tools/browser/runtime-check.ts +4 -2
  672. package/src/tools/calls/call-start.ts +3 -3
  673. package/src/tools/credentials/metadata-store.ts +0 -13
  674. package/src/tools/credentials/vault.ts +7 -31
  675. package/src/tools/followups/followup_create.ts +0 -8
  676. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  677. package/src/tools/memory/definitions.ts +32 -10
  678. package/src/tools/memory/handlers.test.ts +573 -0
  679. package/src/tools/memory/handlers.ts +222 -65
  680. package/src/tools/memory/register.ts +53 -24
  681. package/src/tools/network/script-proxy/session-manager.ts +1 -12
  682. package/src/tools/schedule/update.ts +0 -8
  683. package/src/tools/skills/load.ts +3 -3
  684. package/src/tools/subagent/read.ts +1 -1
  685. package/src/tools/system/voice-config.ts +2 -14
  686. package/src/tools/terminal/safe-env.ts +5 -18
  687. package/src/tools/tool-approval-handler.ts +4 -4
  688. package/src/tools/tool-manifest.ts +4 -2
  689. package/src/tools/types.ts +1 -1
  690. package/src/tools/{guardian-control-plane-policy.ts → verification-control-plane-policy.ts} +37 -39
  691. package/src/twitter/platform-proxy-client.ts +405 -0
  692. package/src/usage/types.ts +21 -0
  693. package/src/util/canonicalize-identity.ts +2 -6
  694. package/src/util/cookie-session.ts +35 -51
  695. package/src/util/platform.ts +93 -86
  696. package/src/util/pricing.ts +180 -43
  697. package/src/work-items/work-item-runner.ts +1 -1
  698. package/scripts/ipc/check-contract-inventory.ts +0 -107
  699. package/scripts/ipc/check-swift-decoder-drift.ts +0 -184
  700. package/scripts/ipc/generate-swift.ts +0 -528
  701. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -3043
  702. package/src/__tests__/app-migration.test.ts +0 -148
  703. package/src/__tests__/config-loader-migration.test.ts +0 -85
  704. package/src/__tests__/daemon-lifecycle.test.ts +0 -715
  705. package/src/__tests__/daemon-server-session-init.test.ts +0 -864
  706. package/src/__tests__/guardian-actions-endpoint.test.ts +0 -1452
  707. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +0 -228
  708. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -397
  709. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -218
  710. package/src/__tests__/handlers-slack-config.test.ts +0 -140
  711. package/src/__tests__/handlers-telegram-config.test.ts +0 -1317
  712. package/src/__tests__/handlers-twitter-config.test.ts +0 -1145
  713. package/src/__tests__/ingress-reconcile.test.ts +0 -606
  714. package/src/__tests__/integrations-cli.test.ts +0 -232
  715. package/src/__tests__/ipc-blob-store.test.ts +0 -329
  716. package/src/__tests__/ipc-contract-inventory.test.ts +0 -69
  717. package/src/__tests__/ipc-contract.test.ts +0 -76
  718. package/src/__tests__/ipc-protocol.test.ts +0 -120
  719. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -250
  720. package/src/__tests__/ipc-snapshot.test.ts +0 -2197
  721. package/src/__tests__/ipc-validate.test.ts +0 -471
  722. package/src/__tests__/migration-cli-flows.test.ts +0 -186
  723. package/src/__tests__/migration-ordering.test.ts +0 -267
  724. package/src/__tests__/oauth-connect-handler.test.ts +0 -361
  725. package/src/__tests__/platform-move-helper.test.ts +0 -108
  726. package/src/__tests__/platform-socket-path.test.ts +0 -52
  727. package/src/__tests__/platform-workspace-migration.test.ts +0 -1051
  728. package/src/__tests__/recording-intent-handler.test.ts +0 -1155
  729. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +0 -127
  730. package/src/__tests__/sms-messaging-provider.test.ts +0 -156
  731. package/src/__tests__/tool-permission-simulate-handler.test.ts +0 -367
  732. package/src/__tests__/twitter-auth-handler.test.ts +0 -561
  733. package/src/__tests__/work-item-output.test.ts +0 -150
  734. package/src/amazon/session.ts +0 -58
  735. package/src/cli/channels.ts +0 -51
  736. package/src/cli/influencer.ts +0 -319
  737. package/src/cli/integrations.ts +0 -372
  738. package/src/cli/ipc-client.ts +0 -88
  739. package/src/config/bundled-skills/configure-settings/SKILL.md +0 -86
  740. package/src/config/bundled-skills/doordash/lib/shared/ipc.ts +0 -32
  741. package/src/config/bundled-skills/sms-setup/SKILL.md +0 -210
  742. package/src/config/core-schema.ts +0 -434
  743. package/src/config/memory-schema.ts +0 -617
  744. package/src/daemon/auth-manager.ts +0 -106
  745. package/src/daemon/handlers/apps.ts +0 -758
  746. package/src/daemon/handlers/avatar.ts +0 -73
  747. package/src/daemon/handlers/browser.ts +0 -3
  748. package/src/daemon/handlers/computer-use.ts +0 -231
  749. package/src/daemon/handlers/config-dispatch.ts +0 -29
  750. package/src/daemon/handlers/config-heartbeat.ts +0 -299
  751. package/src/daemon/handlers/config-inbox.ts +0 -457
  752. package/src/daemon/handlers/config-integrations.ts +0 -409
  753. package/src/daemon/handlers/config-platform.ts +0 -77
  754. package/src/daemon/handlers/config-slack.ts +0 -41
  755. package/src/daemon/handlers/config-tools.ts +0 -226
  756. package/src/daemon/handlers/config-trust.ts +0 -135
  757. package/src/daemon/handlers/config.ts +0 -64
  758. package/src/daemon/handlers/contacts.ts +0 -193
  759. package/src/daemon/handlers/diagnostics.ts +0 -382
  760. package/src/daemon/handlers/documents.ts +0 -188
  761. package/src/daemon/handlers/guardian-actions.ts +0 -82
  762. package/src/daemon/handlers/home-base.ts +0 -82
  763. package/src/daemon/handlers/index.ts +0 -222
  764. package/src/daemon/handlers/misc.ts +0 -1139
  765. package/src/daemon/handlers/navigate-settings.ts +0 -29
  766. package/src/daemon/handlers/oauth-connect.ts +0 -202
  767. package/src/daemon/handlers/open-bundle-handler.ts +0 -88
  768. package/src/daemon/handlers/publish.ts +0 -176
  769. package/src/daemon/handlers/signing.ts +0 -56
  770. package/src/daemon/handlers/subagents.ts +0 -286
  771. package/src/daemon/handlers/twitter-auth.ts +0 -220
  772. package/src/daemon/handlers/work-items.ts +0 -796
  773. package/src/daemon/handlers/workspace-files.ts +0 -84
  774. package/src/daemon/handlers.ts +0 -16
  775. package/src/daemon/ipc-blob-store.ts +0 -246
  776. package/src/daemon/ipc-contract-inventory.json +0 -348
  777. package/src/daemon/ipc-contract-inventory.ts +0 -202
  778. package/src/daemon/ipc-handler.ts +0 -120
  779. package/src/daemon/ipc-protocol.ts +0 -85
  780. package/src/daemon/ipc-validate.ts +0 -254
  781. package/src/memory/app-migration.ts +0 -114
  782. package/src/memory/channel-delivery-store.ts +0 -40
  783. package/src/memory/channel-guardian-store.ts +0 -83
  784. package/src/memory/conversation-store.ts +0 -102
  785. package/src/memory/schema-migration.ts +0 -38
  786. package/src/messaging/providers/sms/adapter.ts +0 -232
  787. package/src/messaging/providers/sms/client.ts +0 -93
  788. package/src/messaging/providers/sms/types.ts +0 -7
  789. package/src/migrations/config-merge.ts +0 -62
  790. package/src/migrations/data-layout.ts +0 -89
  791. package/src/migrations/data-merge.ts +0 -44
  792. package/src/migrations/hooks-merge.ts +0 -118
  793. package/src/migrations/index.ts +0 -6
  794. package/src/migrations/log.ts +0 -28
  795. package/src/migrations/skills-merge.ts +0 -44
  796. package/src/migrations/workspace-layout.ts +0 -94
  797. package/src/notifications/adapters/sms.ts +0 -94
  798. package/src/runtime/channel-approval-parser.ts +0 -123
  799. package/src/runtime/channel-invite-transports/sms.ts +0 -53
  800. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +0 -82
  801. package/src/runtime/routes/integration-routes.ts +0 -381
  802. package/src/runtime/routes/twilio-routes.ts +0 -1251
  803. package/src/twitter/router.ts +0 -131
  804. package/src/twitter/session.ts +0 -54
  805. package/src/watcher/providers/slack.ts +0 -282
  806. /package/src/{amazon → cli/commands/amazon}/cart.ts +0 -0
  807. /package/src/{amazon → cli/commands/amazon}/checkout.ts +0 -0
  808. /package/src/{amazon → cli/commands/amazon}/product-details.ts +0 -0
  809. /package/src/{amazon → cli/commands/amazon}/search.ts +0 -0
  810. /package/src/{twitter → cli/commands/twitter}/oauth-client.ts +0 -0
  811. /package/src/config/{calls-schema.ts → schemas/calls.ts} +0 -0
  812. /package/src/config/{elevenlabs-schema.ts → schemas/elevenlabs.ts} +0 -0
  813. /package/src/config/{mcp-schema.ts → schemas/mcp.ts} +0 -0
  814. /package/src/config/{notifications-schema.ts → schemas/notifications.ts} +0 -0
  815. /package/src/config/{sandbox-schema.ts → schemas/sandbox.ts} +0 -0
  816. /package/src/config/{skills-schema.ts → schemas/skills.ts} +0 -0
  817. /package/src/daemon/{ipc-contract → message-types}/apps.ts +0 -0
  818. /package/src/daemon/{ipc-contract → message-types}/browser.ts +0 -0
  819. /package/src/daemon/{ipc-contract → message-types}/contacts.ts +0 -0
  820. /package/src/daemon/{ipc-contract → message-types}/documents.ts +0 -0
  821. /package/src/daemon/{ipc-contract → message-types}/guardian-actions.ts +0 -0
  822. /package/src/daemon/{ipc-contract → message-types}/inbox.ts +0 -0
  823. /package/src/daemon/{ipc-contract → message-types}/messages.ts +0 -0
  824. /package/src/daemon/{ipc-contract → message-types}/pairing.ts +0 -0
  825. /package/src/daemon/{ipc-contract → message-types}/schedules.ts +0 -0
  826. /package/src/daemon/{ipc-contract → message-types}/settings.ts +0 -0
  827. /package/src/daemon/{ipc-contract → message-types}/skills.ts +0 -0
  828. /package/src/daemon/{ipc-contract → message-types}/subagents.ts +0 -0
  829. /package/src/daemon/{ipc-contract → message-types}/surfaces.ts +0 -0
  830. /package/src/daemon/{ipc-contract → message-types}/trust.ts +0 -0
  831. /package/src/daemon/{ipc-contract → message-types}/work-items.ts +0 -0
  832. /package/src/{cli/email-guardrails.ts → email/guardrails.ts} +0 -0
  833. /package/src/{config → prompts}/__tests__/build-cli-reference-section.test.ts +0 -0
  834. /package/src/{config → prompts}/templates/BOOTSTRAP.md +0 -0
  835. /package/src/{config → prompts}/templates/IDENTITY.md +0 -0
  836. /package/src/{config → prompts}/templates/SOUL.md +0 -0
  837. /package/src/{config → prompts}/templates/UPDATES.md +0 -0
  838. /package/src/{config → prompts}/templates/USER.md +0 -0
  839. /package/src/{config → prompts}/update-bulletin-format.ts +0 -0
  840. /package/src/{config → prompts}/update-bulletin-state.ts +0 -0
  841. /package/src/{config → prompts}/update-bulletin-template-path.ts +0 -0
  842. /package/src/{config → prompts}/update-bulletin.ts +0 -0
  843. /package/src/{config → prompts}/user-reference.ts +0 -0
@@ -1,5 +1,4 @@
1
1
  import { existsSync, rmSync } from "node:fs";
2
- import * as net from "node:net";
3
2
  import { join } from "node:path";
4
3
 
5
4
  import {
@@ -24,6 +23,7 @@ import {
24
23
  import {
25
24
  clawhubCheckUpdates,
26
25
  clawhubInspect,
26
+ type ClawhubInspectResult,
27
27
  clawhubInstall,
28
28
  clawhubSearch,
29
29
  clawhubUpdate,
@@ -48,7 +48,7 @@ import type {
48
48
  SkillsSearchRequest,
49
49
  SkillsUninstallRequest,
50
50
  SkillsUpdateRequest,
51
- } from "../ipc-protocol.js";
51
+ } from "../message-protocol.js";
52
52
  import {
53
53
  CONFIG_RELOAD_DEBOUNCE_MS,
54
54
  defineHandlers,
@@ -57,6 +57,20 @@ import {
57
57
  log,
58
58
  } from "./shared.js";
59
59
 
60
+ // ─── Shared context for standalone functions ─────────────────────────────────
61
+
62
+ /**
63
+ * Minimal context needed by the standalone skill business-logic functions.
64
+ * HandlerContext satisfies this interface, but HTTP routes can also provide
65
+ * a compatible object without coupling to IPC internals.
66
+ */
67
+ export interface SkillOperationContext {
68
+ debounceTimers: HandlerContext["debounceTimers"];
69
+ setSuppressConfigReload(value: boolean): void;
70
+ updateConfigFingerprint(): void;
71
+ broadcast: HandlerContext["broadcast"];
72
+ }
73
+
60
74
  // ─── Provenance resolution ──────────────────────────────────────────────────
61
75
 
62
76
  interface SkillProvenance {
@@ -103,17 +117,147 @@ function resolveProvenance(summary: SkillSummary): SkillProvenance {
103
117
  return { kind: "local" };
104
118
  }
105
119
 
106
- export function handleSkillsList(
107
- socket: net.Socket,
108
- ctx: HandlerContext,
120
+ // ─── Frontmatter parsing ─────────────────────────────────────────────────────
121
+
122
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
123
+
124
+ interface ParsedFrontmatter {
125
+ skillId?: string;
126
+ name?: string;
127
+ description?: string;
128
+ emoji?: string;
129
+ body: string;
130
+ }
131
+
132
+ function parseFrontmatter(sourceText: string): ParsedFrontmatter {
133
+ const match = FRONTMATTER_RE.exec(sourceText);
134
+ if (!match) return { body: sourceText };
135
+
136
+ const yamlBlock = match[1];
137
+ const body = match[2].replace(/\r\n/g, "\n");
138
+
139
+ const result: ParsedFrontmatter = { body };
140
+
141
+ // Simple YAML key-value extraction (handles quoted and unquoted values)
142
+ for (const line of yamlBlock.split(/\r?\n/)) {
143
+ const kvMatch = /^(\w[\w-]*):\s*(.+)$/.exec(line.trim());
144
+ if (!kvMatch) continue;
145
+ const key = kvMatch[1];
146
+ // Strip surrounding quotes
147
+ let value = kvMatch[2].trim();
148
+ if (
149
+ (value.startsWith('"') && value.endsWith('"')) ||
150
+ (value.startsWith("'") && value.endsWith("'"))
151
+ ) {
152
+ value = value.slice(1, -1);
153
+ }
154
+ switch (key) {
155
+ case "skill-id":
156
+ case "skillId":
157
+ case "id":
158
+ result.skillId = value;
159
+ break;
160
+ case "name":
161
+ result.name = value;
162
+ break;
163
+ case "description":
164
+ result.description = value;
165
+ break;
166
+ case "emoji":
167
+ result.emoji = value;
168
+ break;
169
+ }
170
+ }
171
+
172
+ return result;
173
+ }
174
+
175
+ // ─── Slug normalization ──────────────────────────────────────────────────────
176
+
177
+ function toSkillSlug(raw: string): string {
178
+ return raw
179
+ .toLowerCase()
180
+ .replace(/[^a-z0-9._-]+/g, "-") // replace non-valid chars with hyphens
181
+ .replace(/^[^a-z0-9]+/, "") // must start with alphanumeric
182
+ .replace(/-+/g, "-") // collapse multiple hyphens
183
+ .slice(0, 50)
184
+ .replace(/-$/, ""); // no trailing hyphen (after truncation)
185
+ }
186
+
187
+ // ─── Deterministic heuristic draft ───────────────────────────────────────────
188
+
189
+ function heuristicDraft(body: string): {
190
+ skillId: string;
191
+ name: string;
192
+ description: string;
193
+ emoji: string;
194
+ } {
195
+ const lines = body.split("\n").filter((l) => l.trim());
196
+ const firstLine = lines[0]?.trim() ?? "";
197
+ const name =
198
+ firstLine.replace(/^#+\s*/, "").slice(0, 100) || "Untitled Skill";
199
+ const skillId = toSkillSlug(name) || "untitled-skill";
200
+ const description = body.trim().slice(0, 200) || "No description provided";
201
+ return { skillId, name, description, emoji: "\u{1F4DD}" };
202
+ }
203
+
204
+ const LLM_DRAFT_TIMEOUT_MS = 15_000;
205
+
206
+ // ─── Standalone business-logic functions ─────────────────────────────────────
207
+ // These are consumed by both the IPC handlers below and the HTTP route layer.
208
+
209
+ /** Helper: suppress config reload, save, debounce, and update fingerprint. */
210
+ function saveConfigWithSuppression(
211
+ raw: Record<string, unknown>,
212
+ ctx: SkillOperationContext,
109
213
  ): void {
214
+ ctx.setSuppressConfigReload(true);
215
+ try {
216
+ saveRawConfig(raw);
217
+ } catch (err) {
218
+ ctx.setSuppressConfigReload(false);
219
+ throw err;
220
+ }
221
+ invalidateConfigCache();
222
+
223
+ ctx.debounceTimers.schedule(
224
+ "__suppress_reset__",
225
+ () => {
226
+ ctx.setSuppressConfigReload(false);
227
+ },
228
+ CONFIG_RELOAD_DEBOUNCE_MS,
229
+ );
230
+
231
+ ctx.updateConfigFingerprint();
232
+ }
233
+
234
+ export interface SkillListItem {
235
+ id: string;
236
+ name: string;
237
+ description: string;
238
+ emoji?: string;
239
+ homepage?: string;
240
+ source: "bundled" | "managed" | "workspace" | "clawhub" | "extra";
241
+ state: "enabled" | "disabled" | "available";
242
+ degraded: boolean;
243
+ missingRequirements?: {
244
+ bins?: string[];
245
+ env?: string[];
246
+ permissions?: string[];
247
+ };
248
+ updateAvailable: boolean;
249
+ userInvocable: boolean;
250
+ provenance: SkillProvenance;
251
+ }
252
+
253
+ export function listSkills(_ctx: SkillOperationContext): SkillListItem[] {
110
254
  const config = getConfig();
111
255
  const catalog = loadSkillCatalog();
112
256
  const resolved = resolveSkillStates(catalog, config);
113
257
 
114
- const skills = resolved.map((r) => ({
258
+ return resolved.map((r) => ({
115
259
  id: r.summary.id,
116
- name: r.summary.name,
260
+ name: r.summary.displayName,
117
261
  description: r.summary.description,
118
262
  emoji: r.summary.emoji,
119
263
  homepage: r.summary.homepage,
@@ -128,340 +272,169 @@ export function handleSkillsList(
128
272
  userInvocable: r.summary.userInvocable,
129
273
  provenance: resolveProvenance(r.summary),
130
274
  }));
131
-
132
- ctx.send(socket, { type: "skills_list_response", skills });
133
275
  }
134
276
 
135
- export function handleSkillsEnable(
136
- msg: SkillsEnableRequest,
137
- socket: net.Socket,
138
- ctx: HandlerContext,
139
- ): void {
277
+ export function enableSkill(
278
+ skillId: string,
279
+ ctx: SkillOperationContext,
280
+ ): { success: true } | { success: false; error: string } {
140
281
  try {
141
282
  const raw = loadRawConfig();
142
- ensureSkillEntry(raw, msg.name).enabled = true;
143
-
144
- ctx.setSuppressConfigReload(true);
145
- try {
146
- saveRawConfig(raw);
147
- } catch (err) {
148
- ctx.setSuppressConfigReload(false);
149
- throw err;
150
- }
151
- invalidateConfigCache();
152
-
153
- ctx.debounceTimers.schedule(
154
- "__suppress_reset__",
155
- () => {
156
- ctx.setSuppressConfigReload(false);
157
- },
158
- CONFIG_RELOAD_DEBOUNCE_MS,
159
- );
160
-
161
- ctx.updateConfigFingerprint();
162
-
163
- ctx.send(socket, {
164
- type: "skills_operation_response",
165
- operation: "enable",
166
- success: true,
167
- });
283
+ ensureSkillEntry(raw, skillId).enabled = true;
284
+ saveConfigWithSuppression(raw, ctx);
168
285
  ctx.broadcast({
169
286
  type: "skills_state_changed",
170
- name: msg.name,
287
+ name: skillId,
171
288
  state: "enabled",
172
289
  });
290
+ return { success: true };
173
291
  } catch (err) {
174
292
  const message = err instanceof Error ? err.message : String(err);
175
293
  log.error({ err }, "Failed to enable skill");
176
- ctx.send(socket, {
177
- type: "skills_operation_response",
178
- operation: "enable",
179
- success: false,
180
- error: message,
181
- });
294
+ return { success: false, error: message };
182
295
  }
183
296
  }
184
297
 
185
- export function handleSkillsDisable(
186
- msg: SkillsDisableRequest,
187
- socket: net.Socket,
188
- ctx: HandlerContext,
189
- ): void {
298
+ export function disableSkill(
299
+ skillId: string,
300
+ ctx: SkillOperationContext,
301
+ ): { success: true } | { success: false; error: string } {
190
302
  try {
191
303
  const raw = loadRawConfig();
192
- ensureSkillEntry(raw, msg.name).enabled = false;
193
-
194
- ctx.setSuppressConfigReload(true);
195
- try {
196
- saveRawConfig(raw);
197
- } catch (err) {
198
- ctx.setSuppressConfigReload(false);
199
- throw err;
200
- }
201
- invalidateConfigCache();
202
-
203
- ctx.debounceTimers.schedule(
204
- "__suppress_reset__",
205
- () => {
206
- ctx.setSuppressConfigReload(false);
207
- },
208
- CONFIG_RELOAD_DEBOUNCE_MS,
209
- );
210
-
211
- ctx.updateConfigFingerprint();
212
-
213
- ctx.send(socket, {
214
- type: "skills_operation_response",
215
- operation: "disable",
216
- success: true,
217
- });
304
+ ensureSkillEntry(raw, skillId).enabled = false;
305
+ saveConfigWithSuppression(raw, ctx);
218
306
  ctx.broadcast({
219
307
  type: "skills_state_changed",
220
- name: msg.name,
308
+ name: skillId,
221
309
  state: "disabled",
222
310
  });
311
+ return { success: true };
223
312
  } catch (err) {
224
313
  const message = err instanceof Error ? err.message : String(err);
225
314
  log.error({ err }, "Failed to disable skill");
226
- ctx.send(socket, {
227
- type: "skills_operation_response",
228
- operation: "disable",
229
- success: false,
230
- error: message,
231
- });
315
+ return { success: false, error: message };
232
316
  }
233
317
  }
234
318
 
235
- export function handleSkillsConfigure(
236
- msg: SkillsConfigureRequest,
237
- socket: net.Socket,
238
- ctx: HandlerContext,
239
- ): void {
319
+ export function configureSkill(
320
+ skillId: string,
321
+ config: { env?: Record<string, string>; apiKey?: string; config?: Record<string, unknown> },
322
+ ctx: SkillOperationContext,
323
+ ): { success: true } | { success: false; error: string } {
240
324
  try {
241
325
  const raw = loadRawConfig();
242
-
243
- const entry = ensureSkillEntry(raw, msg.name);
244
- if (msg.env) {
245
- entry.env = msg.env;
246
- }
247
- if (msg.apiKey !== undefined) {
248
- entry.apiKey = msg.apiKey;
249
- }
250
- if (msg.config) {
251
- entry.config = msg.config;
252
- }
253
-
254
- ctx.setSuppressConfigReload(true);
255
- try {
256
- saveRawConfig(raw);
257
- } catch (err) {
258
- ctx.setSuppressConfigReload(false);
259
- throw err;
260
- }
261
- invalidateConfigCache();
262
-
263
- ctx.debounceTimers.schedule(
264
- "__suppress_reset__",
265
- () => {
266
- ctx.setSuppressConfigReload(false);
267
- },
268
- CONFIG_RELOAD_DEBOUNCE_MS,
269
- );
270
-
271
- ctx.updateConfigFingerprint();
272
-
273
- ctx.send(socket, {
274
- type: "skills_operation_response",
275
- operation: "configure",
276
- success: true,
277
- });
326
+ const entry = ensureSkillEntry(raw, skillId);
327
+ if (config.env) entry.env = config.env;
328
+ if (config.apiKey !== undefined) entry.apiKey = config.apiKey;
329
+ if (config.config) entry.config = config.config;
330
+ saveConfigWithSuppression(raw, ctx);
331
+ return { success: true };
278
332
  } catch (err) {
279
333
  const message = err instanceof Error ? err.message : String(err);
280
334
  log.error({ err }, "Failed to configure skill");
281
- ctx.send(socket, {
282
- type: "skills_operation_response",
283
- operation: "configure",
284
- success: false,
285
- error: message,
286
- });
335
+ return { success: false, error: message };
287
336
  }
288
337
  }
289
338
 
290
- export async function handleSkillsInstall(
291
- msg: SkillsInstallRequest,
292
- socket: net.Socket,
293
- ctx: HandlerContext,
294
- ): Promise<void> {
339
+ export async function installSkill(
340
+ spec: { slug: string; version?: string },
341
+ ctx: SkillOperationContext,
342
+ ): Promise<{ success: true } | { success: false; error: string }> {
295
343
  try {
296
344
  // Bundled skills are already available — no install needed
297
345
  const catalog = loadSkillCatalog();
298
346
  const bundled = catalog.find(
299
- (s) => s.id === msg.slug && s.source === "bundled",
347
+ (s) => s.id === spec.slug && s.source === "bundled",
300
348
  );
301
349
  if (bundled) {
302
350
  // Auto-enable the bundled skill so it's immediately usable
303
- let autoEnabled = false;
304
351
  try {
305
352
  const raw = loadRawConfig();
306
- ensureSkillEntry(raw, msg.slug).enabled = true;
307
- ctx.setSuppressConfigReload(true);
308
- try {
309
- saveRawConfig(raw);
310
- } catch (err) {
311
- ctx.setSuppressConfigReload(false);
312
- throw err;
313
- }
314
- invalidateConfigCache();
315
- ctx.debounceTimers.schedule(
316
- "__suppress_reset__",
317
- () => {
318
- ctx.setSuppressConfigReload(false);
319
- },
320
- CONFIG_RELOAD_DEBOUNCE_MS,
321
- );
322
- ctx.updateConfigFingerprint();
323
- autoEnabled = true;
324
- } catch (err) {
325
- log.warn(
326
- { err, skillId: msg.slug },
327
- "Failed to auto-enable bundled skill",
328
- );
329
- }
330
-
331
- ctx.send(socket, {
332
- type: "skills_operation_response",
333
- operation: "install",
334
- success: true,
335
- });
336
- if (autoEnabled) {
353
+ ensureSkillEntry(raw, spec.slug).enabled = true;
354
+ saveConfigWithSuppression(raw, ctx);
337
355
  ctx.broadcast({
338
356
  type: "skills_state_changed",
339
- name: msg.slug,
357
+ name: spec.slug,
340
358
  state: "enabled",
341
359
  });
360
+ } catch (err) {
361
+ log.warn(
362
+ { err, skillId: spec.slug },
363
+ "Failed to auto-enable bundled skill",
364
+ );
342
365
  }
343
- return;
366
+ return { success: true };
344
367
  }
345
368
 
346
369
  // Install from clawhub (community)
347
- const result = await clawhubInstall(msg.slug, { version: msg.version });
370
+ const result = await clawhubInstall(spec.slug, { version: spec.version });
348
371
  if (!result.success) {
349
- ctx.send(socket, {
350
- type: "skills_operation_response",
351
- operation: "install",
352
- success: false,
353
- error: result.error ?? "Unknown error",
354
- });
355
- return;
372
+ return { success: false, error: result.error ?? "Unknown error" };
356
373
  }
357
- const rawId = result.skillName ?? msg.slug;
374
+ const rawId = result.skillName ?? spec.slug;
358
375
  const skillId = rawId.includes("/") ? rawId.split("/").pop()! : rawId;
359
376
 
360
377
  // Reload skill catalog so the newly installed skill is picked up
361
378
  loadSkillCatalog();
362
379
 
363
- // Auto-enable the newly installed skill so it's immediately usable.
364
- let autoEnabled = false;
380
+ // Auto-enable the newly installed skill
365
381
  try {
366
382
  const raw = loadRawConfig();
367
383
  ensureSkillEntry(raw, skillId).enabled = true;
368
- ctx.setSuppressConfigReload(true);
369
- try {
370
- saveRawConfig(raw);
371
- } catch (err) {
372
- ctx.setSuppressConfigReload(false);
373
- throw err;
374
- }
375
- invalidateConfigCache();
376
- ctx.debounceTimers.schedule(
377
- "__suppress_reset__",
378
- () => {
379
- ctx.setSuppressConfigReload(false);
380
- },
381
- CONFIG_RELOAD_DEBOUNCE_MS,
382
- );
383
- ctx.updateConfigFingerprint();
384
- autoEnabled = true;
385
- } catch (err) {
386
- log.warn({ err, skillId }, "Failed to auto-enable installed skill");
387
- }
388
-
389
- ctx.send(socket, {
390
- type: "skills_operation_response",
391
- operation: "install",
392
- success: true,
393
- });
394
- if (autoEnabled) {
384
+ saveConfigWithSuppression(raw, ctx);
395
385
  ctx.broadcast({
396
386
  type: "skills_state_changed",
397
387
  name: skillId,
398
388
  state: "enabled",
399
389
  });
390
+ } catch (err) {
391
+ log.warn({ err, skillId }, "Failed to auto-enable installed skill");
400
392
  }
393
+
394
+ return { success: true };
401
395
  } catch (err) {
402
396
  const message = err instanceof Error ? err.message : String(err);
403
397
  log.error({ err }, "Failed to install skill");
404
- ctx.send(socket, {
405
- type: "skills_operation_response",
406
- operation: "install",
407
- success: false,
408
- error: message,
409
- });
398
+ return { success: false, error: message };
410
399
  }
411
400
  }
412
401
 
413
- export async function handleSkillsUninstall(
414
- msg: SkillsUninstallRequest,
415
- socket: net.Socket,
416
- ctx: HandlerContext,
417
- ): Promise<void> {
402
+ export async function uninstallSkill(
403
+ skillId: string,
404
+ ctx: SkillOperationContext,
405
+ ): Promise<{ success: true } | { success: false; error: string }> {
418
406
  // Validate skill name to prevent path traversal while allowing namespaced slugs (org/name)
419
407
  const validNamespacedSlug =
420
408
  /^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
421
409
  const validSimpleName = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
422
410
  if (
423
- msg.name.includes("..") ||
424
- msg.name.includes("\\") ||
425
- !(validSimpleName.test(msg.name) || validNamespacedSlug.test(msg.name))
411
+ skillId.includes("..") ||
412
+ skillId.includes("\\") ||
413
+ !(validSimpleName.test(skillId) || validNamespacedSlug.test(skillId))
426
414
  ) {
427
- ctx.send(socket, {
428
- type: "skills_operation_response",
429
- operation: "uninstall",
430
- success: false,
431
- error: "Invalid skill name",
432
- });
433
- return;
415
+ return { success: false, error: "Invalid skill name" };
434
416
  }
435
417
 
436
418
  try {
437
419
  // Use shared managed-store logic for simple managed skill IDs
438
- const isManagedId = !validateManagedSkillId(msg.name);
420
+ const isManagedId = !validateManagedSkillId(skillId);
439
421
  if (isManagedId) {
440
- const result = deleteManagedSkill(msg.name);
422
+ const result = deleteManagedSkill(skillId);
441
423
  if (!result.deleted) {
442
- ctx.send(socket, {
443
- type: "skills_operation_response",
444
- operation: "uninstall",
424
+ return {
445
425
  success: false,
446
426
  error: result.error ?? "Failed to delete managed skill",
447
- });
448
- return;
427
+ };
449
428
  }
450
429
  } else {
451
430
  // Namespaced slug (org/name) — direct filesystem removal
452
- const skillDir = join(getWorkspaceSkillsDir(), msg.name);
431
+ const skillDir = join(getWorkspaceSkillsDir(), skillId);
453
432
  if (!existsSync(skillDir)) {
454
- ctx.send(socket, {
455
- type: "skills_operation_response",
456
- operation: "uninstall",
457
- success: false,
458
- error: "Skill not found",
459
- });
460
- return;
433
+ return { success: false, error: "Skill not found" };
461
434
  }
462
435
  rmSync(skillDir, { recursive: true });
463
436
  try {
464
- removeSkillsIndexEntry(msg.name);
437
+ removeSkillsIndexEntry(skillId);
465
438
  } catch {
466
439
  /* best effort */
467
440
  }
@@ -471,288 +444,110 @@ export async function handleSkillsUninstall(
471
444
  const raw = loadRawConfig();
472
445
  const skills = raw.skills as Record<string, unknown> | undefined;
473
446
  const entries = skills?.entries as Record<string, unknown> | undefined;
474
- if (entries?.[msg.name]) {
475
- delete entries[msg.name];
476
-
477
- ctx.setSuppressConfigReload(true);
478
- try {
479
- saveRawConfig(raw);
480
- } catch (err) {
481
- ctx.setSuppressConfigReload(false);
482
- throw err;
483
- }
484
- invalidateConfigCache();
485
-
486
- ctx.debounceTimers.schedule(
487
- "__suppress_reset__",
488
- () => {
489
- ctx.setSuppressConfigReload(false);
490
- },
491
- CONFIG_RELOAD_DEBOUNCE_MS,
492
- );
493
-
494
- ctx.updateConfigFingerprint();
447
+ if (entries?.[skillId]) {
448
+ delete entries[skillId];
449
+ saveConfigWithSuppression(raw, ctx);
495
450
  }
496
451
 
497
- ctx.send(socket, {
498
- type: "skills_operation_response",
499
- operation: "uninstall",
500
- success: true,
501
- });
502
452
  ctx.broadcast({
503
453
  type: "skills_state_changed",
504
- name: msg.name,
454
+ name: skillId,
505
455
  state: "uninstalled",
506
456
  });
457
+
458
+ return { success: true };
507
459
  } catch (err) {
508
460
  const message = err instanceof Error ? err.message : String(err);
509
461
  log.error({ err }, "Failed to uninstall skill");
510
- ctx.send(socket, {
511
- type: "skills_operation_response",
512
- operation: "uninstall",
513
- success: false,
514
- error: message,
515
- });
462
+ return { success: false, error: message };
516
463
  }
517
464
  }
518
465
 
519
- export async function handleSkillsUpdate(
520
- msg: SkillsUpdateRequest,
521
- socket: net.Socket,
522
- ctx: HandlerContext,
523
- ): Promise<void> {
466
+ export async function updateSkill(
467
+ skillId: string,
468
+ _ctx: SkillOperationContext,
469
+ ): Promise<{ success: true } | { success: false; error: string }> {
524
470
  try {
525
- const result = await clawhubUpdate(msg.name);
471
+ const result = await clawhubUpdate(skillId);
526
472
  if (!result.success) {
527
- ctx.send(socket, {
528
- type: "skills_operation_response",
529
- operation: "update",
530
- success: false,
531
- error: result.error ?? "Unknown error",
532
- });
533
- return;
473
+ return { success: false, error: result.error ?? "Unknown error" };
534
474
  }
535
-
536
475
  // Reload skill catalog to pick up updated skill
537
476
  loadSkillCatalog();
538
-
539
- ctx.send(socket, {
540
- type: "skills_operation_response",
541
- operation: "update",
542
- success: true,
543
- });
477
+ return { success: true };
544
478
  } catch (err) {
545
479
  const message = err instanceof Error ? err.message : String(err);
546
480
  log.error({ err }, "Failed to update skill");
547
- ctx.send(socket, {
548
- type: "skills_operation_response",
549
- operation: "update",
550
- success: false,
551
- error: message,
552
- });
481
+ return { success: false, error: message };
553
482
  }
554
483
  }
555
484
 
556
- export async function handleSkillsCheckUpdates(
557
- _msg: SkillsCheckUpdatesRequest,
558
- socket: net.Socket,
559
- ctx: HandlerContext,
560
- ): Promise<void> {
485
+ export async function checkSkillUpdates(
486
+ _ctx: SkillOperationContext,
487
+ ): Promise<{ success: true; data: unknown } | { success: false; error: string }> {
561
488
  try {
562
489
  const updates = await clawhubCheckUpdates();
563
- ctx.send(socket, {
564
- type: "skills_operation_response",
565
- operation: "check_updates",
566
- success: true,
567
- data: updates,
568
- });
490
+ return { success: true, data: updates };
569
491
  } catch (err) {
570
492
  const message = err instanceof Error ? err.message : String(err);
571
493
  log.error({ err }, "Failed to check for skill updates");
572
- ctx.send(socket, {
573
- type: "skills_operation_response",
574
- operation: "check_updates",
575
- success: false,
576
- error: message,
577
- });
494
+ return { success: false, error: message };
578
495
  }
579
496
  }
580
497
 
581
- export async function handleSkillsSearch(
582
- msg: SkillsSearchRequest,
583
- socket: net.Socket,
584
- ctx: HandlerContext,
585
- ): Promise<void> {
498
+ export async function searchSkills(
499
+ query: string,
500
+ _ctx: SkillOperationContext,
501
+ ): Promise<{ success: true; data: unknown } | { success: false; error: string }> {
586
502
  try {
587
- const result = await clawhubSearch(msg.query);
588
-
589
- ctx.send(socket, {
590
- type: "skills_operation_response",
591
- operation: "search",
592
- success: true,
593
- data: result,
594
- });
503
+ const result = await clawhubSearch(query);
504
+ return { success: true, data: result };
595
505
  } catch (err) {
596
506
  const message = err instanceof Error ? err.message : String(err);
597
507
  log.error({ err }, "Failed to search skills");
598
- ctx.send(socket, {
599
- type: "skills_operation_response",
600
- operation: "search",
601
- success: false,
602
- error: message,
603
- });
508
+ return { success: false, error: message };
604
509
  }
605
510
  }
606
511
 
607
- export async function handleSkillsInspect(
608
- msg: SkillsInspectRequest,
609
- socket: net.Socket,
610
- ctx: HandlerContext,
611
- ): Promise<void> {
512
+ export async function inspectSkill(
513
+ skillId: string,
514
+ _ctx: SkillOperationContext,
515
+ ): Promise<{ slug: string; data?: ClawhubInspectResult; error?: string }> {
612
516
  try {
613
- const result = await clawhubInspect(msg.slug);
614
- ctx.send(socket, {
615
- type: "skills_inspect_response",
616
- slug: msg.slug,
517
+ const result = await clawhubInspect(skillId);
518
+ return {
519
+ slug: skillId,
617
520
  ...(result.data ? { data: result.data } : {}),
618
521
  ...(result.error ? { error: result.error } : {}),
619
- });
522
+ };
620
523
  } catch (err) {
621
524
  const message = err instanceof Error ? err.message : String(err);
622
525
  log.error({ err }, "Failed to inspect skill");
623
- ctx.send(socket, {
624
- type: "skills_inspect_response",
625
- slug: msg.slug,
626
- error: message,
627
- });
628
- }
629
- }
630
-
631
- export async function handleSkillDetail(
632
- msg: SkillDetailRequest,
633
- socket: net.Socket,
634
- ctx: HandlerContext,
635
- ): Promise<void> {
636
- const result = loadSkillBySelector(msg.skillId);
637
- if (result.skill) {
638
- const icon = await ensureSkillIcon(
639
- result.skill.directoryPath,
640
- result.skill.name,
641
- result.skill.description,
642
- );
643
- ctx.send(socket, {
644
- type: "skill_detail_response",
645
- skillId: result.skill.id,
646
- body: result.skill.body,
647
- ...(icon ? { icon } : {}),
648
- });
649
- } else {
650
- ctx.send(socket, {
651
- type: "skill_detail_response",
652
- skillId: msg.skillId,
653
- body: "",
654
- error: result.error ?? "Skill not found",
655
- });
526
+ return { slug: skillId, error: message };
656
527
  }
657
528
  }
658
529
 
659
- // ─── Frontmatter parsing ─────────────────────────────────────────────────────
660
-
661
- const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
662
-
663
- interface ParsedFrontmatter {
664
- skillId?: string;
665
- name?: string;
666
- description?: string;
667
- emoji?: string;
668
- body: string;
530
+ export interface DraftResult {
531
+ success: boolean;
532
+ draft?: {
533
+ skillId: string;
534
+ name: string;
535
+ description: string;
536
+ emoji?: string;
537
+ bodyMarkdown: string;
538
+ };
539
+ warnings?: string[];
540
+ error?: string;
669
541
  }
670
542
 
671
- function parseFrontmatter(sourceText: string): ParsedFrontmatter {
672
- const match = FRONTMATTER_RE.exec(sourceText);
673
- if (!match) return { body: sourceText };
674
-
675
- const yamlBlock = match[1];
676
- const body = match[2].replace(/\r\n/g, "\n");
677
-
678
- const result: ParsedFrontmatter = { body };
679
-
680
- // Simple YAML key-value extraction (handles quoted and unquoted values)
681
- for (const line of yamlBlock.split(/\r?\n/)) {
682
- const kvMatch = /^(\w[\w-]*):\s*(.+)$/.exec(line.trim());
683
- if (!kvMatch) continue;
684
- const key = kvMatch[1];
685
- // Strip surrounding quotes
686
- let value = kvMatch[2].trim();
687
- if (
688
- (value.startsWith('"') && value.endsWith('"')) ||
689
- (value.startsWith("'") && value.endsWith("'"))
690
- ) {
691
- value = value.slice(1, -1);
692
- }
693
- switch (key) {
694
- case "skill-id":
695
- case "skillId":
696
- case "id":
697
- result.skillId = value;
698
- break;
699
- case "name":
700
- result.name = value;
701
- break;
702
- case "description":
703
- result.description = value;
704
- break;
705
- case "emoji":
706
- result.emoji = value;
707
- break;
708
- }
709
- }
710
-
711
- return result;
712
- }
713
-
714
- // ─── Slug normalization ──────────────────────────────────────────────────────
715
-
716
- function toSkillSlug(raw: string): string {
717
- return raw
718
- .toLowerCase()
719
- .replace(/[^a-z0-9._-]+/g, "-") // replace non-valid chars with hyphens
720
- .replace(/^[^a-z0-9]+/, "") // must start with alphanumeric
721
- .replace(/-+/g, "-") // collapse multiple hyphens
722
- .slice(0, 50)
723
- .replace(/-$/, ""); // no trailing hyphen (after truncation)
724
- }
725
-
726
- // ─── Deterministic heuristic draft ───────────────────────────────────────────
727
-
728
- function heuristicDraft(body: string): {
729
- skillId: string;
730
- name: string;
731
- description: string;
732
- emoji: string;
733
- } {
734
- const lines = body.split("\n").filter((l) => l.trim());
735
- const firstLine = lines[0]?.trim() ?? "";
736
- const name =
737
- firstLine.replace(/^#+\s*/, "").slice(0, 100) || "Untitled Skill";
738
- const skillId = toSkillSlug(name) || "untitled-skill";
739
- const description = body.trim().slice(0, 200) || "No description provided";
740
- return { skillId, name, description, emoji: "\u{1F4DD}" };
741
- }
742
-
743
- // ─── Draft handler ───────────────────────────────────────────────────────────
744
-
745
- const LLM_DRAFT_TIMEOUT_MS = 15_000;
746
-
747
- export async function handleSkillsDraft(
748
- msg: SkillsDraftRequest,
749
- socket: net.Socket,
750
- ctx: HandlerContext,
751
- ): Promise<void> {
543
+ export async function draftSkill(
544
+ params: { sourceText: string },
545
+ _ctx: SkillOperationContext,
546
+ ): Promise<DraftResult> {
752
547
  try {
753
548
  const warnings: string[] = [];
754
- const parsed = parseFrontmatter(msg.sourceText);
755
- const body = parsed.body.trim() || msg.sourceText.trim();
549
+ const parsed = parseFrontmatter(params.sourceText);
550
+ const body = parsed.body.trim() || params.sourceText.trim();
756
551
 
757
552
  let { skillId, name, description, emoji } = parsed;
758
553
 
@@ -870,8 +665,7 @@ export async function handleSkillsDraft(
870
665
  );
871
666
  }
872
667
 
873
- ctx.send(socket, {
874
- type: "skills_draft_response",
668
+ return {
875
669
  success: true,
876
670
  draft: {
877
671
  skillId: skillId!,
@@ -881,102 +675,257 @@ export async function handleSkillsDraft(
881
675
  bodyMarkdown: body,
882
676
  },
883
677
  ...(warnings.length > 0 ? { warnings } : {}),
884
- });
678
+ };
885
679
  } catch (err) {
886
680
  const message = err instanceof Error ? err.message : String(err);
887
681
  log.error({ err }, "Failed to generate skill draft");
888
- ctx.send(socket, {
889
- type: "skills_draft_response",
890
- success: false,
891
- error: message,
892
- });
682
+ return { success: false, error: message };
893
683
  }
894
684
  }
895
685
 
896
- // ─── Create handler ──────────────────────────────────────────────────────────
686
+ export interface CreateSkillParams {
687
+ skillId: string;
688
+ name: string;
689
+ description: string;
690
+ emoji?: string;
691
+ bodyMarkdown: string;
692
+ userInvocable?: boolean;
693
+ disableModelInvocation?: boolean;
694
+ overwrite?: boolean;
695
+ }
897
696
 
898
- export async function handleSkillsCreate(
899
- msg: SkillsCreateRequest,
900
- socket: net.Socket,
901
- ctx: HandlerContext,
902
- ): Promise<void> {
697
+ export async function createSkill(
698
+ params: CreateSkillParams,
699
+ ctx: SkillOperationContext,
700
+ ): Promise<{ success: true } | { success: false; error: string }> {
903
701
  try {
904
702
  const result = createManagedSkill({
905
- id: msg.skillId,
906
- name: msg.name,
907
- description: msg.description,
908
- emoji: msg.emoji,
909
- bodyMarkdown: msg.bodyMarkdown,
910
- userInvocable: msg.userInvocable,
911
- disableModelInvocation: msg.disableModelInvocation,
912
- overwrite: msg.overwrite,
703
+ id: params.skillId,
704
+ name: params.name,
705
+ description: params.description,
706
+ emoji: params.emoji,
707
+ bodyMarkdown: params.bodyMarkdown,
708
+ userInvocable: params.userInvocable,
709
+ disableModelInvocation: params.disableModelInvocation,
710
+ overwrite: params.overwrite,
913
711
  });
914
712
 
915
713
  if (!result.created) {
916
- ctx.send(socket, {
917
- type: "skills_operation_response",
918
- operation: "create",
714
+ return {
919
715
  success: false,
920
716
  error: result.error ?? "Failed to create managed skill",
921
- });
922
- return;
717
+ };
923
718
  }
924
719
 
925
720
  // Auto-enable the newly created skill
926
- let autoEnabled = false;
927
721
  try {
928
722
  const raw = loadRawConfig();
929
- ensureSkillEntry(raw, msg.skillId).enabled = true;
930
- ctx.setSuppressConfigReload(true);
931
- try {
932
- saveRawConfig(raw);
933
- } catch (err) {
934
- ctx.setSuppressConfigReload(false);
935
- throw err;
936
- }
937
- invalidateConfigCache();
938
- ctx.debounceTimers.schedule(
939
- "__suppress_reset__",
940
- () => {
941
- ctx.setSuppressConfigReload(false);
942
- },
943
- CONFIG_RELOAD_DEBOUNCE_MS,
944
- );
945
- ctx.updateConfigFingerprint();
946
- autoEnabled = true;
723
+ ensureSkillEntry(raw, params.skillId).enabled = true;
724
+ saveConfigWithSuppression(raw, ctx);
725
+ ctx.broadcast({
726
+ type: "skills_state_changed",
727
+ name: params.skillId,
728
+ state: "enabled",
729
+ });
947
730
  } catch (err) {
948
731
  log.warn(
949
- { err, skillId: msg.skillId },
732
+ { err, skillId: params.skillId },
950
733
  "Failed to auto-enable created skill",
951
734
  );
952
735
  }
953
736
 
954
- ctx.send(socket, {
955
- type: "skills_operation_response",
956
- operation: "create",
957
- success: true,
958
- });
959
- if (autoEnabled) {
960
- ctx.broadcast({
961
- type: "skills_state_changed",
962
- name: msg.skillId,
963
- state: "enabled",
964
- });
965
- }
737
+ return { success: true };
966
738
  } catch (err) {
967
739
  const message = err instanceof Error ? err.message : String(err);
968
740
  log.error({ err }, "Failed to create skill");
969
- ctx.send(socket, {
970
- type: "skills_operation_response",
971
- operation: "create",
972
- success: false,
973
- error: message,
741
+ return { success: false, error: message };
742
+ }
743
+ }
744
+
745
+ // ─── IPC handlers (thin wrappers) ───────────────────────────────────────────
746
+
747
+ export function handleSkillsList(
748
+ ctx: HandlerContext,
749
+ ): void {
750
+ const skills = listSkills(ctx);
751
+ ctx.send({ type: "skills_list_response", skills });
752
+ }
753
+
754
+ export function handleSkillsEnable(
755
+ msg: SkillsEnableRequest,
756
+ ctx: HandlerContext,
757
+ ): void {
758
+ const result = enableSkill(msg.name, ctx);
759
+ ctx.send({
760
+ type: "skills_operation_response",
761
+ operation: "enable",
762
+ ...result,
763
+ });
764
+ }
765
+
766
+ export function handleSkillsDisable(
767
+ msg: SkillsDisableRequest,
768
+ ctx: HandlerContext,
769
+ ): void {
770
+ const result = disableSkill(msg.name, ctx);
771
+ ctx.send({
772
+ type: "skills_operation_response",
773
+ operation: "disable",
774
+ ...result,
775
+ });
776
+ }
777
+
778
+ export function handleSkillsConfigure(
779
+ msg: SkillsConfigureRequest,
780
+ ctx: HandlerContext,
781
+ ): void {
782
+ const result = configureSkill(
783
+ msg.name,
784
+ { env: msg.env, apiKey: msg.apiKey, config: msg.config },
785
+ ctx,
786
+ );
787
+ ctx.send({
788
+ type: "skills_operation_response",
789
+ operation: "configure",
790
+ ...result,
791
+ });
792
+ }
793
+
794
+ export async function handleSkillsInstall(
795
+ msg: SkillsInstallRequest,
796
+ ctx: HandlerContext,
797
+ ): Promise<void> {
798
+ const result = await installSkill(
799
+ { slug: msg.slug, version: msg.version },
800
+ ctx,
801
+ );
802
+ ctx.send({
803
+ type: "skills_operation_response",
804
+ operation: "install",
805
+ ...result,
806
+ });
807
+ }
808
+
809
+ export async function handleSkillsUninstall(
810
+ msg: SkillsUninstallRequest,
811
+ ctx: HandlerContext,
812
+ ): Promise<void> {
813
+ const result = await uninstallSkill(msg.name, ctx);
814
+ ctx.send({
815
+ type: "skills_operation_response",
816
+ operation: "uninstall",
817
+ ...result,
818
+ });
819
+ }
820
+
821
+ export async function handleSkillsUpdate(
822
+ msg: SkillsUpdateRequest,
823
+ ctx: HandlerContext,
824
+ ): Promise<void> {
825
+ const result = await updateSkill(msg.name, ctx);
826
+ ctx.send({
827
+ type: "skills_operation_response",
828
+ operation: "update",
829
+ ...result,
830
+ });
831
+ }
832
+
833
+ export async function handleSkillsCheckUpdates(
834
+ _msg: SkillsCheckUpdatesRequest,
835
+ ctx: HandlerContext,
836
+ ): Promise<void> {
837
+ const result = await checkSkillUpdates(ctx);
838
+ ctx.send({
839
+ type: "skills_operation_response",
840
+ operation: "check_updates",
841
+ ...result,
842
+ });
843
+ }
844
+
845
+ export async function handleSkillsSearch(
846
+ msg: SkillsSearchRequest,
847
+ ctx: HandlerContext,
848
+ ): Promise<void> {
849
+ const result = await searchSkills(msg.query, ctx);
850
+ ctx.send({
851
+ type: "skills_operation_response",
852
+ operation: "search",
853
+ ...result,
854
+ });
855
+ }
856
+
857
+ export async function handleSkillsInspect(
858
+ msg: SkillsInspectRequest,
859
+ ctx: HandlerContext,
860
+ ): Promise<void> {
861
+ const result = await inspectSkill(msg.slug, ctx);
862
+ ctx.send({
863
+ type: "skills_inspect_response",
864
+ ...result,
865
+ });
866
+ }
867
+
868
+ export async function handleSkillDetail(
869
+ msg: SkillDetailRequest,
870
+ ctx: HandlerContext,
871
+ ): Promise<void> {
872
+ const result = loadSkillBySelector(msg.skillId);
873
+ if (result.skill) {
874
+ const icon = await ensureSkillIcon(
875
+ result.skill.directoryPath,
876
+ result.skill.displayName,
877
+ result.skill.description,
878
+ );
879
+ ctx.send({
880
+ type: "skill_detail_response",
881
+ skillId: result.skill.id,
882
+ body: result.skill.body,
883
+ ...(icon ? { icon } : {}),
884
+ });
885
+ } else {
886
+ ctx.send({
887
+ type: "skill_detail_response",
888
+ skillId: msg.skillId,
889
+ body: "",
890
+ error: result.error ?? "Skill not found",
974
891
  });
975
892
  }
976
893
  }
977
894
 
895
+ export async function handleSkillsDraft(
896
+ msg: SkillsDraftRequest,
897
+ ctx: HandlerContext,
898
+ ): Promise<void> {
899
+ const result = await draftSkill({ sourceText: msg.sourceText }, ctx);
900
+ ctx.send({ type: "skills_draft_response", ...result });
901
+ }
902
+
903
+ export async function handleSkillsCreate(
904
+ msg: SkillsCreateRequest,
905
+ ctx: HandlerContext,
906
+ ): Promise<void> {
907
+ const result = await createSkill(
908
+ {
909
+ skillId: msg.skillId,
910
+ name: msg.name,
911
+ description: msg.description,
912
+ emoji: msg.emoji,
913
+ bodyMarkdown: msg.bodyMarkdown,
914
+ userInvocable: msg.userInvocable,
915
+ disableModelInvocation: msg.disableModelInvocation,
916
+ overwrite: msg.overwrite,
917
+ },
918
+ ctx,
919
+ );
920
+ ctx.send({
921
+ type: "skills_operation_response",
922
+ operation: "create",
923
+ ...result,
924
+ });
925
+ }
926
+
978
927
  export const skillHandlers = defineHandlers({
979
- skills_list: (_msg, socket, ctx) => handleSkillsList(socket, ctx),
928
+ skills_list: (_msg, ctx) => handleSkillsList(ctx),
980
929
  skill_detail: handleSkillDetail,
981
930
  skills_enable: handleSkillsEnable,
982
931
  skills_disable: handleSkillsDisable,