@synap-core/cli 1.11.0 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (452) hide show
  1. package/README.md +23 -198
  2. package/dist/build-info.json +6 -0
  3. package/dist/commands/agent-run.js +3 -2
  4. package/dist/commands/agent-run.js.map +1 -1
  5. package/dist/commands/agents.d.ts +33 -17
  6. package/dist/commands/agents.js +203 -237
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/app.d.ts +143 -0
  9. package/dist/commands/app.js +523 -0
  10. package/dist/commands/app.js.map +1 -0
  11. package/dist/commands/automate.d.ts +21 -0
  12. package/dist/commands/automate.js +42 -0
  13. package/dist/commands/automate.js.map +1 -0
  14. package/dist/commands/automation-schema.test.d.ts +16 -0
  15. package/dist/commands/automation-schema.test.js +77 -0
  16. package/dist/commands/automation-schema.test.js.map +1 -0
  17. package/dist/commands/automation.d.ts +12 -0
  18. package/dist/commands/automation.js +80 -35
  19. package/dist/commands/automation.js.map +1 -1
  20. package/dist/commands/bridge-setup.d.ts +14 -1
  21. package/dist/commands/bridge-setup.js +392 -128
  22. package/dist/commands/bridge-setup.js.map +1 -1
  23. package/dist/commands/cap-connections.d.ts +4 -4
  24. package/dist/commands/cap-connections.js +14 -14
  25. package/dist/commands/cap-connections.js.map +1 -1
  26. package/dist/commands/capability.d.ts +2 -0
  27. package/dist/commands/capability.js +218 -168
  28. package/dist/commands/capability.js.map +1 -1
  29. package/dist/commands/catalog.d.ts +275 -0
  30. package/dist/commands/catalog.js +481 -0
  31. package/dist/commands/catalog.js.map +1 -0
  32. package/dist/commands/cell.d.ts +155 -8
  33. package/dist/commands/cell.js +416 -40
  34. package/dist/commands/cell.js.map +1 -1
  35. package/dist/commands/centrality.js +1 -13
  36. package/dist/commands/centrality.js.map +1 -1
  37. package/dist/commands/connect.d.ts +38 -13
  38. package/dist/commands/connect.js +68 -167
  39. package/dist/commands/connect.js.map +1 -1
  40. package/dist/commands/connections.d.ts +3 -2
  41. package/dist/commands/connections.js +95 -25
  42. package/dist/commands/connections.js.map +1 -1
  43. package/dist/commands/context.js +7 -1
  44. package/dist/commands/context.js.map +1 -1
  45. package/dist/commands/data-extra.d.ts +34 -0
  46. package/dist/commands/data-extra.js +193 -23
  47. package/dist/commands/data-extra.js.map +1 -1
  48. package/dist/commands/data.d.ts +120 -2
  49. package/dist/commands/data.js +293 -20
  50. package/dist/commands/data.js.map +1 -1
  51. package/dist/commands/diagnose.d.ts +66 -4
  52. package/dist/commands/diagnose.js +285 -28
  53. package/dist/commands/diagnose.js.map +1 -1
  54. package/dist/commands/doc.d.ts +11 -4
  55. package/dist/commands/doc.js +39 -14
  56. package/dist/commands/doc.js.map +1 -1
  57. package/dist/commands/doctor.d.ts +112 -3
  58. package/dist/commands/doctor.js +657 -32
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/explain.js +5 -5
  61. package/dist/commands/explain.js.map +1 -1
  62. package/dist/commands/import.d.ts +368 -13
  63. package/dist/commands/import.js +1064 -54
  64. package/dist/commands/import.js.map +1 -1
  65. package/dist/commands/init.d.ts +20 -9
  66. package/dist/commands/init.js +433 -973
  67. package/dist/commands/init.js.map +1 -1
  68. package/dist/commands/keys.d.ts +1 -0
  69. package/dist/commands/keys.js +15 -2
  70. package/dist/commands/keys.js.map +1 -1
  71. package/dist/commands/knowledge.d.ts +22 -6
  72. package/dist/commands/knowledge.js +117 -55
  73. package/dist/commands/knowledge.js.map +1 -1
  74. package/dist/commands/lens.d.ts +37 -1
  75. package/dist/commands/lens.js +192 -71
  76. package/dist/commands/lens.js.map +1 -1
  77. package/dist/commands/market-authoring.d.ts +29 -2
  78. package/dist/commands/market-authoring.js +348 -7
  79. package/dist/commands/market-authoring.js.map +1 -1
  80. package/dist/commands/market-official.d.ts +58 -0
  81. package/dist/commands/market-official.js +84 -0
  82. package/dist/commands/market-official.js.map +1 -0
  83. package/dist/commands/market.d.ts +400 -16
  84. package/dist/commands/market.js +1802 -146
  85. package/dist/commands/market.js.map +1 -1
  86. package/dist/commands/mcp.d.ts +60 -25
  87. package/dist/commands/mcp.js +251 -64
  88. package/dist/commands/mcp.js.map +1 -1
  89. package/dist/commands/open.d.ts +39 -9
  90. package/dist/commands/open.js +80 -25
  91. package/dist/commands/open.js.map +1 -1
  92. package/dist/commands/playbook.d.ts +42 -0
  93. package/dist/commands/playbook.js +162 -0
  94. package/dist/commands/playbook.js.map +1 -0
  95. package/dist/commands/pod.js +1 -1
  96. package/dist/commands/pod.js.map +1 -1
  97. package/dist/commands/pods.d.ts +5 -0
  98. package/dist/commands/pods.js +97 -116
  99. package/dist/commands/pods.js.map +1 -1
  100. package/dist/commands/proposals-actions.d.ts +62 -0
  101. package/dist/commands/proposals-actions.js +143 -8
  102. package/dist/commands/proposals-actions.js.map +1 -1
  103. package/dist/commands/proposals-await.d.ts +68 -0
  104. package/dist/commands/proposals-await.js +248 -0
  105. package/dist/commands/proposals-await.js.map +1 -0
  106. package/dist/commands/proton-setup.d.ts +73 -0
  107. package/dist/commands/proton-setup.js +577 -0
  108. package/dist/commands/proton-setup.js.map +1 -0
  109. package/dist/commands/providers.d.ts +23 -0
  110. package/dist/commands/providers.js +126 -1
  111. package/dist/commands/providers.js.map +1 -1
  112. package/dist/commands/raycast.js +6 -2
  113. package/dist/commands/raycast.js.map +1 -1
  114. package/dist/commands/rule.d.ts +150 -0
  115. package/dist/commands/rule.js +447 -0
  116. package/dist/commands/rule.js.map +1 -0
  117. package/dist/commands/session-wait.d.ts +111 -0
  118. package/dist/commands/session-wait.js +209 -0
  119. package/dist/commands/session-wait.js.map +1 -0
  120. package/dist/commands/sessions.d.ts +52 -0
  121. package/dist/commands/sessions.js +478 -58
  122. package/dist/commands/sessions.js.map +1 -1
  123. package/dist/commands/skill-manage.d.ts +21 -0
  124. package/dist/commands/skill-manage.js +136 -19
  125. package/dist/commands/skill-manage.js.map +1 -1
  126. package/dist/commands/skills.js +16 -0
  127. package/dist/commands/skills.js.map +1 -1
  128. package/dist/commands/status.d.ts +1 -4
  129. package/dist/commands/status.js +5 -34
  130. package/dist/commands/status.js.map +1 -1
  131. package/dist/commands/statusline.backoff.test.d.ts +13 -0
  132. package/dist/commands/statusline.backoff.test.js +100 -0
  133. package/dist/commands/statusline.backoff.test.js.map +1 -0
  134. package/dist/commands/statusline.js +16 -9
  135. package/dist/commands/statusline.js.map +1 -1
  136. package/dist/commands/sync-status.d.ts +12 -0
  137. package/dist/commands/sync-status.js +125 -0
  138. package/dist/commands/sync-status.js.map +1 -0
  139. package/dist/commands/templates-retire.d.ts +34 -0
  140. package/dist/commands/templates-retire.js +192 -0
  141. package/dist/commands/templates-retire.js.map +1 -0
  142. package/dist/commands/tools.js +6 -21
  143. package/dist/commands/tools.js.map +1 -1
  144. package/dist/commands/tracks.d.ts +51 -0
  145. package/dist/commands/tracks.js +291 -0
  146. package/dist/commands/tracks.js.map +1 -0
  147. package/dist/commands/update.d.ts +3 -11
  148. package/dist/commands/update.js +5 -134
  149. package/dist/commands/update.js.map +1 -1
  150. package/dist/commands/upload.d.ts +41 -3
  151. package/dist/commands/upload.js +120 -18
  152. package/dist/commands/upload.js.map +1 -1
  153. package/dist/commands/vendor.d.ts +28 -0
  154. package/dist/commands/vendor.js +110 -0
  155. package/dist/commands/vendor.js.map +1 -0
  156. package/dist/commands/versions.js +6 -0
  157. package/dist/commands/versions.js.map +1 -1
  158. package/dist/commands/view.js +10 -5
  159. package/dist/commands/view.js.map +1 -1
  160. package/dist/commands/whoami.d.ts +23 -3
  161. package/dist/commands/whoami.js +169 -23
  162. package/dist/commands/whoami.js.map +1 -1
  163. package/dist/commands/worker.d.ts +122 -0
  164. package/dist/commands/worker.js +435 -0
  165. package/dist/commands/worker.js.map +1 -0
  166. package/dist/commands/worker.test.d.ts +1 -0
  167. package/dist/commands/worker.test.js +116 -0
  168. package/dist/commands/worker.test.js.map +1 -0
  169. package/dist/commands/workspace-ops.d.ts +35 -0
  170. package/dist/commands/workspace-ops.js +153 -0
  171. package/dist/commands/workspace-ops.js.map +1 -0
  172. package/dist/index.d.ts +6 -6
  173. package/dist/index.js +900 -180
  174. package/dist/index.js.map +1 -1
  175. package/dist/lib/agent-connections.d.ts +31 -0
  176. package/dist/lib/agent-connections.js +33 -0
  177. package/dist/lib/agent-connections.js.map +1 -0
  178. package/dist/lib/agent-detect.d.ts +27 -0
  179. package/dist/lib/agent-detect.js +71 -0
  180. package/dist/lib/agent-detect.js.map +1 -0
  181. package/dist/lib/agent-door.d.ts +138 -0
  182. package/dist/lib/agent-door.js +426 -0
  183. package/dist/lib/agent-door.js.map +1 -0
  184. package/dist/lib/agents-config.d.ts +2 -0
  185. package/dist/lib/agents-config.js +4 -9
  186. package/dist/lib/agents-config.js.map +1 -1
  187. package/dist/lib/approval-poll.d.ts +31 -2
  188. package/dist/lib/approval-poll.js +20 -7
  189. package/dist/lib/approval-poll.js.map +1 -1
  190. package/dist/lib/atomic-file.d.ts +48 -0
  191. package/dist/lib/atomic-file.js +129 -0
  192. package/dist/lib/atomic-file.js.map +1 -0
  193. package/dist/lib/auth.d.ts +14 -9
  194. package/dist/lib/auth.js +44 -61
  195. package/dist/lib/auth.js.map +1 -1
  196. package/dist/lib/batch-approval.d.ts +85 -0
  197. package/dist/lib/batch-approval.js +170 -0
  198. package/dist/lib/batch-approval.js.map +1 -0
  199. package/dist/lib/capture-lane.d.ts +6 -5
  200. package/dist/lib/capture-lane.js +6 -5
  201. package/dist/lib/capture-lane.js.map +1 -1
  202. package/dist/lib/capture-structure.d.ts +230 -11
  203. package/dist/lib/capture-structure.js +251 -13
  204. package/dist/lib/capture-structure.js.map +1 -1
  205. package/dist/lib/catalog-templates.d.ts +59 -0
  206. package/dist/lib/catalog-templates.js +126 -0
  207. package/dist/lib/catalog-templates.js.map +1 -0
  208. package/dist/lib/cli-build.d.ts +19 -0
  209. package/dist/lib/cli-build.js +37 -0
  210. package/dist/lib/cli-build.js.map +1 -0
  211. package/dist/lib/conversation-headers.d.ts +18 -0
  212. package/dist/lib/conversation-headers.js +32 -0
  213. package/dist/lib/conversation-headers.js.map +1 -0
  214. package/dist/lib/cp-packages.d.ts +167 -11
  215. package/dist/lib/cp-packages.js +253 -21
  216. package/dist/lib/cp-packages.js.map +1 -1
  217. package/dist/lib/credential-class.d.ts +117 -0
  218. package/dist/lib/credential-class.js +116 -0
  219. package/dist/lib/credential-class.js.map +1 -0
  220. package/dist/lib/describe-lens.d.ts +35 -0
  221. package/dist/lib/describe-lens.js +40 -0
  222. package/dist/lib/describe-lens.js.map +1 -1
  223. package/dist/lib/device-connect.d.ts +125 -0
  224. package/dist/lib/device-connect.js +256 -0
  225. package/dist/lib/device-connect.js.map +1 -0
  226. package/dist/lib/directory-lens.d.ts +99 -0
  227. package/dist/lib/directory-lens.js +187 -0
  228. package/dist/lib/directory-lens.js.map +1 -0
  229. package/dist/lib/exporter-coverage.d.ts +71 -0
  230. package/dist/lib/exporter-coverage.js +97 -0
  231. package/dist/lib/exporter-coverage.js.map +1 -0
  232. package/dist/lib/hub-client.d.ts +29 -8
  233. package/dist/lib/hub-client.js +328 -55
  234. package/dist/lib/hub-client.js.map +1 -1
  235. package/dist/lib/init-connect.d.ts +41 -0
  236. package/dist/lib/init-connect.js +75 -0
  237. package/dist/lib/init-connect.js.map +1 -0
  238. package/dist/lib/init-exit.d.ts +24 -0
  239. package/dist/lib/init-exit.js +41 -0
  240. package/dist/lib/init-exit.js.map +1 -0
  241. package/dist/lib/init-flow.d.ts +25 -0
  242. package/dist/lib/init-flow.js +40 -0
  243. package/dist/lib/init-flow.js.map +1 -0
  244. package/dist/lib/init-handoff.d.ts +16 -0
  245. package/dist/lib/init-handoff.js +19 -0
  246. package/dist/lib/init-handoff.js.map +1 -0
  247. package/dist/lib/init-output.d.ts +18 -0
  248. package/dist/lib/init-output.js +43 -0
  249. package/dist/lib/init-output.js.map +1 -0
  250. package/dist/lib/init-pod.d.ts +45 -0
  251. package/dist/lib/init-pod.js +36 -0
  252. package/dist/lib/init-pod.js.map +1 -0
  253. package/dist/lib/installed.d.ts +210 -11
  254. package/dist/lib/installed.js +234 -36
  255. package/dist/lib/installed.js.map +1 -1
  256. package/dist/lib/key-approval.d.ts +57 -0
  257. package/dist/lib/key-approval.js +117 -0
  258. package/dist/lib/key-approval.js.map +1 -0
  259. package/dist/lib/key-diagnosis.d.ts +56 -0
  260. package/dist/lib/key-diagnosis.js +227 -0
  261. package/dist/lib/key-diagnosis.js.map +1 -0
  262. package/dist/lib/key-doctor.d.ts +136 -0
  263. package/dist/lib/key-doctor.js +286 -0
  264. package/dist/lib/key-doctor.js.map +1 -0
  265. package/dist/lib/key-locations.d.ts +120 -0
  266. package/dist/lib/key-locations.js +326 -0
  267. package/dist/lib/key-locations.js.map +1 -0
  268. package/dist/lib/key-source.d.ts +66 -0
  269. package/dist/lib/key-source.js +106 -0
  270. package/dist/lib/key-source.js.map +1 -0
  271. package/dist/lib/key-state.d.ts +70 -0
  272. package/dist/lib/key-state.js +115 -0
  273. package/dist/lib/key-state.js.map +1 -0
  274. package/dist/lib/kind-package.d.ts +181 -0
  275. package/dist/lib/kind-package.js +679 -0
  276. package/dist/lib/kind-package.js.map +1 -0
  277. package/dist/lib/knowledge-title.d.ts +24 -0
  278. package/dist/lib/knowledge-title.js +46 -0
  279. package/dist/lib/knowledge-title.js.map +1 -0
  280. package/dist/lib/knowledge-title.test.d.ts +1 -0
  281. package/dist/lib/knowledge-title.test.js +34 -0
  282. package/dist/lib/knowledge-title.test.js.map +1 -0
  283. package/dist/lib/machine-instance.d.ts +64 -0
  284. package/dist/lib/machine-instance.js +142 -0
  285. package/dist/lib/machine-instance.js.map +1 -0
  286. package/dist/lib/mcp-bridge.d.ts +42 -0
  287. package/dist/lib/mcp-bridge.js +147 -0
  288. package/dist/lib/mcp-bridge.js.map +1 -0
  289. package/dist/lib/mcp-bridge.test.d.ts +1 -0
  290. package/dist/lib/mcp-bridge.test.js +90 -0
  291. package/dist/lib/mcp-bridge.test.js.map +1 -0
  292. package/dist/lib/mcp-call.d.ts +30 -0
  293. package/dist/lib/mcp-call.js +107 -0
  294. package/dist/lib/mcp-call.js.map +1 -0
  295. package/dist/lib/mcp-snippets.d.ts +53 -0
  296. package/dist/lib/mcp-snippets.js +82 -0
  297. package/dist/lib/mcp-snippets.js.map +1 -0
  298. package/dist/lib/next-steps.d.ts +8 -0
  299. package/dist/lib/next-steps.js +31 -1
  300. package/dist/lib/next-steps.js.map +1 -1
  301. package/dist/lib/package-wire.d.ts +179 -0
  302. package/dist/lib/package-wire.js +68 -0
  303. package/dist/lib/package-wire.js.map +1 -0
  304. package/dist/lib/pair-link.d.ts +38 -0
  305. package/dist/lib/pair-link.js +68 -0
  306. package/dist/lib/pair-link.js.map +1 -0
  307. package/dist/lib/pod-wide.d.ts +40 -0
  308. package/dist/lib/pod-wide.js +46 -0
  309. package/dist/lib/pod-wide.js.map +1 -0
  310. package/dist/lib/pod.d.ts +66 -112
  311. package/dist/lib/pod.js +134 -412
  312. package/dist/lib/pod.js.map +1 -1
  313. package/dist/lib/project-ref.d.ts +9 -3
  314. package/dist/lib/project-ref.js +10 -4
  315. package/dist/lib/project-ref.js.map +1 -1
  316. package/dist/lib/review-credential.d.ts +119 -0
  317. package/dist/lib/review-credential.js +147 -0
  318. package/dist/lib/review-credential.js.map +1 -0
  319. package/dist/lib/safe-open.d.ts +49 -0
  320. package/dist/lib/safe-open.js +119 -0
  321. package/dist/lib/safe-open.js.map +1 -0
  322. package/dist/lib/session-lens.d.ts +40 -1
  323. package/dist/lib/session-lens.js +54 -4
  324. package/dist/lib/session-lens.js.map +1 -1
  325. package/dist/lib/superwhisper-import.d.ts +8 -0
  326. package/dist/lib/superwhisper-import.js +14 -7
  327. package/dist/lib/superwhisper-import.js.map +1 -1
  328. package/dist/lib/superwhisper-title.test.d.ts +1 -0
  329. package/dist/lib/superwhisper-title.test.js +18 -0
  330. package/dist/lib/superwhisper-title.test.js.map +1 -0
  331. package/dist/lib/targets.d.ts +134 -10
  332. package/dist/lib/targets.js +962 -258
  333. package/dist/lib/targets.js.map +1 -1
  334. package/dist/lib/template-file.d.ts +4 -0
  335. package/dist/lib/template-file.js.map +1 -1
  336. package/dist/lib/template-lifecycle.d.ts +217 -0
  337. package/dist/lib/template-lifecycle.js +433 -0
  338. package/dist/lib/template-lifecycle.js.map +1 -0
  339. package/dist/lib/template-steps.d.ts +88 -0
  340. package/dist/lib/template-steps.js +118 -0
  341. package/dist/lib/template-steps.js.map +1 -0
  342. package/dist/lib/time-ago.d.ts +2 -0
  343. package/dist/lib/time-ago.js +15 -0
  344. package/dist/lib/time-ago.js.map +1 -0
  345. package/dist/utils/logger.js +5 -2
  346. package/dist/utils/logger.js.map +1 -1
  347. package/package.json +23 -17
  348. package/skills/README.md +12 -10
  349. package/skills/agent-os/SKILL.md +214 -99
  350. package/skills/manifest.json +1 -1
  351. package/skills/onboard/SKILL.md +55 -26
  352. package/skills/synap/README.md +5 -8
  353. package/skills/synap/SKILL.md +1086 -283
  354. package/skills/synap/_order.txt +7 -0
  355. package/skills/synap/_skill.yaml +1 -1
  356. package/skills/synap/automations.md +15 -0
  357. package/skills/synap/capture.md +5 -0
  358. package/skills/synap/cli-operations.md +24 -18
  359. package/skills/synap/concepts.md +28 -0
  360. package/skills/synap/content-os.md +10 -1
  361. package/skills/synap/creative-loop.md +15 -10
  362. package/skills/synap/crm.md +21 -52
  363. package/skills/synap/document-embeds.md +141 -47
  364. package/skills/synap/escalation-ladder.md +20 -10
  365. package/skills/synap/focus-sessions.md +47 -21
  366. package/skills/synap/from-intent.md +142 -0
  367. package/skills/synap/governance-rules.md +4 -4
  368. package/skills/synap/governance.md +10 -7
  369. package/skills/synap/hand-off.md +33 -0
  370. package/skills/synap/inline-patterns.md +15 -7
  371. package/skills/synap/lenses.md +33 -15
  372. package/skills/synap/linking.md +41 -40
  373. package/skills/synap/mcp-remote-servers.md +64 -0
  374. package/skills/synap/mental-model.md +17 -15
  375. package/skills/synap/operating-mode-rules.md +1 -1
  376. package/skills/synap/processes.md +118 -0
  377. package/skills/synap/quick-reference.md +5 -1
  378. package/skills/synap/reading.md +3 -1
  379. package/skills/synap/reflexes.md +12 -42
  380. package/skills/synap/viewframe-cells.md +38 -5
  381. package/skills/synap/work-flow.md +1 -1
  382. package/skills/synap/work-model.md +96 -0
  383. package/skills/synap/worked-examples.md +4 -5
  384. package/skills/synap/workspace-design.md +14 -10
  385. package/skills/synap/writes.md +97 -24
  386. package/skills/synap/writing-titles.md +63 -0
  387. package/skills/synap-app/SKILL.md +2 -2
  388. package/skills/synap-app/_skill.yaml +1 -1
  389. package/skills/synap-app/install-commands.md +1 -1
  390. package/skills/synap-design/SKILL.md +474 -0
  391. package/skills/synap-design/_order.txt +4 -0
  392. package/skills/synap-design/_skill.yaml +21 -0
  393. package/skills/synap-design/loop.md +134 -0
  394. package/skills/synap-design/overview.md +44 -0
  395. package/skills/synap-design/principles.md +130 -0
  396. package/skills/synap-design/system.md +133 -0
  397. package/skills/synap-market/SKILL.md +306 -16
  398. package/skills/synap-market/_skill.yaml +1 -1
  399. package/skills/synap-market/author-and-publish.md +145 -8
  400. package/skills/synap-market/governance-and-catalog.md +7 -0
  401. package/skills/synap-market/install.md +79 -1
  402. package/skills/synap-market/overview.md +74 -6
  403. package/skills/synap-schema/SKILL.md +172 -10
  404. package/skills/synap-schema/_order.txt +2 -0
  405. package/skills/synap-schema/_skill.yaml +4 -2
  406. package/skills/synap-schema/common-mistakes.md +4 -2
  407. package/skills/synap-schema/discover-profiles.md +1 -1
  408. package/skills/synap-schema/entity-scope.md +15 -3
  409. package/skills/synap-schema/extend-first.md +29 -0
  410. package/skills/synap-schema/extend-vs-create.md +1 -1
  411. package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
  412. package/skills/synap-schema/property-types.md +1 -1
  413. package/skills/synap-schema/relations.md +1 -1
  414. package/skills/synap-ui/SKILL.md +19 -12
  415. package/skills/synap-ui/_skill.yaml +1 -1
  416. package/skills/synap-ui/ai-companion.md +1 -1
  417. package/skills/synap-ui/arranging-bento.md +2 -0
  418. package/skills/synap-ui/bento-layouts.md +10 -10
  419. package/skills/synap-ui/bento-recipes.md +313 -543
  420. package/skills/synap-ui/four-builds.md +5 -0
  421. package/skills/synap-ui/view-types.md +2 -2
  422. package/skills/synap-ui/widget-catalog.md +22 -278
  423. package/templates/automations/bookmark-enrichment.automation.json +290 -13
  424. package/templates/automations/url-bookmark-capture.automation.json +73 -11
  425. package/templates/skills/authoring-playbooks/SKILL.md +6 -3
  426. package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
  427. package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
  428. package/dist/commands/infra.d.ts +0 -21
  429. package/dist/commands/infra.js +0 -262
  430. package/dist/commands/infra.js.map +0 -1
  431. package/dist/commands/template.d.ts +0 -42
  432. package/dist/commands/template.js +0 -191
  433. package/dist/commands/template.js.map +0 -1
  434. package/dist/lib/browser-auth.d.ts +0 -35
  435. package/dist/lib/browser-auth.js +0 -170
  436. package/dist/lib/browser-auth.js.map +0 -1
  437. package/dist/lib/openclaw.d.ts +0 -32
  438. package/dist/lib/openclaw.js +0 -164
  439. package/dist/lib/openclaw.js.map +0 -1
  440. package/dist/lib/seed.d.ts +0 -13
  441. package/dist/lib/seed.js +0 -135
  442. package/dist/lib/seed.js.map +0 -1
  443. package/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -1261
  444. package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -1647
  445. package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -1647
  446. package/node_modules/@synap/hub-rest-client/dist/index.js +0 -1231
  447. package/node_modules/@synap/hub-rest-client/package.json +0 -45
  448. package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1631
  449. package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
  450. package/node_modules/@synap/hub-rest-client/src/index.ts +0 -153
  451. package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -133
  452. package/node_modules/@synap/hub-rest-client/src/types.ts +0 -1299
@@ -1,1631 +0,0 @@
1
- /**
2
- * HubRestClient — typed HTTP client for the Synap Hub Protocol REST API.
3
- *
4
- * Uses the native `fetch` API (Node.js >= 18, browsers, Deno, Bun).
5
- * Zero runtime dependencies.
6
- *
7
- * @example
8
- * ```ts
9
- * const client = new HubRestClient({
10
- * podUrl: "https://my-pod.synap.live",
11
- * apiKey: "synap_hub_live_...",
12
- * });
13
- *
14
- * const entities = await client.searchEntities("meeting notes", { profileSlug: "note" });
15
- * ```
16
- */
17
-
18
- import { HubApiError } from "./errors.js";
19
- import type {
20
- HubEntity,
21
- HubChannel,
22
- HubWorkspace,
23
- HubUser,
24
- HubMemoryResult,
25
- HubListResponse,
26
- HubSingleResponse,
27
- HubWorkspacesListResponse,
28
- CreateEntityInput,
29
- UpdateEntityInput,
30
- StoreMemoryInput,
31
- SendToChannelInput,
32
- CaptureProposal,
33
- CaptureStructureResponse,
34
- CaptureExecuteInput,
35
- CaptureExecuteResponse,
36
- AskResponse,
37
- HubDocument,
38
- HubRelation,
39
- HubGraphResult,
40
- HubConnectionsResult,
41
- HubProfile,
42
- HubPropertyDef,
43
- HubDiscoverResult,
44
- HubDiscoverOptions,
45
- HubOrientOptions,
46
- HubOrientResult,
47
- HubThread,
48
- HubMessage,
49
- HubThreadContext,
50
- HubProposal,
51
- HubView,
52
- HubSearchResult,
53
- HubCommand,
54
- HubAgentUser,
55
- HubUserContext,
56
- HubGovernanceResult,
57
- CreateThreadInput,
58
- CreateRelationInput,
59
- AttachFacetInput,
60
- HubAttachFacetResult,
61
- CreateViewInput,
62
- UpdateViewInput,
63
- ArrangeBentoViewInput,
64
- HubBentoArrangementResult,
65
- ExecuteCommandInput,
66
- CreateDocumentInput,
67
- UpdateDocumentInput,
68
- CreateDocumentProposalInput,
69
- HubDocumentProposalResult,
70
- HubCapability,
71
- HubCapabilityCatalogResult,
72
- HubRunnableCapabilityActionsResult,
73
- ExecuteCapabilityInput,
74
- ExecuteCapabilityResult,
75
- ListAgentSkillsOptions,
76
- HubAgentSkillsResult,
77
- HubAgentSkill,
78
- GetCapabilityBriefsInput,
79
- HubCapabilityBriefsResult,
80
- SubmitCaptureGraphInput,
81
- SubmitCaptureGraphResult,
82
- HubAutomation,
83
- CreateAutomationInput,
84
- UpdateAutomationInput,
85
- AutomationStatus,
86
- ReactionKind,
87
- ReactionLens,
88
- HubReactionEvent,
89
- CreateNotificationInput,
90
- HubWebhookDelivery,
91
- } from "./types.js";
92
-
93
- export interface HubRestClientConfig {
94
- /** Pod URL, e.g. https://my-pod.synap.live */
95
- podUrl: string;
96
- /** Hub Protocol API key (Bearer token) */
97
- apiKey: string;
98
- /** Default workspace ID — used when not specified per call */
99
- workspaceId?: string;
100
- /** Optional request timeout in ms (default: 30000). Fallback when read/write timeouts are unset. */
101
- timeoutMs?: number;
102
- /** Optional read (GET) timeout in ms (default: timeoutMs ?? 30000). */
103
- readTimeoutMs?: number;
104
- /** Optional write (non-GET) timeout in ms (default: timeoutMs ?? 30000). */
105
- writeTimeoutMs?: number;
106
- /**
107
- * Max attempts for a request (default: 3). Retries ONLY on network failure or
108
- * 5xx — never on 4xx, never on a caller-provided abort. Set to 1 to disable.
109
- */
110
- maxAttempts?: number;
111
- }
112
-
113
- function normalizeUrl(url: string): string {
114
- return url.replace(/\/$/, "");
115
- }
116
-
117
- function formatHubErrorMessage(
118
- status: number,
119
- statusText: string,
120
- errorBody: unknown
121
- ): string {
122
- let detail = "";
123
- if (errorBody && typeof errorBody === "object" && "error" in errorBody) {
124
- detail = String((errorBody as { error: unknown }).error);
125
- }
126
- const base = `Hub API error: ${status} ${statusText}`;
127
- let msg = detail ? `${base} — ${detail}` : base;
128
- if (status === 403 && /hub-protocol\.write/i.test(detail)) {
129
- msg +=
130
- " Create or reconnect an API key that includes the hub-protocol.write scope (Settings → API keys on your pod).";
131
- }
132
- return msg;
133
- }
134
-
135
- function unwrapList<T>(result: T[] | HubListResponse<T>): T[] {
136
- return Array.isArray(result)
137
- ? result
138
- : ((result as HubListResponse<T>).data ?? []);
139
- }
140
-
141
- /** Hub GET /workspaces returns `{ workspaces }`, not `{ data }`. */
142
- function unwrapWorkspacesResponse(
143
- result:
144
- HubWorkspace[] | HubListResponse<HubWorkspace> | HubWorkspacesListResponse
145
- ): HubWorkspace[] {
146
- if (Array.isArray(result)) return result;
147
- if (result && typeof result === "object" && "workspaces" in result) {
148
- const w = (result as HubWorkspacesListResponse).workspaces;
149
- return Array.isArray(w) ? w : [];
150
- }
151
- return unwrapList(result as HubWorkspace[] | HubListResponse<HubWorkspace>);
152
- }
153
-
154
- function unwrapSingle<T>(result: T | HubSingleResponse<T>): T {
155
- if (result && typeof result === "object" && "data" in result) {
156
- return (result as HubSingleResponse<T>).data;
157
- }
158
- return result as T;
159
- }
160
-
161
- export class HubRestClient {
162
- private readonly base: string;
163
- private readonly headers: Record<string, string>;
164
- private readonly timeoutMs: number;
165
- private readonly readTimeoutMs: number;
166
- private readonly writeTimeoutMs: number;
167
- private readonly maxAttempts: number;
168
- readonly workspaceId: string | undefined;
169
-
170
- /** Cached from GET /users/me — avoids repeated identity calls. */
171
- private resolvedUserId: string | null = null;
172
-
173
- constructor(config: HubRestClientConfig) {
174
- this.base = normalizeUrl(config.podUrl);
175
- this.headers = {
176
- Authorization: `Bearer ${config.apiKey}`,
177
- "Content-Type": "application/json",
178
- };
179
- this.workspaceId = config.workspaceId;
180
- this.timeoutMs = config.timeoutMs ?? 30_000;
181
- this.readTimeoutMs = config.readTimeoutMs ?? this.timeoutMs;
182
- this.writeTimeoutMs = config.writeTimeoutMs ?? this.timeoutMs;
183
- this.maxAttempts = Math.max(1, config.maxAttempts ?? 3);
184
- }
185
-
186
- /** User id for the current API key (Hub REST requires userId on several GETs). */
187
- private async resolveUserId(): Promise<string> {
188
- if (this.resolvedUserId) return this.resolvedUserId;
189
- const me = await this.getMe();
190
- this.resolvedUserId = me.id;
191
- return me.id;
192
- }
193
-
194
- /**
195
- * The ONE shared request loop. Per-method timeout (GET = read, else write, or a
196
- * caller override) + up to `maxAttempts` with exponential backoff. Retries ONLY
197
- * on a network failure or 5xx; NEVER on a 4xx or a caller abort. Returns the raw
198
- * `Response` for any non-5xx (ok OR 4xx) — the typed entry points below decide
199
- * how to interpret it. This is the single source of retry/timeout truth, shared
200
- * by the CLI and the IS's `ISHubClient` (which reuses the protected entry points
201
- * rather than re-implementing fetch).
202
- */
203
- private async fetchWithRetry(
204
- method: string,
205
- path: string,
206
- body?: unknown,
207
- signal?: AbortSignal,
208
- timeoutMsOverride?: number
209
- ): Promise<Response> {
210
- const url = `${this.base}${path}`;
211
- const perAttemptTimeout =
212
- timeoutMsOverride ??
213
- (method.toUpperCase() === "GET"
214
- ? this.readTimeoutMs
215
- : this.writeTimeoutMs);
216
-
217
- let lastError: unknown;
218
- for (let attempt = 0; attempt < this.maxAttempts; attempt++) {
219
- if (attempt > 0) {
220
- await new Promise((r) => setTimeout(r, 1_000 * attempt)); // 0, 1s, 2s, …
221
- }
222
- const timeout = AbortSignal.timeout(perAttemptTimeout);
223
- const combined = signal ? AbortSignal.any([signal, timeout]) : timeout;
224
- try {
225
- const res = await fetch(url, {
226
- method,
227
- headers: this.headers,
228
- body: body !== undefined ? JSON.stringify(body) : undefined,
229
- signal: combined,
230
- });
231
- if (res.status < 500) return res; // ok or 4xx — caller decides; never retry
232
- lastError = new Error(`HTTP ${res.status}`); // 5xx — retry until exhausted
233
- } catch (err) {
234
- if (signal?.aborted) throw err; // caller asked to abort — honor it
235
- lastError = err; // network/abort-timeout — retry
236
- }
237
- }
238
- throw lastError;
239
- }
240
-
241
- /** Build a HubApiError from a non-ok Response (reads the JSON error body). */
242
- private async toHubError(res: Response): Promise<HubApiError> {
243
- const errorBody = await res.json().catch(() => ({}));
244
- return new HubApiError(
245
- formatHubErrorMessage(res.status, res.statusText, errorBody),
246
- res.status,
247
- errorBody
248
- );
249
- }
250
-
251
- /** Parse a 2xx body, tolerating an empty/204 response (returns undefined). */
252
- private async parseBody<T>(res: Response): Promise<T> {
253
- const text = await res.text();
254
- return (text ? JSON.parse(text) : undefined) as T;
255
- }
256
-
257
- /**
258
- * Typed JSON request — throws `HubApiError` on any non-2xx. Protected so the IS
259
- * subclass reuses it. Tolerates an empty/204 body (returns `undefined`).
260
- */
261
- protected async request<T>(
262
- method: string,
263
- path: string,
264
- body?: unknown,
265
- signal?: AbortSignal
266
- ): Promise<T> {
267
- const res = await this.fetchWithRetry(method, path, body, signal);
268
- if (!res.ok) throw await this.toHubError(res);
269
- return this.parseBody<T>(res);
270
- }
271
-
272
- /**
273
- * Like `request<T>` but returns `null` on 404/403 (the "absent/forbidden →
274
- * empty" contract several IS reads use) instead of throwing.
275
- */
276
- protected async requestOrNull<T>(
277
- method: string,
278
- path: string,
279
- body?: unknown,
280
- signal?: AbortSignal
281
- ): Promise<T | null> {
282
- const res = await this.fetchWithRetry(method, path, body, signal);
283
- if (res.status === 404 || res.status === 403) return null;
284
- if (!res.ok) throw await this.toHubError(res);
285
- return this.parseBody<T | null>(res);
286
- }
287
-
288
- /**
289
- * The raw `Response` (same retry/timeout infra), for the few callers that read
290
- * `.text()`, branch on status themselves, or need a per-call timeout override.
291
- */
292
- protected async requestRaw(
293
- method: string,
294
- path: string,
295
- body?: unknown,
296
- signal?: AbortSignal,
297
- timeoutMsOverride?: number
298
- ): Promise<Response> {
299
- return this.fetchWithRetry(method, path, body, signal, timeoutMsOverride);
300
- }
301
-
302
- // ─── Identity ─────────────────────────────────────────────────────────────
303
-
304
- async getMe(): Promise<HubUser> {
305
- return this.request<HubUser>("GET", "/api/hub/users/me");
306
- }
307
-
308
- async getWorkspaces(): Promise<HubWorkspace[]> {
309
- const result = await this.request<
310
- HubWorkspace[] | HubListResponse<HubWorkspace> | HubWorkspacesListResponse
311
- >("GET", "/api/hub/workspaces");
312
- return unwrapWorkspacesResponse(result);
313
- }
314
-
315
- async provisionAgentWorkspace(input: {
316
- agentUserId: string;
317
- workspaceName?: string;
318
- }): Promise<{ workspaceId: string; created: boolean }> {
319
- return this.request<{ workspaceId: string; created: boolean }>(
320
- "POST",
321
- "/api/hub/workspaces/provision-agent",
322
- input
323
- );
324
- }
325
-
326
- /**
327
- * Get full activity context for a user — recent entities, active threads, workspace summary.
328
- * Use at session start to orient the agent to the user's current state.
329
- */
330
- async getUserContext(
331
- userId: string,
332
- options?: { workspaceId?: string }
333
- ): Promise<HubUserContext> {
334
- const params = new URLSearchParams();
335
- const wsId = options?.workspaceId ?? this.workspaceId;
336
- if (wsId) params.set("workspaceId", wsId);
337
- const qs = params.toString() ? `?${params}` : "";
338
- return this.request<HubUserContext>(
339
- "GET",
340
- `/api/hub/users/${userId}/context${qs}`
341
- );
342
- }
343
-
344
- // ─── Entities ─────────────────────────────────────────────────────────────
345
-
346
- async searchEntities(
347
- query: string,
348
- options?: {
349
- profileSlug?: string;
350
- workspaceId?: string;
351
- /**
352
- * "workspace" (default) — applies the client workspaceId filter.
353
- * "all" — omits workspaceId entirely so results span all workspaces.
354
- */
355
- scope?: "workspace" | "all";
356
- limit?: number;
357
- },
358
- signal?: AbortSignal
359
- ): Promise<HubEntity[]> {
360
- const params = new URLSearchParams({ q: query });
361
- if (options?.profileSlug) params.set("profileSlug", options.profileSlug);
362
- // When scope === "all", intentionally omit workspaceId for cross-workspace search.
363
- if (options?.scope !== "all") {
364
- const wsId = options?.workspaceId ?? this.workspaceId;
365
- if (wsId) params.set("workspaceId", wsId);
366
- }
367
- if (options?.limit) params.set("limit", String(options.limit));
368
-
369
- const result = await this.request<HubEntity[] | HubListResponse<HubEntity>>(
370
- "GET",
371
- `/api/hub/entities?${params}`,
372
- undefined,
373
- signal
374
- );
375
- return unwrapList(result);
376
- }
377
-
378
- async getEntity(id: string): Promise<HubEntity> {
379
- const result = await this.request<HubEntity | HubSingleResponse<HubEntity>>(
380
- "GET",
381
- `/api/hub/entities/${id}`
382
- );
383
- return unwrapSingle(result);
384
- }
385
-
386
- async getRecentEntities(options?: {
387
- profileSlug?: string;
388
- workspaceId?: string;
389
- limit?: number;
390
- /** "all" — omits workspaceId so results span all workspaces the user can access. */
391
- scope?: "workspace" | "all";
392
- }): Promise<HubEntity[]> {
393
- const params = new URLSearchParams({
394
- sort: "updatedAt:desc",
395
- limit: String(options?.limit ?? 20),
396
- });
397
- if (options?.profileSlug) params.set("profileSlug", options.profileSlug);
398
- if (options?.scope !== "all") {
399
- const wsId = options?.workspaceId ?? this.workspaceId;
400
- if (wsId) params.set("workspaceId", wsId);
401
- }
402
-
403
- const result = await this.request<HubEntity[] | HubListResponse<HubEntity>>(
404
- "GET",
405
- `/api/hub/entities?${params}`
406
- );
407
- return unwrapList(result);
408
- }
409
-
410
- async createEntity(input: CreateEntityInput): Promise<HubGovernanceResult> {
411
- const { content, url, status, priority, dueDate, properties, ...rest } =
412
- input;
413
- return this.request<HubGovernanceResult>("POST", "/api/hub/entities", {
414
- ...rest,
415
- // Entity placement is a write decision, never an ambient client default.
416
- // Omitted means pod/base behavior; an explicit workspace opts into its
417
- // overlay/membership lens. This deliberately differs from read helpers.
418
- ...(rest.workspaceId ? { workspaceId: rest.workspaceId } : {}),
419
- ...(content !== undefined ? { content } : {}),
420
- properties: {
421
- ...properties,
422
- ...(url !== undefined ? { url } : {}),
423
- ...(status !== undefined ? { status } : {}),
424
- ...(priority !== undefined ? { priority } : {}),
425
- ...(dueDate !== undefined ? { dueDate } : {}),
426
- },
427
- });
428
- }
429
-
430
- async updateEntity(
431
- id: string,
432
- input: UpdateEntityInput
433
- ): Promise<HubEntity | HubGovernanceResult> {
434
- // Backend may return a full entity (approved) or a governance envelope
435
- // (proposed/denied). Callers MUST check `status` first when governance
436
- // is likely — e.g., agent-owned workspaces, destructive updates.
437
- const { properties, content, url, status, priority, dueDate, ...rest } =
438
- input;
439
- return this.request<HubEntity | HubGovernanceResult>(
440
- "PATCH",
441
- `/api/hub/entities/${id}`,
442
- {
443
- ...rest,
444
- metadata: {
445
- ...properties,
446
- ...(content !== undefined ? { content } : {}),
447
- ...(url !== undefined ? { url } : {}),
448
- ...(status !== undefined ? { status } : {}),
449
- ...(priority !== undefined ? { priority } : {}),
450
- ...(dueDate !== undefined ? { dueDate } : {}),
451
- },
452
- }
453
- );
454
- }
455
-
456
- // ─── Unified Search ───────────────────────────────────────────────────────
457
-
458
- /**
459
- * Unified full-text search across entities, documents, and views.
460
- * Use when you don't know the content type. For entity-only search use searchEntities().
461
- *
462
- * Note: The backend GET /search requires userId as a query param; this method resolves
463
- * the current user automatically.
464
- */
465
- async search(
466
- query: string,
467
- options?: {
468
- collections?: Array<"entities" | "documents" | "views">;
469
- workspaceId?: string;
470
- limit?: number;
471
- },
472
- signal?: AbortSignal
473
- ): Promise<HubSearchResult> {
474
- const userId = await this.resolveUserId();
475
- const wsId = options?.workspaceId ?? this.workspaceId;
476
- const params = new URLSearchParams({ userId, query });
477
- if (wsId) params.set("workspaceId", wsId);
478
- if (options?.collections?.length)
479
- params.set("collections", options.collections.join(","));
480
- if (options?.limit) params.set("limit", String(options.limit));
481
- return this.request<HubSearchResult>(
482
- "GET",
483
- `/api/hub/search?${params}`,
484
- undefined,
485
- signal
486
- );
487
- }
488
-
489
- // ─── Relations & Graph ────────────────────────────────────────────────────
490
-
491
- /**
492
- * Get all relations for an entity — inbound and outbound.
493
- * Use to discover connections before graph traversal.
494
- *
495
- * Note: The backend GET /relations requires both userId and workspaceId.
496
- * This method resolves userId automatically; workspaceId falls back to client default.
497
- */
498
- async getRelations(
499
- entityId: string,
500
- options?: { workspaceId?: string }
501
- ): Promise<HubRelation[]> {
502
- const userId = await this.resolveUserId();
503
- const wsId = options?.workspaceId ?? this.workspaceId;
504
- if (!wsId) throw new Error("workspaceId is required for getRelations");
505
- const params = new URLSearchParams({ userId, workspaceId: wsId, entityId });
506
- const result = await this.request<
507
- HubRelation[] | HubListResponse<HubRelation>
508
- >("GET", `/api/hub/relations?${params}`);
509
- return unwrapList(result);
510
- }
511
-
512
- /**
513
- * Create a typed relation between two entities.
514
- * Type is a free string — conventions: "related_to", "parent_of", "child_of",
515
- * "belongs_to", "authored_by", "depends_on", "references".
516
- * Goes through governance — may return "proposed".
517
- */
518
- async createRelation(
519
- input: CreateRelationInput
520
- ): Promise<HubGovernanceResult> {
521
- const userId = input.userId ?? (await this.resolveUserId());
522
- const wsId = input.workspaceId ?? this.workspaceId;
523
- if (!wsId) throw new Error("workspaceId is required for createRelation");
524
- return this.request<HubGovernanceResult>("POST", "/api/hub/relations", {
525
- userId,
526
- workspaceId: wsId,
527
- sourceEntityId: input.sourceEntityId,
528
- targetEntityId: input.targetEntityId,
529
- type: input.type,
530
- });
531
- }
532
-
533
- /**
534
- * Attach a role-profile through the canonical governed facet door. A result
535
- * may be `proposed`; callers must surface its review information instead of
536
- * claiming the role was applied.
537
- */
538
- async attachFacet(input: AttachFacetInput): Promise<HubAttachFacetResult> {
539
- const userId = await this.resolveUserId();
540
- return this.request<HubAttachFacetResult>(
541
- "POST",
542
- `/api/hub/entities/${input.entityId}/facets`,
543
- {
544
- userId,
545
- profileSlug: input.profileSlug,
546
- profileId: input.profileId,
547
- workspaceId: input.workspaceId ?? this.workspaceId,
548
- contextEntityId: input.contextEntityId,
549
- status: input.status,
550
- properties: input.properties,
551
- reasoning: input.reasoning,
552
- }
553
- );
554
- }
555
-
556
- /**
557
- * Delete a relation by ID (get from getRelations()).
558
- */
559
- async deleteRelation(relationId: string): Promise<void> {
560
- const userId = await this.resolveUserId();
561
- await this.request<unknown>("DELETE", `/api/hub/relations/${relationId}`, {
562
- userId,
563
- });
564
- }
565
-
566
- /**
567
- * Traverse the knowledge graph from an entity using BFS.
568
- * Returns nodes and edges up to maxDepth hops away.
569
- * maxDepth: 1=direct neighbors, 2=neighborhood (recommended), 3=extended (expensive).
570
- *
571
- * @example
572
- * const graph = await client.traverseGraph(projectId, { maxDepth: 2 });
573
- * const tasks = graph.nodes.filter(n => n.profileSlug === "task");
574
- */
575
- async traverseGraph(
576
- entityId: string,
577
- options?: { maxDepth?: number; workspaceId?: string }
578
- ): Promise<HubGraphResult> {
579
- const userId = await this.resolveUserId();
580
- const params = new URLSearchParams({
581
- userId,
582
- startEntityId: entityId,
583
- maxDepth: String(options?.maxDepth ?? 2),
584
- });
585
- const wsId = options?.workspaceId ?? this.workspaceId;
586
- if (wsId) params.set("workspaceId", wsId);
587
- return this.request<HubGraphResult>(
588
- "GET",
589
- `/api/hub/graph/traverse?${params}`
590
- );
591
- }
592
-
593
- /**
594
- * Unified view of everything connected to an entity across the local graph:
595
- * 1. Graph relations — explicit rows in the relations table (both directions)
596
- * 2. Structural links — inbound and outbound `entity_id` property edges
597
- * 3. Channel and focus-session connections around this entity
598
- *
599
- * Prefer this over `getRelations()` / `traverseGraph()` when you want the complete
600
- * picture — those only see the relations table and miss property-based links that
601
- * haven't been synced (notably custom profiles without a `relationDefId` mapping).
602
- *
603
- * Each connection carries a `source` field so callers can filter by origin.
604
- *
605
- * @example
606
- * const { connections } = await client.getConnections(entityId);
607
- * const tasks = connections.filter(c => c.entity?.profileSlug === "task");
608
- */
609
- async getConnections(
610
- entityId: string,
611
- options?: { workspaceId?: string; limit?: number }
612
- ): Promise<HubConnectionsResult> {
613
- const userId = await this.resolveUserId();
614
- const wsId = options?.workspaceId ?? this.workspaceId;
615
- const params = new URLSearchParams({ userId });
616
- if (wsId) params.set("workspaceId", wsId);
617
- if (options?.limit) params.set("limit", String(options.limit));
618
- return this.request<HubConnectionsResult>(
619
- "GET",
620
- `/api/hub/entities/${entityId}/connections?${params}`
621
- );
622
- }
623
-
624
- // ─── Session orientation & profile discovery ─────────────────────────────
625
-
626
- /**
627
- * Canonical session bootstrap shared by the MCP, CLI, and external surfaces.
628
- * It is deliberately a lens map, not a profile/schema dump; use discover()
629
- * only for the selected profiles needed by the next action.
630
- */
631
- async orient(options?: HubOrientOptions): Promise<HubOrientResult> {
632
- const params = new URLSearchParams();
633
- if (options?.detail) params.set("detail", options.detail);
634
- if (options?.scope?.length) params.set("scope", options.scope.join(","));
635
- if (options?.workspaceId) params.set("workspaceId", options.workspaceId);
636
- if (options?.projectId) params.set("projectId", options.projectId);
637
- const qs = params.toString() ? `?${params}` : "";
638
- return this.request<HubOrientResult>("GET", `/api/hub/orient${qs}`);
639
- }
640
-
641
- // ─── Profiles & Schema ────────────────────────────────────────────────────
642
-
643
- /**
644
- * List all entity profile types in the workspace.
645
- * Always call before creating entities to discover what types are available.
646
- * Returns system profiles (always present) + custom workspace profiles.
647
- */
648
- async listProfiles(
649
- workspaceId: string,
650
- options?: { detail?: "full" }
651
- ): Promise<HubProfile[]> {
652
- const userId = await this.resolveUserId();
653
- const params = new URLSearchParams({ userId, workspaceId });
654
- if (options?.detail) params.set("detail", options.detail);
655
- const result = await this.request<
656
- HubProfile[] | HubListResponse<HubProfile>
657
- >("GET", `/api/hub/profiles?${params}`);
658
- return unwrapList(result);
659
- }
660
-
661
- /**
662
- * List property definitions for a workspace, optionally filtered by profile.
663
- */
664
- async listPropertyDefs(
665
- workspaceId: string,
666
- options?: { profileSlug?: string }
667
- ): Promise<HubPropertyDef[]> {
668
- const userId = await this.resolveUserId();
669
- const params = new URLSearchParams({ userId, workspaceId });
670
- if (options?.profileSlug) params.set("profileId", options.profileSlug);
671
- const result = await this.request<
672
- HubPropertyDef[] | HubListResponse<HubPropertyDef>
673
- >("GET", `/api/hub/property-defs?${params}`);
674
- return unwrapList(result);
675
- }
676
-
677
- /**
678
- * Runtime discovery — profiles with property schemas + command tree.
679
- *
680
- * Call once per session at session start. Returns ground-truth profile
681
- * schemas (including custom workspace profiles) and the canonical CLI
682
- * command map. Replaces static skill file profile descriptions.
683
- */
684
- async discover(
685
- options?: string | HubDiscoverOptions
686
- ): Promise<HubDiscoverResult> {
687
- const userId = await this.resolveUserId();
688
- const normalized =
689
- typeof options === "string" ? { workspaceId: options } : (options ?? {});
690
- const params = new URLSearchParams({ userId });
691
- // No configured fallback: an omitted workspace asks for the base schema,
692
- // while an explicit one resolves only that workspace's overlays.
693
- if (normalized.workspaceId)
694
- params.set("workspaceId", normalized.workspaceId);
695
- if (normalized.summary !== undefined)
696
- params.set("summary", String(normalized.summary));
697
- if (normalized.profileSlugs?.length)
698
- params.set("profileSlugs", normalized.profileSlugs.join(","));
699
- return this.request<HubDiscoverResult>(
700
- "GET",
701
- `/api/hub/discover?${params}`
702
- );
703
- }
704
-
705
- // ─── Threads & Channels ───────────────────────────────────────────────────
706
-
707
- /**
708
- * List threads (channels) accessible to a user.
709
- */
710
- async listThreads(
711
- userId: string,
712
- options?: { workspaceId?: string; type?: string }
713
- ): Promise<HubThread[]> {
714
- const wsId = options?.workspaceId ?? this.workspaceId;
715
- const params = new URLSearchParams({ userId });
716
- if (wsId) params.set("workspaceId", wsId);
717
- if (options?.type) params.set("type", options.type);
718
- const result = await this.request<HubThread[] | HubListResponse<HubThread>>(
719
- "GET",
720
- `/api/hub/threads?${params}`
721
- );
722
- return unwrapList(result);
723
- }
724
-
725
- /**
726
- * Get the user's personal channel — their private AI conversation thread.
727
- * Use as default destination for messages and proactive posts.
728
- *
729
- * Note: The backend GET /channels/personal requires both userId and workspaceId.
730
- */
731
- async getPersonalChannel(
732
- userId: string,
733
- workspaceId?: string
734
- ): Promise<HubThread> {
735
- const wsId = workspaceId ?? this.workspaceId;
736
- if (!wsId)
737
- throw new Error("workspaceId is required for getPersonalChannel");
738
- const params = new URLSearchParams({ userId, workspaceId: wsId });
739
- return this.request<HubThread>(
740
- "GET",
741
- `/api/hub/channels/personal?${params}`
742
- );
743
- }
744
-
745
- /**
746
- * Create a new thread. Pass entityId to auto-link on creation.
747
- *
748
- * Note: The backend POST /threads requires workspaceId in the body.
749
- */
750
- async createThread(input: CreateThreadInput): Promise<HubThread> {
751
- const userId = input.userId ?? (await this.resolveUserId());
752
- const wsId = input.workspaceId ?? this.workspaceId;
753
- if (!wsId) throw new Error("workspaceId is required for createThread");
754
- return this.request<HubThread>("POST", "/api/hub/threads", {
755
- userId,
756
- workspaceId: wsId,
757
- title: input.name,
758
- agentType: input.agentType,
759
- contextObjectType: input.entityId
760
- ? "entity"
761
- : input.documentId
762
- ? "document"
763
- : undefined,
764
- contextObjectId: input.entityId ?? input.documentId,
765
- });
766
- }
767
-
768
- /**
769
- * Get full thread context: messages + all linked entities and documents.
770
- * Call before sending a message to orient the AI with conversation history.
771
- */
772
- async getThreadContext(threadId: string): Promise<HubThreadContext> {
773
- return this.request<HubThreadContext>(
774
- "GET",
775
- `/api/hub/threads/${threadId}/context`
776
- );
777
- }
778
-
779
- /**
780
- * Get messages in a thread.
781
- */
782
- async getMessages(
783
- threadId: string,
784
- _options?: { limit?: number; before?: string }
785
- ): Promise<HubMessage[]> {
786
- // The backend GET /threads/:threadId/messages does not accept query params in
787
- // the current implementation — returns all messages ordered by timestamp.
788
- const result = await this.request<
789
- HubMessage[] | HubListResponse<HubMessage>
790
- >("GET", `/api/hub/threads/${threadId}/messages`);
791
- return unwrapList(result);
792
- }
793
-
794
- /**
795
- * Link an entity to a thread so it appears in thread context for AI.
796
- */
797
- async linkEntityToThread(threadId: string, entityId: string): Promise<void> {
798
- const userId = await this.resolveUserId();
799
- await this.request<unknown>(
800
- "POST",
801
- `/api/hub/threads/${threadId}/link-entity`,
802
- { userId, entityId }
803
- );
804
- }
805
-
806
- /**
807
- * Link a document to a thread.
808
- */
809
- async linkDocumentToThread(
810
- threadId: string,
811
- documentId: string
812
- ): Promise<void> {
813
- const userId = await this.resolveUserId();
814
- await this.request<unknown>(
815
- "POST",
816
- `/api/hub/threads/${threadId}/link-document`,
817
- { userId, documentId }
818
- );
819
- }
820
-
821
- /**
822
- * Get research branches of a thread — parallel AI investigations.
823
- */
824
- async getThreadBranches(
825
- threadId: string
826
- ): Promise<
827
- Array<{ channelId: string; branchPurpose: string | null; status: string }>
828
- > {
829
- const result = await this.request<{
830
- branches: Array<{
831
- channelId: string;
832
- branchPurpose: string | null;
833
- status: string;
834
- }>;
835
- }>("GET", `/api/hub/threads/${threadId}/branches`);
836
- return result.branches ?? [];
837
- }
838
-
839
- // ─── Memory ───────────────────────────────────────────────────────────────
840
-
841
- async storeMemory(input: StoreMemoryInput): Promise<{ id: string }> {
842
- const userId = await this.resolveUserId();
843
- const fact =
844
- input.context && String(input.context).trim().length > 0
845
- ? `[${String(input.context).trim()}] ${input.fact}`
846
- : input.fact;
847
- return this.request<{ id: string }>("POST", "/api/hub/memory", {
848
- userId,
849
- fact,
850
- });
851
- }
852
-
853
- async recallMemory(
854
- query: string,
855
- options?: { workspaceId?: string; limit?: number }
856
- ): Promise<HubMemoryResult[]> {
857
- const wsId = options?.workspaceId ?? this.workspaceId;
858
- const userId = await this.resolveUserId();
859
- const params = new URLSearchParams({
860
- userId,
861
- query,
862
- limit: String(options?.limit ?? 10),
863
- });
864
- if (wsId) params.set("workspaceId", wsId);
865
-
866
- const result = await this.request<
867
- HubMemoryResult[] | HubListResponse<HubMemoryResult>
868
- >("GET", `/api/hub/memory?${params}`);
869
- return unwrapList(result);
870
- }
871
-
872
- /**
873
- * Delete a stored memory fact by ID.
874
- */
875
- async deleteMemory(memoryId: string): Promise<void> {
876
- const userId = await this.resolveUserId();
877
- const params = new URLSearchParams({ userId });
878
- await this.request<unknown>(
879
- "DELETE",
880
- `/api/hub/memory/${memoryId}?${params}`
881
- );
882
- }
883
-
884
- // ─── Channels (Hub REST: channels are listed via GET /threads) ────────────
885
-
886
- async getChannels(options?: { workspaceId?: string }): Promise<HubChannel[]> {
887
- const wsId = options?.workspaceId ?? this.workspaceId;
888
- const userId = await this.resolveUserId();
889
- const params = new URLSearchParams({ userId });
890
- if (wsId) params.set("workspaceId", wsId);
891
-
892
- const result = await this.request<
893
- HubChannel[] | HubListResponse<HubChannel>
894
- >("GET", `/api/hub/threads?${params}`);
895
- return unwrapList(result);
896
- }
897
-
898
- async sendToChannel(input: SendToChannelInput): Promise<{ id: string }> {
899
- const userId = input.userId ?? (await this.resolveUserId());
900
- return this.request<{ id: string }>(
901
- "POST",
902
- `/api/hub/threads/${input.channelId}/messages`,
903
- {
904
- role: input.role ?? "user",
905
- content: input.content,
906
- userId,
907
- ...(input.autoRespond !== undefined
908
- ? { autoRespond: input.autoRespond }
909
- : {}),
910
- }
911
- );
912
- }
913
-
914
- // ─── Proposals ────────────────────────────────────────────────────────────
915
-
916
- /**
917
- * List proposals — pending AI writes awaiting human review.
918
- * Filter by status: "pending" (needs review), "approved", "rejected".
919
- */
920
- async listProposals(options?: {
921
- status?: "pending" | "approved" | "rejected";
922
- workspaceId?: string;
923
- /**
924
- * "workspace" (default) — applies the client workspaceId filter.
925
- * "all" — omits workspaceId so results span every workspace the user can see.
926
- */
927
- scope?: "workspace" | "all";
928
- limit?: number;
929
- }): Promise<HubProposal[]> {
930
- const userId = await this.resolveUserId();
931
- const params = new URLSearchParams({ userId });
932
- // When scope === "all", intentionally omit workspaceId — matches searchEntities/
933
- // getRecentEntities so a "review everything" caller isn't silently narrowed to
934
- // just the connection's default workspace.
935
- if (options?.scope !== "all") {
936
- const wsId = options?.workspaceId ?? this.workspaceId;
937
- if (wsId) params.set("workspaceId", wsId);
938
- }
939
- if (options?.status) params.set("status", options.status);
940
- if (options?.limit) params.set("limit", String(options.limit));
941
- const result = await this.request<
942
- HubProposal[] | HubListResponse<HubProposal>
943
- >("GET", `/api/hub/proposals?${params}`);
944
- return unwrapList(result);
945
- }
946
-
947
- /**
948
- * Approve or reject a proposal.
949
- *
950
- * Note: The backend PATCH /proposals/:id is an AI-revision endpoint that updates
951
- * the proposal data/summary, not a review (approve/reject) endpoint.
952
- * Use this to update proposal data before human review.
953
- */
954
- async reviewProposal(
955
- proposalId: string,
956
- decision: "approved" | "rejected",
957
- reason?: string
958
- ): Promise<HubProposal> {
959
- return this.request<HubProposal>(
960
- "PATCH",
961
- `/api/hub/proposals/${proposalId}`,
962
- {
963
- data: { status: decision },
964
- summary: reason,
965
- }
966
- );
967
- }
968
-
969
- // ─── Views ────────────────────────────────────────────────────────────────
970
-
971
- /**
972
- * List data views in a workspace.
973
- */
974
- async listViews(
975
- workspaceId: string,
976
- options?: { profileSlug?: string }
977
- ): Promise<HubView[]> {
978
- const userId = await this.resolveUserId();
979
- const params = new URLSearchParams({ userId, workspaceId });
980
- if (options?.profileSlug) params.set("profileId", options.profileSlug);
981
- const result = await this.request<HubView[] | HubListResponse<HubView>>(
982
- "GET",
983
- `/api/hub/views?${params}`
984
- );
985
- return unwrapList(result);
986
- }
987
-
988
- /**
989
- * Create a new view. Goes through governance.
990
- */
991
- async createView(input: CreateViewInput): Promise<HubGovernanceResult> {
992
- const userId = input.userId ?? (await this.resolveUserId());
993
- return this.request<HubGovernanceResult>("POST", "/api/hub/views", {
994
- userId,
995
- workspaceId: input.workspaceId ?? this.workspaceId,
996
- name: input.name,
997
- type: input.type,
998
- profileId: input.profileSlug,
999
- config: input.config,
1000
- metadata: input.metadata,
1001
- agentUserId: input.agentUserId,
1002
- reasoning: input.reasoning,
1003
- sourceMessageId: input.sourceMessageId,
1004
- });
1005
- }
1006
-
1007
- /** Update a view through the existing governed Hub route. */
1008
- async updateView(
1009
- viewId: string,
1010
- input: UpdateViewInput
1011
- ): Promise<HubView | HubGovernanceResult> {
1012
- const userId = input.userId ?? (await this.resolveUserId());
1013
- return this.request<HubView | HubGovernanceResult>(
1014
- "PATCH",
1015
- `/api/hub/views/${viewId}`,
1016
- {
1017
- userId,
1018
- workspaceId: input.workspaceId ?? this.workspaceId,
1019
- name: input.name,
1020
- config: input.config,
1021
- metadata: input.metadata,
1022
- agentUserId: input.agentUserId,
1023
- reasoning: input.reasoning,
1024
- sourceMessageId: input.sourceMessageId,
1025
- }
1026
- );
1027
- }
1028
-
1029
- /** Replace a bento view's widget arrangement through the existing Hub route. */
1030
- async arrangeBentoView(
1031
- viewId: string,
1032
- input: ArrangeBentoViewInput
1033
- ): Promise<HubBentoArrangementResult> {
1034
- const userId = input.userId ?? (await this.resolveUserId());
1035
- const workspaceId = input.workspaceId ?? this.workspaceId;
1036
- if (!workspaceId) {
1037
- throw new Error("workspaceId is required for arrangeBentoView");
1038
- }
1039
- return this.request<HubBentoArrangementResult>(
1040
- "POST",
1041
- `/api/hub/views/${viewId}/arrange`,
1042
- {
1043
- userId,
1044
- workspaceId,
1045
- widgets: input.widgets,
1046
- agentUserId: input.agentUserId,
1047
- reasoning: input.reasoning,
1048
- sourceMessageId: input.sourceMessageId,
1049
- }
1050
- );
1051
- }
1052
-
1053
- // ─── Documents ────────────────────────────────────────────────────────────
1054
-
1055
- /**
1056
- * Get a document by ID with full markdown content.
1057
- */
1058
- async getDocument(documentId: string): Promise<HubDocument> {
1059
- const userId = await this.resolveUserId();
1060
- const params = new URLSearchParams({ userId });
1061
- const result = await this.request<HubDocument | { document: HubDocument }>(
1062
- "GET",
1063
- `/api/hub/documents/${documentId}?${params}`
1064
- );
1065
- return "document" in result ? result.document : result;
1066
- }
1067
-
1068
- /**
1069
- * Create a document. Use for long-form content: meeting notes, research, writeups.
1070
- * Goes through governance.
1071
- */
1072
- async createDocument(
1073
- input: CreateDocumentInput & { workspaceId?: string }
1074
- ): Promise<HubGovernanceResult> {
1075
- const userId = await this.resolveUserId();
1076
- return this.request<HubGovernanceResult>("POST", "/api/hub/documents", {
1077
- userId,
1078
- workspaceId: input.workspaceId ?? this.workspaceId,
1079
- title: input.title,
1080
- content: input.content ?? "",
1081
- type: input.type,
1082
- reasoning: input.reasoning,
1083
- agentUserId: input.agentUserId,
1084
- sourceMessageId: input.sourceMessageId,
1085
- sessionId: input.sessionId,
1086
- });
1087
- }
1088
-
1089
- /** Propose a full document-content replacement through the governed Hub route. */
1090
- async updateDocument(
1091
- documentId: string,
1092
- input: UpdateDocumentInput
1093
- ): Promise<HubDocumentProposalResult> {
1094
- const userId = await this.resolveUserId();
1095
- return this.request<HubDocumentProposalResult>(
1096
- "PATCH",
1097
- `/api/hub/documents/${documentId}`,
1098
- {
1099
- userId,
1100
- content: input.content,
1101
- title: input.title,
1102
- agentUserId: input.agentUserId,
1103
- sourceMessageId: input.sourceMessageId,
1104
- sessionId: input.sessionId,
1105
- }
1106
- );
1107
- }
1108
-
1109
- /** Submit a structured, reviewable document-edit proposal. */
1110
- async createDocumentProposal(
1111
- input: CreateDocumentProposalInput
1112
- ): Promise<HubDocumentProposalResult> {
1113
- const userId = await this.resolveUserId();
1114
- return this.request<HubDocumentProposalResult>(
1115
- "POST",
1116
- "/api/hub/documents/proposals",
1117
- {
1118
- userId,
1119
- ...input,
1120
- }
1121
- );
1122
- }
1123
-
1124
- // ─── Capabilities & teaching substrate ───────────────────────────────────
1125
-
1126
- /** Flat capability read-model. Prefer getCapabilityCatalog() for presentation. */
1127
- async listCapabilities(options?: {
1128
- workspaceId?: string;
1129
- }): Promise<HubCapability[]> {
1130
- const workspaceId = options?.workspaceId ?? this.workspaceId;
1131
- if (!workspaceId) {
1132
- throw new Error("workspaceId is required for listCapabilities");
1133
- }
1134
- const params = new URLSearchParams({ workspaceId });
1135
- const result = await this.request<{ capabilities: HubCapability[] }>(
1136
- "GET",
1137
- `/api/hub/capabilities?${params}`
1138
- );
1139
- return result.capabilities;
1140
- }
1141
-
1142
- /** Status-computed, pack-grouped capability catalog for every external surface. */
1143
- async getCapabilityCatalog(options?: {
1144
- workspaceId?: string;
1145
- extraKey?: string;
1146
- }): Promise<HubCapabilityCatalogResult> {
1147
- const workspaceId = options?.workspaceId ?? this.workspaceId;
1148
- if (!workspaceId) {
1149
- throw new Error("workspaceId is required for getCapabilityCatalog");
1150
- }
1151
- const params = new URLSearchParams({ workspaceId });
1152
- if (options?.extraKey) params.set("extraKey", options.extraKey);
1153
- return this.request<HubCapabilityCatalogResult>(
1154
- "GET",
1155
- `/api/hub/capabilities/catalog?${params}`
1156
- );
1157
- }
1158
-
1159
- /** List only approved, connected actions that this client can execute now. */
1160
- async listRunnableCapabilityActions(options?: {
1161
- workspaceId?: string;
1162
- query?: string;
1163
- kind?: string;
1164
- limit?: number;
1165
- }): Promise<HubRunnableCapabilityActionsResult> {
1166
- const workspaceId = options?.workspaceId ?? this.workspaceId;
1167
- if (!workspaceId) {
1168
- throw new Error(
1169
- "workspaceId is required for listRunnableCapabilityActions"
1170
- );
1171
- }
1172
- const params = new URLSearchParams({ workspaceId });
1173
- if (options?.query) params.set("query", options.query);
1174
- if (options?.kind) params.set("kind", options.kind);
1175
- if (options?.limit !== undefined)
1176
- params.set("limit", String(options.limit));
1177
- return this.request<HubRunnableCapabilityActionsResult>(
1178
- "GET",
1179
- `/api/hub/capabilities/actions?${params}`
1180
- );
1181
- }
1182
-
1183
- /** Run one registered capability through the shared governance gate. */
1184
- async executeCapability(
1185
- input: ExecuteCapabilityInput
1186
- ): Promise<ExecuteCapabilityResult> {
1187
- return this.request<ExecuteCapabilityResult>(
1188
- "POST",
1189
- "/api/hub/capabilities/execute",
1190
- {
1191
- ...input,
1192
- // Graph proposals follow the same explicit-scope rule as direct writes.
1193
- ...(input.workspaceId ? { workspaceId: input.workspaceId } : {}),
1194
- }
1195
- );
1196
- }
1197
-
1198
- /** List the compact system teaching catalog, or search the available skill index. */
1199
- async listAgentSkills(
1200
- options?: ListAgentSkillsOptions
1201
- ): Promise<HubAgentSkillsResult> {
1202
- const params = new URLSearchParams();
1203
- if (options?.topic) params.set("topic", options.topic);
1204
- if (options?.query) params.set("q", options.query);
1205
- if (options?.tag) params.set("tag", options.tag);
1206
- if (options?.system !== undefined)
1207
- params.set("system", String(options.system));
1208
- const workspaceId = options?.workspaceId ?? this.workspaceId;
1209
- if (workspaceId) params.set("workspaceId", workspaceId);
1210
- if (options?.limit !== undefined)
1211
- params.set("limit", String(options.limit));
1212
- if (options?.offset !== undefined)
1213
- params.set("offset", String(options.offset));
1214
- const qs = params.toString() ? `?${params}` : "";
1215
- return this.request<HubAgentSkillsResult>(
1216
- "GET",
1217
- `/api/hub/agent-skills${qs}`
1218
- );
1219
- }
1220
-
1221
- /** Load one skill body only when it is relevant to the agent's next action. */
1222
- async getAgentSkillBySlug(
1223
- slug: string,
1224
- options?: { workspaceId?: string }
1225
- ): Promise<HubAgentSkill> {
1226
- const workspaceId = options?.workspaceId ?? this.workspaceId;
1227
- const qs = workspaceId ? `?${new URLSearchParams({ workspaceId })}` : "";
1228
- return this.request<HubAgentSkill>(
1229
- "GET",
1230
- `/api/hub/agent-skills/by-slug/${encodeURIComponent(slug)}${qs}`
1231
- );
1232
- }
1233
-
1234
- /** Compose just-in-time teaching and governance briefs for selected tools. */
1235
- async getCapabilityBriefs(
1236
- input: GetCapabilityBriefsInput
1237
- ): Promise<HubCapabilityBriefsResult> {
1238
- if (input.tools.length === 0) return { briefs: {} };
1239
- const workspaceId = input.workspaceId ?? this.workspaceId;
1240
- const params = new URLSearchParams({ tools: input.tools.join(",") });
1241
- if (workspaceId) params.set("workspaceId", workspaceId);
1242
- if (input.door) params.set("door", input.door);
1243
- return this.request<HubCapabilityBriefsResult>(
1244
- "GET",
1245
- `/api/hub/briefs?${params}`
1246
- );
1247
- }
1248
-
1249
- // ─── Commands & Agents ────────────────────────────────────────────────────
1250
-
1251
- /**
1252
- * List available commands (automation shortcuts) in the workspace.
1253
- */
1254
- async listCommands(workspaceId?: string): Promise<HubCommand[]> {
1255
- const wsId = workspaceId ?? this.workspaceId;
1256
- const params = new URLSearchParams();
1257
- if (wsId) params.set("workspaceId", wsId);
1258
- const qs = params.toString() ? `?${params}` : "";
1259
- const result = await this.request<
1260
- HubCommand[] | HubListResponse<HubCommand>
1261
- >("GET", `/api/hub/commands${qs}`);
1262
- return unwrapList(result);
1263
- }
1264
-
1265
- /**
1266
- * Execute a command by slug.
1267
- *
1268
- * Note: The backend POST /commands/execute uses a `command` field (the shell command
1269
- * string) and `userId`, not a `slug`. This maps ExecuteCommandInput.slug to `command`.
1270
- */
1271
- async executeCommand(
1272
- input: ExecuteCommandInput
1273
- ): Promise<{ status: string; result?: unknown }> {
1274
- const userId = input.userId ?? (await this.resolveUserId());
1275
- return this.request<{ status: string; result?: unknown }>(
1276
- "POST",
1277
- "/api/hub/commands/execute",
1278
- {
1279
- command: input.slug,
1280
- userId,
1281
- workspaceId: input.workspaceId ?? this.workspaceId,
1282
- ...(input.parameters ? { parameters: input.parameters } : {}),
1283
- }
1284
- );
1285
- }
1286
-
1287
- /**
1288
- * List agent users provisioned in the workspace.
1289
- */
1290
- async listAgentUsers(workspaceId?: string): Promise<HubAgentUser[]> {
1291
- const wsId = workspaceId ?? this.workspaceId;
1292
- const params = new URLSearchParams();
1293
- if (wsId) params.set("workspaceId", wsId);
1294
- const qs = params.toString() ? `?${params}` : "";
1295
- const result = await this.request<
1296
- HubAgentUser[] | HubListResponse<HubAgentUser>
1297
- >("GET", `/api/hub/agent-users${qs}`);
1298
- return unwrapList(result);
1299
- }
1300
-
1301
- // ─── Proactive posting ────────────────────────────────────────────────────
1302
-
1303
- /**
1304
- * Post a proactive message to the user's personal channel.
1305
- * For AI-initiated insights and summaries. Rate-limited: 3/hour, 10/day.
1306
- * proactiveType must be one of: insight, suggestion, alert, nudge,
1307
- * morning_briefing, weekly_digest, health_check.
1308
- */
1309
- async postProactive(
1310
- userId: string,
1311
- content: string,
1312
- options?: { workspaceId?: string; type?: string }
1313
- ): Promise<{ id: string }> {
1314
- const wsId = options?.workspaceId ?? this.workspaceId;
1315
- if (!wsId) throw new Error("workspaceId is required for postProactive");
1316
- return this.request<{ id: string }>("POST", "/api/hub/proactive/post", {
1317
- userId,
1318
- workspaceId: wsId,
1319
- content,
1320
- proactiveType: options?.type ?? "insight",
1321
- });
1322
- }
1323
-
1324
- // ─── Capture pipeline ─────────────────────────────────────────────────────
1325
-
1326
- async captureStructure(input: {
1327
- text: string;
1328
- url?: string;
1329
- workspaceId?: string;
1330
- previousEntities?: CaptureProposal[];
1331
- }): Promise<CaptureStructureResponse> {
1332
- const userId = await this.resolveUserId();
1333
- return this.request<CaptureStructureResponse>(
1334
- "POST",
1335
- "/api/hub/capture/structure",
1336
- {
1337
- userId,
1338
- text: input.text,
1339
- url: input.url,
1340
- workspaceId: input.workspaceId ?? this.workspaceId,
1341
- previousEntities: input.previousEntities,
1342
- }
1343
- );
1344
- }
1345
-
1346
- async captureExecute(
1347
- input: CaptureExecuteInput & { workspaceId?: string }
1348
- ): Promise<CaptureExecuteResponse> {
1349
- const userId = await this.resolveUserId();
1350
- return this.request<CaptureExecuteResponse>(
1351
- "POST",
1352
- "/api/hub/capture/execute",
1353
- {
1354
- userId,
1355
- entities: input.entities,
1356
- relations: input.relations ?? [],
1357
- workspaceId: input.workspaceId ?? this.workspaceId,
1358
- // Keep this exact routing bundle in lockstep with CaptureExecuteInput
1359
- // and the REST codec. Dropping it here silently made CLI/Raycast capture
1360
- // behave differently from MCP despite all three using the same backend.
1361
- projectId: input.projectId,
1362
- targetWorkspaceId: input.targetWorkspaceId,
1363
- keepRaw: input.keepRaw,
1364
- file: input.file,
1365
- idempotencyKey: input.idempotencyKey,
1366
- workspaceRouting: input.workspaceRouting,
1367
- aiWorkspaceId: input.aiWorkspaceId,
1368
- aiWorkspaceConfidence: input.aiWorkspaceConfidence,
1369
- aiWorkspaceReason: input.aiWorkspaceReason,
1370
- }
1371
- );
1372
- }
1373
-
1374
- /**
1375
- * Submit a designed entity graph as ONE reviewable composite proposal.
1376
- *
1377
- * This is intentionally distinct from captureExecute(): execute materializes
1378
- * a prior structure result immediately, while this door keeps an autonomous
1379
- * graph plan reviewable and applies entities, relations, and bindings together
1380
- * only after approval.
1381
- */
1382
- async submitCaptureGraph(
1383
- input: SubmitCaptureGraphInput
1384
- ): Promise<SubmitCaptureGraphResult> {
1385
- const { workspaceId, relations, bindings, ...body } = input;
1386
- return this.request<SubmitCaptureGraphResult>(
1387
- "POST",
1388
- "/api/hub/capture/graph",
1389
- {
1390
- ...body,
1391
- // Proposal audience and schema overlays are explicit write choices.
1392
- ...(workspaceId ? { workspaceId } : {}),
1393
- relations: relations ?? [],
1394
- bindings: bindings ?? [],
1395
- }
1396
- );
1397
- }
1398
-
1399
- // ─── Recall: the one door ──────────────────────────────────────────────────
1400
-
1401
- /**
1402
- * `ask` — the unified recall verb. Routes a natural-language question across
1403
- * all knowledge substrates (semantic entities, procedural runbooks, episodic
1404
- * facts) server-side and returns ONE provenance-tagged answer. The canonical
1405
- * recall door — prefer it over the fragmented searchEntities / recallMemory.
1406
- * The server builds the profile catalog from the caller's workspace; the
1407
- * client only sends the query (+ optional scope).
1408
- */
1409
- async ask(input: {
1410
- query: string;
1411
- workspaceId?: string;
1412
- limit?: number;
1413
- /**
1414
- * Return just the glass-box understanding + routing (no retrieval) — for a
1415
- * caller that routes a query before fetching results (e.g. a palette
1416
- * completing a type word). `answers` comes back empty.
1417
- */
1418
- parseOnly?: boolean;
1419
- }): Promise<AskResponse> {
1420
- return this.request<AskResponse>("POST", "/api/hub/knowledge/ask", {
1421
- query: input.query,
1422
- workspaceId: input.workspaceId ?? this.workspaceId,
1423
- limit: input.limit,
1424
- parseOnly: input.parseOnly,
1425
- });
1426
- }
1427
-
1428
- // ─── Automations ───────────────────────────────────────────────────────────
1429
-
1430
- /**
1431
- * List automations for the current user, optionally filtered by workspace and status.
1432
- */
1433
- async listAutomations(options?: {
1434
- workspaceId?: string;
1435
- status?: AutomationStatus;
1436
- limit?: number;
1437
- }): Promise<HubAutomation[]> {
1438
- const userId = await this.resolveUserId();
1439
- const wsId = options?.workspaceId ?? this.workspaceId;
1440
- const params = new URLSearchParams({ userId });
1441
- if (wsId) params.set("workspaceId", wsId);
1442
- if (options?.status) params.set("status", options.status);
1443
- if (options?.limit) params.set("limit", String(options.limit));
1444
- const result = await this.request<
1445
- HubAutomation[] | HubListResponse<HubAutomation>
1446
- >("GET", `/api/hub/automations?${params}`);
1447
- return unwrapList(result);
1448
- }
1449
-
1450
- /**
1451
- * Get a single automation by ID.
1452
- */
1453
- async getAutomation(
1454
- automationId: string,
1455
- options?: { workspaceId?: string }
1456
- ): Promise<HubAutomation> {
1457
- const userId = await this.resolveUserId();
1458
- const wsId = options?.workspaceId ?? this.workspaceId;
1459
- const params = new URLSearchParams({ userId });
1460
- if (wsId) params.set("workspaceId", wsId);
1461
- return this.request<HubAutomation>(
1462
- "GET",
1463
- `/api/hub/automations/${automationId}?${params}`
1464
- );
1465
- }
1466
-
1467
- /**
1468
- * Create an automation. Defaults to status=draft.
1469
- * Use activateAutomation() to enable it.
1470
- */
1471
- async createAutomation(input: CreateAutomationInput): Promise<HubAutomation> {
1472
- const userId = input.userId ?? (await this.resolveUserId());
1473
- const wsId = input.workspaceId ?? this.workspaceId;
1474
- return this.request<HubAutomation>("POST", "/api/hub/automations/create", {
1475
- ...input,
1476
- userId,
1477
- workspaceId: wsId ?? null,
1478
- });
1479
- }
1480
-
1481
- /**
1482
- * Update an automation's definition or metadata.
1483
- */
1484
- async updateAutomation(
1485
- automationId: string,
1486
- input: UpdateAutomationInput
1487
- ): Promise<HubAutomation> {
1488
- const userId = input.userId ?? (await this.resolveUserId());
1489
- const wsId = input.workspaceId ?? this.workspaceId;
1490
- if (!wsId) throw new Error("workspaceId is required for updateAutomation");
1491
- return this.request<HubAutomation>(
1492
- "PATCH",
1493
- `/api/hub/automations/${automationId}`,
1494
- { ...input, userId, workspaceId: wsId }
1495
- );
1496
- }
1497
-
1498
- /**
1499
- * Manually trigger an automation once with an optional payload.
1500
- * Bypasses the automation's normal trigger config.
1501
- */
1502
- async triggerAutomation(
1503
- automationId: string,
1504
- options?: {
1505
- payload?: Record<string, unknown>;
1506
- workspaceId?: string;
1507
- }
1508
- ): Promise<{ status: string; runId?: string; result?: unknown }> {
1509
- const userId = await this.resolveUserId();
1510
- const wsId = options?.workspaceId ?? this.workspaceId;
1511
- return this.request<{ status: string; runId?: string; result?: unknown }>(
1512
- "POST",
1513
- `/api/hub/automations/${automationId}/trigger`,
1514
- { userId, workspaceId: wsId ?? null, payload: options?.payload }
1515
- );
1516
- }
1517
-
1518
- /**
1519
- * Activate a draft or paused automation (sets status=active).
1520
- */
1521
- async activateAutomation(
1522
- automationId: string,
1523
- options?: { workspaceId?: string }
1524
- ): Promise<HubAutomation> {
1525
- const userId = await this.resolveUserId();
1526
- const wsId = options?.workspaceId ?? this.workspaceId;
1527
- if (!wsId)
1528
- throw new Error("workspaceId is required for activateAutomation");
1529
- return this.request<HubAutomation>(
1530
- "POST",
1531
- `/api/hub/automations/${automationId}/activate`,
1532
- { userId, workspaceId: wsId }
1533
- );
1534
- }
1535
-
1536
- /**
1537
- * Pause an active automation (sets status=paused).
1538
- */
1539
- async pauseAutomation(
1540
- automationId: string,
1541
- options?: { workspaceId?: string }
1542
- ): Promise<HubAutomation> {
1543
- const userId = await this.resolveUserId();
1544
- const wsId = options?.workspaceId ?? this.workspaceId;
1545
- if (!wsId) throw new Error("workspaceId is required for pauseAutomation");
1546
- return this.request<HubAutomation>(
1547
- "POST",
1548
- `/api/hub/automations/${automationId}/pause`,
1549
- { userId, workspaceId: wsId }
1550
- );
1551
- }
1552
-
1553
- // ─── Subscriptions / Reactions (Pulse) ────────────────────────────────────
1554
-
1555
- /**
1556
- * List the user-wide Pulse feed — the timestamp-sorted union of reactive events.
1557
- * Call getSubscriptionFanout() on an individual event for its dense reactions[].
1558
- */
1559
- async listSubscriptions(options?: {
1560
- workspaceId?: string;
1561
- kind?: ReactionKind;
1562
- eventType?: string;
1563
- lens?: ReactionLens;
1564
- limit?: number;
1565
- }): Promise<HubReactionEvent[]> {
1566
- const wsId = options?.workspaceId ?? this.workspaceId;
1567
- const params = new URLSearchParams();
1568
- if (wsId) params.set("workspaceId", wsId);
1569
- if (options?.kind) params.set("kind", options.kind);
1570
- if (options?.eventType) params.set("eventType", options.eventType);
1571
- if (options?.lens) params.set("lens", options.lens);
1572
- if (options?.limit) params.set("limit", String(options.limit));
1573
- const qs = params.toString() ? `?${params}` : "";
1574
- const result = await this.request<
1575
- HubReactionEvent[] | HubListResponse<HubReactionEvent>
1576
- >("GET", `/api/hub/subscriptions${qs}`);
1577
- return unwrapList(result);
1578
- }
1579
-
1580
- /**
1581
- * Get the reaction fan-out for a single event — full reactions[] populated.
1582
- */
1583
- async getSubscriptionFanout(
1584
- eventId: string,
1585
- options?: { lens?: ReactionLens }
1586
- ): Promise<HubReactionEvent> {
1587
- const params = new URLSearchParams();
1588
- if (options?.lens) params.set("lens", options.lens);
1589
- const qs = params.toString() ? `?${params}` : "";
1590
- return this.request<HubReactionEvent>(
1591
- "GET",
1592
- `/api/hub/subscriptions/${eventId}/fanout${qs}`
1593
- );
1594
- }
1595
-
1596
- // ─── Notifications ─────────────────────────────────────────────────────────
1597
-
1598
- /**
1599
- * Persist a notification and emit notification:new to the frontend.
1600
- * Use for IS-originated events (skill.triggered, agent actions, etc.).
1601
- * Backend-originated notifications (vault, proposals) use NotificationService directly.
1602
- */
1603
- async createNotification(
1604
- input: CreateNotificationInput
1605
- ): Promise<{ id: string }> {
1606
- return this.request<{ id: string }>(
1607
- "POST",
1608
- "/api/hub/notifications",
1609
- input
1610
- );
1611
- }
1612
-
1613
- // ─── Webhooks ──────────────────────────────────────────────────────────────
1614
-
1615
- /**
1616
- * List delivery log for a webhook subscription.
1617
- * Powers the Reactions Health tab and replay flows.
1618
- */
1619
- async getWebhookDeliveries(
1620
- subscriptionId: string,
1621
- options?: { limit?: number }
1622
- ): Promise<HubWebhookDelivery[]> {
1623
- const params = new URLSearchParams();
1624
- if (options?.limit) params.set("limit", String(options.limit));
1625
- const qs = params.toString() ? `?${params}` : "";
1626
- const result = await this.request<
1627
- HubWebhookDelivery[] | HubListResponse<HubWebhookDelivery>
1628
- >("GET", `/api/hub/webhooks/${subscriptionId}/deliveries${qs}`);
1629
- return unwrapList(result);
1630
- }
1631
- }