shadow-claw 1.29.0 → 1.30.0

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 (277) hide show
  1. package/.agents/skills/main/skill-creator/SKILL.md +3 -2
  2. package/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  3. package/.well-known/agent-skills/index.json +1 -1
  4. package/.well-known/mcp/server-card.json +1 -1
  5. package/.well-known/mcp.json +1 -1
  6. package/dist/lib/{app-routes-CqBOeA5q.js → app-routes-BAEMLu9g.js} +3 -2
  7. package/dist/lib/app-routes-BAEMLu9g.js.map +1 -0
  8. package/dist/lib/{bundler-8JNIKwOs.js → bundler-CsL7hHMq.js} +4 -9
  9. package/dist/lib/{bundler-8JNIKwOs.js.map → bundler-CsL7hHMq.js.map} +1 -1
  10. package/dist/lib/components/index.js +26 -26
  11. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  12. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  13. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  14. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  15. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  16. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  17. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  18. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  19. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  20. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  21. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  22. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  23. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  24. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  25. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  26. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  27. package/dist/lib/components/shadow-claw-channels.js +1 -1
  28. package/dist/lib/components/shadow-claw-chat.js +1 -1
  29. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  30. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  31. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  32. package/dist/lib/components/shadow-claw-files.js +1 -1
  33. package/dist/lib/components/shadow-claw-git.js +1 -1
  34. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  35. package/dist/lib/components/shadow-claw-llm.js +1 -1
  36. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  37. package/dist/lib/components/shadow-claw-networking.js +1 -1
  38. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  39. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  40. package/dist/lib/components/shadow-claw-pages.js +1 -1
  41. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  42. package/dist/lib/components/shadow-claw-settings.js +1 -1
  43. package/dist/lib/components/shadow-claw-storage.js +1 -1
  44. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  45. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  46. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  47. package/dist/lib/components/shadow-claw-tools.js +1 -1
  48. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  49. package/dist/lib/components/shadow-claw.js +1 -1
  50. package/dist/lib/{config--CFrw3J3.js → config-DjZ9QWc4.js} +2 -2
  51. package/dist/lib/{config--CFrw3J3.js.map → config-DjZ9QWc4.js.map} +1 -1
  52. package/dist/lib/{configurePeerJs-DG4hliKp.js → configurePeerJs-H0WaoT0w.js} +3 -3
  53. package/dist/lib/{configurePeerJs-DG4hliKp.js.map → configurePeerJs-H0WaoT0w.js.map} +1 -1
  54. package/dist/lib/{connections-DwjzwVz0.js → connections-BURqMIUv.js} +2 -2
  55. package/dist/lib/{connections-DwjzwVz0.js.map → connections-BURqMIUv.js.map} +1 -1
  56. package/dist/lib/content/markdown-links.d.ts +19 -0
  57. package/dist/lib/core/app-routes.d.ts +1 -0
  58. package/dist/lib/{downloadGroupFile-DmcBQU1n.js → downloadGroupFile-B8J4up2a.js} +2 -2
  59. package/dist/lib/{downloadGroupFile-DmcBQU1n.js.map → downloadGroupFile-B8J4up2a.js.map} +1 -1
  60. package/dist/lib/{file-viewer-C3YKnq_-.js → file-viewer-CwvhxAAG.js} +5 -5
  61. package/dist/lib/{file-viewer-C3YKnq_-.js.map → file-viewer-CwvhxAAG.js.map} +1 -1
  62. package/dist/lib/{getGroupDir-m0f-ekgX.js → getGroupDir-QrN2aTo8.js} +4 -4
  63. package/dist/lib/{getGroupDir-m0f-ekgX.js.map → getGroupDir-QrN2aTo8.js.map} +1 -1
  64. package/dist/lib/{git-C-Q6-IVe.js → git-DhZoe1SE.js} +3 -3
  65. package/dist/lib/{git-C-Q6-IVe.js.map → git-DhZoe1SE.js.map} +1 -1
  66. package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js → iframe-sanitizer-Bujgq14T.js} +2 -2
  67. package/dist/lib/{iframe-sanitizer-CUqHuWQ-.js.map → iframe-sanitizer-Bujgq14T.js.map} +1 -1
  68. package/dist/lib/index.js +27 -27
  69. package/dist/lib/{initChatSplitResize-yyBTU6h9.js → initChatSplitResize-BjiWoqC_.js} +2 -2
  70. package/dist/lib/{initChatSplitResize-yyBTU6h9.js.map → initChatSplitResize-BjiWoqC_.js.map} +1 -1
  71. package/dist/lib/{initControlPlane-DnpAzphg.js → initControlPlane-C9JxQCDh.js} +16 -16
  72. package/dist/lib/{initControlPlane-DnpAzphg.js.map → initControlPlane-C9JxQCDh.js.map} +1 -1
  73. package/dist/lib/{markdown-DgdSt2GD.js → markdown-DYHmNjC4.js} +126 -5
  74. package/dist/lib/markdown-DYHmNjC4.js.map +1 -0
  75. package/dist/lib/{mcp-reconnect-C86MR3z8.js → mcp-reconnect-BxJ77WSb.js} +2 -2
  76. package/dist/lib/{mcp-reconnect-C86MR3z8.js.map → mcp-reconnect-BxJ77WSb.js.map} +1 -1
  77. package/dist/lib/{memoryStorage-UR8E8K-H.js → memoryStorage-D3FBwO9T.js} +2 -2
  78. package/dist/lib/{memoryStorage-UR8E8K-H.js.map → memoryStorage-D3FBwO9T.js.map} +1 -1
  79. package/dist/lib/{orchestrator-ClXbJ4Mb.js → orchestrator-C6dc-2OQ.js} +130 -27
  80. package/dist/lib/{orchestrator-ClXbJ4Mb.js.map → orchestrator-C6dc-2OQ.js.map} +1 -1
  81. package/dist/lib/{orchestrator-CjEau_RG.js → orchestrator-DVkyd8K9.js} +27 -17
  82. package/dist/lib/orchestrator-DVkyd8K9.js.map +1 -0
  83. package/dist/lib/{peerjs-BdfpltIe.js → peerjs-BUS9O04I.js} +274 -60
  84. package/dist/lib/peerjs-BUS9O04I.js.map +1 -0
  85. package/dist/lib/{push-client-DjwKknNg.js → push-client-4JsQGmQa.js} +3 -3
  86. package/dist/lib/{push-client-DjwKknNg.js.map → push-client-4JsQGmQa.js.map} +1 -1
  87. package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js → readGroupFileBytes-CSA7u-nJ.js} +2 -2
  88. package/dist/lib/{readGroupFileBytes-C8oOe8Iu.js.map → readGroupFileBytes-CSA7u-nJ.js.map} +1 -1
  89. package/dist/lib/{shadow-claw-DcPGKenn.js → shadow-claw-BMoF8Auf.js} +11 -11
  90. package/dist/lib/{shadow-claw-DcPGKenn.js.map → shadow-claw-BMoF8Auf.js.map} +1 -1
  91. package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js → shadow-claw-a2ui-2I5nffIn.js} +2 -2
  92. package/dist/lib/{shadow-claw-a2ui-CpZUTzlh.js.map → shadow-claw-a2ui-2I5nffIn.js.map} +1 -1
  93. package/dist/lib/{shadow-claw-accounts-03oJ__XC.js → shadow-claw-accounts-BCjlgvzy.js} +3 -3
  94. package/dist/lib/{shadow-claw-accounts-03oJ__XC.js.map → shadow-claw-accounts-BCjlgvzy.js.map} +1 -1
  95. package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js → shadow-claw-channel-config-CxQAmlDE.js} +3 -3
  96. package/dist/lib/{shadow-claw-channel-config-DEL-aZ7N.js.map → shadow-claw-channel-config-CxQAmlDE.js.map} +1 -1
  97. package/dist/lib/{shadow-claw-channels-BgaJiPdE.js → shadow-claw-channels-CuYMUVAG.js} +3 -3
  98. package/dist/lib/{shadow-claw-channels-BgaJiPdE.js.map → shadow-claw-channels-CuYMUVAG.js.map} +1 -1
  99. package/dist/lib/{shadow-claw-chat-mXPQZbwT.js → shadow-claw-chat-RFtPmmyl.js} +13 -12
  100. package/dist/lib/shadow-claw-chat-RFtPmmyl.js.map +1 -0
  101. package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js → shadow-claw-control-plane-siqmRzR1.js} +7 -7
  102. package/dist/lib/{shadow-claw-control-plane-DO6foOLV.js.map → shadow-claw-control-plane-siqmRzR1.js.map} +1 -1
  103. package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js → shadow-claw-conversations-DygK5y1e.js} +7 -7
  104. package/dist/lib/{shadow-claw-conversations-BLwHTwdW.js.map → shadow-claw-conversations-DygK5y1e.js.map} +1 -1
  105. package/dist/lib/{shadow-claw-file-viewer-BSbZvSl-.js → shadow-claw-file-viewer-DGMA7d7H.js} +11 -11
  106. package/dist/lib/shadow-claw-file-viewer-DGMA7d7H.js.map +1 -0
  107. package/dist/lib/{shadow-claw-files-BLVr9Pua.js → shadow-claw-files-CgD1B9J7.js} +8 -8
  108. package/dist/lib/{shadow-claw-files-BLVr9Pua.js.map → shadow-claw-files-CgD1B9J7.js.map} +1 -1
  109. package/dist/lib/{shadow-claw-git-CHC1H86J.js → shadow-claw-git-Bw1jGRrf.js} +6 -6
  110. package/dist/lib/{shadow-claw-git-CHC1H86J.js.map → shadow-claw-git-Bw1jGRrf.js.map} +1 -1
  111. package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js → shadow-claw-integrations-ChaXtvsg.js} +4 -4
  112. package/dist/lib/{shadow-claw-integrations-Ds-CLPhj.js.map → shadow-claw-integrations-ChaXtvsg.js.map} +1 -1
  113. package/dist/lib/{shadow-claw-llm-CKXfxd3D.js → shadow-claw-llm-CDM4Akjc.js} +6 -6
  114. package/dist/lib/{shadow-claw-llm-CKXfxd3D.js.map → shadow-claw-llm-CDM4Akjc.js.map} +1 -1
  115. package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js → shadow-claw-mcp-remote-BLxs_Z4I.js} +4 -4
  116. package/dist/lib/{shadow-claw-mcp-remote-CT5Q-54E.js.map → shadow-claw-mcp-remote-BLxs_Z4I.js.map} +1 -1
  117. package/dist/lib/{shadow-claw-networking-dpYvfchh.js → shadow-claw-networking-BYt-kMSI.js} +2 -2
  118. package/dist/lib/{shadow-claw-networking-dpYvfchh.js.map → shadow-claw-networking-BYt-kMSI.js.map} +1 -1
  119. package/dist/lib/{shadow-claw-notifications-_YeAVPga.js → shadow-claw-notifications-Dpe4EtZI.js} +3 -3
  120. package/dist/lib/{shadow-claw-notifications-_YeAVPga.js.map → shadow-claw-notifications-Dpe4EtZI.js.map} +1 -1
  121. package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js → shadow-claw-page-header-P4EvWyUr.js} +2 -2
  122. package/dist/lib/{shadow-claw-page-header-Cti2fzf-.js.map → shadow-claw-page-header-P4EvWyUr.js.map} +1 -1
  123. package/dist/lib/{shadow-claw-pages-DVzZriZ7.js → shadow-claw-pages-DWd_c4d6.js} +10 -10
  124. package/dist/lib/{shadow-claw-pages-DVzZriZ7.js.map → shadow-claw-pages-DWd_c4d6.js.map} +1 -1
  125. package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js → shadow-claw-peerjs-D928817m.js} +3 -3
  126. package/dist/lib/{shadow-claw-peerjs-BvixjeBz.js.map → shadow-claw-peerjs-D928817m.js.map} +1 -1
  127. package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js → shadow-claw-settings-C8OPrSqs.js} +8 -8
  128. package/dist/lib/{shadow-claw-settings-DV9-gD4Q.js.map → shadow-claw-settings-C8OPrSqs.js.map} +1 -1
  129. package/dist/lib/{shadow-claw-storage-Bv__kXG6.js → shadow-claw-storage-CZ2uZJNw.js} +5 -5
  130. package/dist/lib/{shadow-claw-storage-Bv__kXG6.js.map → shadow-claw-storage-CZ2uZJNw.js.map} +1 -1
  131. package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js → shadow-claw-task-server-CLT018BX.js} +2 -2
  132. package/dist/lib/{shadow-claw-task-server-DNOe8PWK.js.map → shadow-claw-task-server-CLT018BX.js.map} +1 -1
  133. package/dist/lib/{shadow-claw-tasks-qmcDT4PU.js → shadow-claw-tasks-D5h-lGmq.js} +9 -8
  134. package/dist/lib/shadow-claw-tasks-D5h-lGmq.js.map +1 -0
  135. package/dist/lib/{shadow-claw-terminal-0QUWP8of.js → shadow-claw-terminal-Cy1O6KVM.js} +2 -2
  136. package/dist/lib/{shadow-claw-terminal-0QUWP8of.js.map → shadow-claw-terminal-Cy1O6KVM.js.map} +1 -1
  137. package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js → shadow-claw-tools-CVD06bCR.js} +9 -9
  138. package/dist/lib/{shadow-claw-tools-Bs_bmI6-.js.map → shadow-claw-tools-CVD06bCR.js.map} +1 -1
  139. package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js → shadow-claw-webvm-DoGl5ZSJ.js} +3 -3
  140. package/dist/lib/{shadow-claw-webvm-DYaoL7QY.js.map → shadow-claw-webvm-DoGl5ZSJ.js.map} +1 -1
  141. package/dist/lib/subsystems/channels/peerjs.d.ts +37 -4
  142. package/dist/lib/subsystems/channels/room.d.ts +4 -0
  143. package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js → syncWebMcpRegistration-BeYkQEvj.js} +5 -5
  144. package/dist/lib/{syncWebMcpRegistration-BhbqI6R2.js.map → syncWebMcpRegistration-BeYkQEvj.js.map} +1 -1
  145. package/dist/lib/tools-C3Kft940.js +1 -0
  146. package/dist/lib/{tools-DBaMRiEu.js → tools-DKzPWc0q.js} +2 -2
  147. package/dist/lib/{tools-DBaMRiEu.js.map → tools-DKzPWc0q.js.map} +1 -1
  148. package/dist/lib/{tools-DwwB9RBa.js → tools-DqcJe8LS.js} +5 -5
  149. package/dist/lib/{tools-DwwB9RBa.js.map → tools-DqcJe8LS.js.map} +1 -1
  150. package/dist/lib/{trusted-types-Dx0RZlrd.js → trusted-types-Oz7xXJAY.js} +4 -4
  151. package/dist/lib/{trusted-types-Dx0RZlrd.js.map → trusted-types-Oz7xXJAY.js.map} +1 -1
  152. package/dist/lib/utils/index.js +1 -1
  153. package/dist/lib/utils/namespacedStorage.js +1 -1
  154. package/dist/lib/utils/utils.js +1 -1
  155. package/dist/lib/{webmcp-j_1_T3wf.js → webmcp-BC8_WafM.js} +4 -4
  156. package/dist/lib/{webmcp-j_1_T3wf.js.map → webmcp-BC8_WafM.js.map} +1 -1
  157. package/dist/lib/worker/utils/system-prompt.d.ts +4 -1
  158. package/dist/public/.agents/skills/main/skill-creator/SKILL.md +3 -2
  159. package/dist/public/.agents/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  160. package/dist/public/.well-known/agent-skills/index.json +1 -1
  161. package/dist/public/.well-known/mcp/server-card.json +1 -1
  162. package/dist/public/.well-known/mcp.json +1 -1
  163. package/dist/public/agent.worker.js +18 -17
  164. package/dist/public/app-routes-BMQ4HFaM.js +1 -0
  165. package/dist/public/{bundler-Ca-Xwln8.js → bundler-0if-QelV.js} +4 -4
  166. package/dist/public/{config-CrHchneq.js → config-Bnwx4EfS.js} +1 -1
  167. package/dist/public/{configurePeerJs-B470pdeU.js → configurePeerJs-DkyGvwk_.js} +1 -1
  168. package/dist/public/{connections-DvbgdkaB.js → connections-6575KDGE.js} +1 -1
  169. package/dist/public/{custom-element-security-FU04Cq05.js → custom-element-security-BQJQ_oKz.js} +1 -1
  170. package/dist/public/docs/example/article/index.html +2 -2
  171. package/dist/public/docs/publishing/index.html +2 -2
  172. package/dist/public/docs/skill-creator/index.html +2 -2
  173. package/dist/public/docs/subsystems/skills.md +3 -1
  174. package/dist/public/{downloadGroupFile-D8KRJGGL.js → downloadGroupFile-Wo1Sxdhr.js} +1 -1
  175. package/dist/public/{e2e-bridge-CSW0S5Yz.js → e2e-bridge-CvLCUU2O.js} +1 -1
  176. package/dist/public/{file-viewer-Cs-riNvy.js → file-viewer-CIjqAvNF.js} +1 -1
  177. package/dist/public/{getGroupDir-P1h9wl6S.js → getGroupDir-BwprrdrQ.js} +1 -1
  178. package/dist/public/{git-7Vq_SJSp.js → git-BSnY2D-A.js} +2 -2
  179. package/dist/public/{iframe-sanitizer-y2Z1pPwY.js → iframe-sanitizer-viROQkRn.js} +1 -1
  180. package/dist/public/index.html +2 -2
  181. package/dist/public/index.js +1 -1
  182. package/dist/public/{initChatSplitResize-CzV2E7Ul.js → initChatSplitResize-BA18wLQQ.js} +1 -1
  183. package/dist/public/{initControlPlane-BqCY0NQy.js → initControlPlane-L96uJkRA.js} +1 -1
  184. package/dist/public/main/index.html +2 -2
  185. package/dist/public/main/memory/index.html +2 -2
  186. package/dist/public/{markdown-Cw7vCtTg.js → markdown-DGjZAm_w.js} +17 -14
  187. package/dist/public/{mcp-reconnect-9emsqGRe.js → mcp-reconnect-CBHuaYdF.js} +1 -1
  188. package/dist/public/{memoryStorage-C0KvLNUp.js → memoryStorage-C1llaYus.js} +1 -1
  189. package/dist/public/orchestrator-C0VOoTiK.js +15 -0
  190. package/dist/public/{orchestrator-DpkkeD6T.js → orchestrator-DMWi--Dc.js} +20 -19
  191. package/dist/public/peerjs-Bf6ZxfbA.js +1 -0
  192. package/dist/public/{push-client-CHjSbrWs.js → push-client-BD4YalBa.js} +1 -1
  193. package/dist/public/service-worker.js +1 -1
  194. package/dist/public/{shadow-claw-BBPV_9X8.js → shadow-claw-DRy-D4Qi.js} +2 -2
  195. package/dist/public/{shadow-claw-accounts-xUOLBsQZ.js → shadow-claw-accounts-DnfmA8cb.js} +1 -1
  196. package/dist/public/{shadow-claw-channels-BJvrKQjg.js → shadow-claw-channels-8UkycZAa.js} +1 -1
  197. package/dist/public/{shadow-claw-chat-BG2EaRaw.js → shadow-claw-chat-Cf5LUiul.js} +9 -9
  198. package/dist/public/{shadow-claw-control-plane-BBa7WbTg.js → shadow-claw-control-plane-UsBF-Nvd.js} +2 -2
  199. package/dist/public/{shadow-claw-conversations-CFaWFmkm.js → shadow-claw-conversations-Aoe61Y21.js} +1 -1
  200. package/dist/public/{shadow-claw-file-viewer-Z-GIKaE9.js → shadow-claw-file-viewer-D28dSSEn.js} +6 -6
  201. package/dist/public/{shadow-claw-files-BBx4iMsk.js → shadow-claw-files-CaDUlPEU.js} +1 -1
  202. package/dist/public/{shadow-claw-git-vTOKatwd.js → shadow-claw-git-DYNcZMWA.js} +2 -2
  203. package/dist/public/{shadow-claw-integrations-BBVnO0Fc.js → shadow-claw-integrations-BJf_hQVv.js} +1 -1
  204. package/dist/public/{shadow-claw-llm-Ce1Ax6-x.js → shadow-claw-llm-BqK2SIRf.js} +2 -2
  205. package/dist/public/{shadow-claw-mcp-remote-Bkx0gsmF.js → shadow-claw-mcp-remote-B_dDG990.js} +1 -1
  206. package/dist/public/{shadow-claw-networking-q4XIzdB5.js → shadow-claw-networking-D8LxOofv.js} +1 -1
  207. package/dist/public/{shadow-claw-notifications-D2cz0gmm.js → shadow-claw-notifications-DpVyiNG_.js} +1 -1
  208. package/dist/public/{shadow-claw-page-header-BccSHItx.js → shadow-claw-page-header-DdC7bJuW.js} +1 -1
  209. package/dist/public/{shadow-claw-pages-3335lmSC.js → shadow-claw-pages-CYMl4J-6.js} +3 -3
  210. package/dist/public/{shadow-claw-settings-4ptYuJwO.js → shadow-claw-settings-Da_8Oy3O.js} +3 -3
  211. package/dist/public/{shadow-claw-storage-bIrPKFhF.js → shadow-claw-storage-DXIm86_-.js} +1 -1
  212. package/dist/public/{shadow-claw-task-server-5yqVBxy1.js → shadow-claw-task-server-BCceBD0G.js} +1 -1
  213. package/dist/public/{shadow-claw-tasks-DcqYHPLZ.js → shadow-claw-tasks-BW1QZ5L3.js} +19 -19
  214. package/dist/public/{shadow-claw-terminal-fARaDONr.js → shadow-claw-terminal-vqfsxhcK.js} +1 -1
  215. package/dist/public/{shadow-claw-tools-paEAhcJr.js → shadow-claw-tools-l0Jsa7UJ.js} +1 -1
  216. package/dist/public/{shadow-claw-webvm-CbzH_vyX.js → shadow-claw-webvm-CDPOWZm7.js} +1 -1
  217. package/dist/public/skills/main/skill-creator/SKILL.md +3 -2
  218. package/dist/public/skills/main/skill-creator/references/frontmatter-spec.md +5 -3
  219. package/dist/public/static-main-manifest.json +2 -2
  220. package/dist/public/{syncWebMcpRegistration-CWSYaHex.js → syncWebMcpRegistration-5b5FkP9_.js} +1 -1
  221. package/dist/public/tools-B-PzsLc2.js +1 -0
  222. package/dist/public/{tools-C8x3nmo4.js → tools-CcgG5XuA.js} +1 -1
  223. package/dist/public/{tools-DvckJZG2.js → tools-VSOY66vs.js} +1 -1
  224. package/dist/public/{webmcp-DAjmliCx.js → webmcp-DBONjQWd.js} +1 -1
  225. package/dist/server.js +2 -2
  226. package/package.json +2 -2
  227. package/src/__mocks__/marked.cjs +14 -0
  228. package/src/components/shadow-claw-chat/shadow-claw-chat.test.ts +17 -0
  229. package/src/components/shadow-claw-chat/shadow-claw-chat.ts +5 -1
  230. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.test.ts +78 -0
  231. package/src/components/shadow-claw-file-viewer/shadow-claw-file-viewer.ts +6 -2
  232. package/src/components/shadow-claw-pages/utils/resolveWorkspaceLinkPath.test.ts +56 -0
  233. package/src/components/shadow-claw-tasks/shadow-claw-tasks.test.ts +22 -0
  234. package/src/components/shadow-claw-tasks/shadow-claw-tasks.ts +5 -1
  235. package/src/content/markdown-links.test.ts +109 -0
  236. package/src/content/markdown-links.ts +187 -0
  237. package/src/content/markdown.test.ts +33 -0
  238. package/src/content/markdown.ts +6 -1
  239. package/src/core/app-routes.test.ts +65 -0
  240. package/src/core/app-routes.ts +1 -1
  241. package/src/core/orchestrator/orchestrator.ts +3 -0
  242. package/src/core/orchestrator/utils/compactContext.ts +2 -0
  243. package/src/core/orchestrator/utils/invokeAgent.ts +1 -0
  244. package/src/subsystems/accounts/service-accounts.test.ts +0 -1
  245. package/src/subsystems/channels/peerjs.test.ts +479 -1
  246. package/src/subsystems/channels/peerjs.ts +420 -75
  247. package/src/subsystems/channels/room.test.ts +35 -0
  248. package/src/subsystems/channels/room.ts +15 -0
  249. package/src/subsystems/skills/activateSkill.test.ts +38 -5
  250. package/src/subsystems/skills/activateSkill.ts +25 -3
  251. package/src/subsystems/skills/parseSkill.test.ts +71 -0
  252. package/src/subsystems/skills/parseSkill.ts +185 -25
  253. package/src/subsystems/tools/files.ts +4 -4
  254. package/src/worker/tools/spawn-subagent/spawn-subagent.test.ts +22 -23
  255. package/src/worker/tools/workspace/send-file.test.ts +24 -1
  256. package/src/worker/tools/workspace/send-file.ts +6 -3
  257. package/src/worker/utils/handleCompact.test.ts +3 -4
  258. package/src/worker/utils/handleInvoke.test.ts +13 -11
  259. package/src/worker/utils/handleInvoke.ts +3 -0
  260. package/src/worker/utils/handleMessage.test.ts +0 -1
  261. package/src/worker/utils/post.test.ts +3 -4
  262. package/src/worker/utils/sandboxedEval.test.ts +1 -2
  263. package/src/worker/utils/system-prompt.test.ts +59 -0
  264. package/src/worker/utils/system-prompt.ts +21 -1
  265. package/src/worker/utils/withRetry.test.ts +3 -16
  266. package/dist/lib/app-routes-CqBOeA5q.js.map +0 -1
  267. package/dist/lib/markdown-DgdSt2GD.js.map +0 -1
  268. package/dist/lib/orchestrator-CjEau_RG.js.map +0 -1
  269. package/dist/lib/peerjs-BdfpltIe.js.map +0 -1
  270. package/dist/lib/shadow-claw-chat-mXPQZbwT.js.map +0 -1
  271. package/dist/lib/shadow-claw-file-viewer-BSbZvSl-.js.map +0 -1
  272. package/dist/lib/shadow-claw-tasks-qmcDT4PU.js.map +0 -1
  273. package/dist/lib/tools-D4Pp-nUw.js +0 -1
  274. package/dist/public/app-routes-Bs-riIvr.js +0 -1
  275. package/dist/public/orchestrator-BWkHHO9Y.js +0 -15
  276. package/dist/public/peerjs-tf2EmWjB.js +0 -1
  277. package/dist/public/tools-COduyYJ0.js +0 -1
@@ -1,9 +1,11 @@
1
1
  import { jest } from "@jest/globals";
2
2
 
3
3
  const mockLoadSkill = jest.fn() as any;
4
+ const mockDiscoverSkills = jest.fn() as any;
4
5
 
5
6
  jest.unstable_mockModule("./discoverSkills.js", () => ({
6
7
  loadSkill: mockLoadSkill,
8
+ discoverSkills: mockDiscoverSkills,
7
9
  }));
8
10
 
9
11
  const { executeActivateSkill } = await import("./activateSkill.js");
@@ -11,21 +13,27 @@ const { executeActivateSkill } = await import("./activateSkill.js");
11
13
  describe("executeActivateSkill", () => {
12
14
  beforeEach(() => {
13
15
  jest.clearAllMocks();
16
+ mockDiscoverSkills.mockResolvedValue({
17
+ skills: [{ name: "existing-skill", description: "An existing skill" }],
18
+ diagnostics: [],
19
+ });
14
20
  });
15
21
 
16
- it("returns error when skill name is missing or empty", async () => {
22
+ it("returns error when skill name is missing or empty, including available skills", async () => {
17
23
  const res1 = await executeActivateSkill({} as any, {}, "group-1");
18
- expect(res1).toBe("Error: activate_skill requires a skill name.");
24
+ expect(res1).toContain("Error: activate_skill requires a skill name.");
25
+ expect(res1).toContain("Available skills: existing-skill.");
19
26
 
20
27
  const res2 = await executeActivateSkill(
21
28
  {} as any,
22
29
  { name: " " },
23
30
  "group-1",
24
31
  );
25
- expect(res2).toBe("Error: activate_skill requires a skill name.");
32
+ expect(res2).toContain("Error: activate_skill requires a skill name.");
33
+ expect(res2).toContain("Available skills: existing-skill.");
26
34
  });
27
35
 
28
- it("returns error when skill is not found", async () => {
36
+ it("returns error when skill is not found, including available skills", async () => {
29
37
  mockLoadSkill.mockResolvedValue(null);
30
38
 
31
39
  const res = await executeActivateSkill(
@@ -33,9 +41,34 @@ describe("executeActivateSkill", () => {
33
41
  { name: "my-skill" },
34
42
  "group-1",
35
43
  );
36
- expect(res).toBe(
44
+ expect(res).toContain(
37
45
  'Error: skill "my-skill" was not found in this conversation workspace.',
38
46
  );
47
+ expect(res).toContain("Available skills: existing-skill.");
48
+ });
49
+
50
+ it("reports matched diagnostic when a skill exists on disk but failed to parse", async () => {
51
+ mockLoadSkill.mockResolvedValue(null);
52
+ mockDiscoverSkills.mockResolvedValue({
53
+ skills: [{ name: "existing-skill", description: "An existing skill" }],
54
+ diagnostics: [
55
+ {
56
+ path: ".agents/skills/main/broken-skill/SKILL.md",
57
+ message: "YAML parse error on line 3",
58
+ },
59
+ ],
60
+ });
61
+
62
+ const res = await executeActivateSkill(
63
+ {} as any,
64
+ { name: "broken-skill" },
65
+ "group-1",
66
+ );
67
+ expect(res).toContain(
68
+ 'Error: skill "broken-skill" was found at ".agents/skills/main/broken-skill/SKILL.md" but failed to load: YAML parse error on line 3.',
69
+ );
70
+ expect(res).toContain("Please fix the frontmatter in SKILL.md.");
71
+ expect(res).toContain("Available skills: existing-skill.");
39
72
  });
40
73
 
41
74
  it("returns error when skill disables model invocation", async () => {
@@ -1,4 +1,4 @@
1
- import { loadSkill } from "./discoverSkills.js";
1
+ import { discoverSkills, loadSkill } from "./discoverSkills.js";
2
2
  import type { ShadowClawDatabase } from "../../db/types.js";
3
3
 
4
4
  export async function executeActivateSkill(
@@ -7,13 +7,35 @@ export async function executeActivateSkill(
7
7
  groupId: string,
8
8
  ): Promise<string> {
9
9
  const name = typeof input.name === "string" ? input.name.trim() : "";
10
+ const discovery = await discoverSkills(db, groupId);
11
+ const availableSkillNames = discovery.skills.map((s) => s.name);
12
+ const availableList =
13
+ availableSkillNames.length > 0 ? availableSkillNames.join(", ") : "(none)";
14
+
10
15
  if (!name) {
11
- return "Error: activate_skill requires a skill name.";
16
+ let msg = `Error: activate_skill requires a skill name. Available skills: ${availableList}.`;
17
+ if (discovery.diagnostics.length > 0) {
18
+ msg += ` (Note: ${discovery.diagnostics.length} skill file(s) had errors: ${discovery.diagnostics.map((d) => `${d.path}: ${d.message}`).join("; ")})`;
19
+ }
20
+ return msg;
12
21
  }
13
22
 
14
23
  const skill = await loadSkill(db, groupId, name);
15
24
  if (!skill) {
16
- return `Error: skill "${name}" was not found in this conversation workspace.`;
25
+ const matchedDiag = discovery.diagnostics.find(
26
+ (d) =>
27
+ d.path.toLowerCase().includes(name.toLowerCase()) ||
28
+ d.message.toLowerCase().includes(name.toLowerCase()),
29
+ );
30
+ if (matchedDiag) {
31
+ return `Error: skill "${name}" was found at "${matchedDiag.path}" but failed to load: ${matchedDiag.message}. Please fix the frontmatter in SKILL.md. Available skills: ${availableList}.`;
32
+ }
33
+
34
+ let msg = `Error: skill "${name}" was not found in this conversation workspace. Available skills: ${availableList}.`;
35
+ if (discovery.diagnostics.length > 0) {
36
+ msg += ` (Note: ${discovery.diagnostics.length} skill file(s) had errors: ${discovery.diagnostics.map((d) => `${d.path}: ${d.message}`).join("; ")})`;
37
+ }
38
+ return msg;
17
39
  }
18
40
  if (skill.disableModelInvocation) {
19
41
  return `Error: skill "${name}" is not available for model-driven activation.`;
@@ -83,4 +83,75 @@ describe("parseSkill", () => {
83
83
 
84
84
  expect(result.execution).toBeUndefined();
85
85
  });
86
+
87
+ it("resiliently parses frontmatter with unquoted colons, URLs, and quotes in description", () => {
88
+ const rawSkill = `---
89
+ name: bible-lookup
90
+ description: Look up Bible verses from the bible-tools/data repository (https://bible-tools.github.io/data/). Supports multiple translations in Arabic (ar), German (de), English (en: ASV, KJV, WEB), Spanish (es), and French (fr). Trigger phrases: "bible lookup", "look up a bible verse", "bible verse", "find bible verse", "bible reference", "what does the bible say about", "scripture reference", "look up verse", "bible passage".
91
+ user-invocable: true
92
+ metadata:
93
+ allowed-tools:
94
+ - fetch_url
95
+ - javascript
96
+ ---
97
+
98
+ # Bible Lookup Skill
99
+
100
+ Instructions here.`;
101
+
102
+ const result = parseSkill(
103
+ ".agents/skills/main/bible-lookup/SKILL.md",
104
+ rawSkill,
105
+ );
106
+
107
+ expect(result.name).toBe("bible-lookup");
108
+ expect(result.description).toContain(
109
+ "Look up Bible verses from the bible-tools/data repository",
110
+ );
111
+ expect(result.description).toContain("(en: ASV, KJV, WEB)");
112
+ expect(result.userInvocable).toBe(true);
113
+ expect(result.allowedTools).toBe("fetch_url javascript");
114
+ expect(result.metadata?.["allowed-tools"]).toBe("fetch_url javascript");
115
+ expect(result.body).toBe("# Bible Lookup Skill\n\nInstructions here.");
116
+ expect(result.path).toBe(".agents/skills/main/bible-lookup/SKILL.md");
117
+ expect(result.basePath).toBe(".agents/skills/main/bible-lookup");
118
+ });
119
+
120
+ it("normalizes array allowed-tools into a space-separated string", () => {
121
+ const result = parseSkill(
122
+ "skills/tools/SKILL.md",
123
+ `---\nname: tools-test\ndescription: Test tools array\nmetadata:\n allowed-tools:\n - read_file\n - write_file\n - javascript\n---\nbody`,
124
+ );
125
+
126
+ expect(result.allowedTools).toBe("read_file write_file javascript");
127
+ expect(result.metadata?.["allowed-tools"]).toBe(
128
+ "read_file write_file javascript",
129
+ );
130
+ });
131
+
132
+ it("recovers via fallback extraction when YAML syntax is malformed", () => {
133
+ const brokenYaml = `---
134
+ name: broken-yaml-skill
135
+ description: Resilient fallback description with : colons and [broken brackets
136
+ user-invocable: true
137
+ disable-model-invocation: false
138
+ allowed-tools:
139
+ - tool_a
140
+ - tool_b
141
+ some_random_key: {unclosed object
142
+ ---
143
+
144
+ # Fallback Body`;
145
+
146
+ const result = parseSkill("skills/broken/SKILL.md", brokenYaml);
147
+
148
+ expect(result.name).toBe("broken-yaml-skill");
149
+ expect(result.description).toBe(
150
+ "Resilient fallback description with : colons and [broken brackets",
151
+ );
152
+ expect(result.userInvocable).toBe(true);
153
+ expect(result.disableModelInvocation).toBe(false);
154
+ expect(result.allowedTools).toBe("tool_a tool_b");
155
+ expect(result.body).toBe("# Fallback Body");
156
+ });
86
157
  });
@@ -5,10 +5,145 @@ import type { SkillExecution, SkillRecord } from "./types.js";
5
5
 
6
6
  const NAME_PATTERN = /^[a-z0-9](?:[a-z0-9]|-(?!-))*[a-z0-9]$|^[a-z0-9]$/;
7
7
 
8
+ interface FrontmatterParseResult {
9
+ data: Record<string, unknown>;
10
+ content: string;
11
+ }
12
+
13
+ function parseFrontmatterResiliently(source: string): FrontmatterParseResult {
14
+ try {
15
+ const parsed = matter(source);
16
+ return {
17
+ data: parsed.data && typeof parsed.data === "object" ? parsed.data : {},
18
+ content: parsed.content || "",
19
+ };
20
+ } catch {
21
+ // Attempt 1: Sanitize unquoted scalar lines in the frontmatter block
22
+ const fmMatch = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
23
+ if (fmMatch) {
24
+ const rawFm = fmMatch[1];
25
+ const rest = fmMatch[2] || "";
26
+ const lines = rawFm.split(/\r?\n/);
27
+ const sanitizedLines = lines.map((line) => {
28
+ const fieldMatch = line.match(/^([a-zA-Z0-9_-]+):\s*(.+)$/);
29
+ if (fieldMatch) {
30
+ const [, key, val] = fieldMatch;
31
+ const trimmed = val.trim();
32
+ // If value is not already quoted and not a YAML block indicator/collection opening or boolean/number
33
+ if (
34
+ trimmed &&
35
+ trimmed !== "true" &&
36
+ trimmed !== "false" &&
37
+ trimmed !== "null" &&
38
+ !trimmed.startsWith('"') &&
39
+ !trimmed.startsWith("'") &&
40
+ !trimmed.startsWith("[") &&
41
+ !trimmed.startsWith("{") &&
42
+ trimmed !== ">" &&
43
+ trimmed !== "|" &&
44
+ trimmed !== ">-" &&
45
+ trimmed !== "|-" &&
46
+ !/^-?\d+(?:\.\d+)?$/.test(trimmed)
47
+ ) {
48
+ return `${key}: ${JSON.stringify(trimmed)}`;
49
+ }
50
+ }
51
+ return line;
52
+ });
53
+
54
+ try {
55
+ const sanitizedSource = `---\n${sanitizedLines.join("\n")}\n---\n${rest}`;
56
+ const parsed = matter(sanitizedSource);
57
+ return {
58
+ data:
59
+ parsed.data && typeof parsed.data === "object" ? parsed.data : {},
60
+ content: parsed.content || "",
61
+ };
62
+ } catch {
63
+ // Continue to fallback
64
+ }
65
+
66
+ // Attempt 2: Line-by-line fallback extraction for essential frontmatter fields
67
+ const fallbackData: Record<string, unknown> = {};
68
+ const nameMatch = rawFm.match(/^name:\s*["']?([^"'\r\n]+)["']?/m);
69
+ if (nameMatch) {
70
+ fallbackData.name = nameMatch[1].trim();
71
+ }
72
+
73
+ const descMatch = rawFm.match(/^description:\s*(.+)$/m);
74
+ if (descMatch) {
75
+ let desc = descMatch[1].trim();
76
+ if (
77
+ (desc.startsWith('"') && desc.endsWith('"')) ||
78
+ (desc.startsWith("'") && desc.endsWith("'"))
79
+ ) {
80
+ desc = desc.slice(1, -1);
81
+ }
82
+ fallbackData.description = desc;
83
+ }
84
+
85
+ const userInvocableMatch = rawFm.match(
86
+ /^user-invocable:\s*(true|false)/im,
87
+ );
88
+ if (userInvocableMatch) {
89
+ fallbackData["user-invocable"] =
90
+ userInvocableMatch[1].toLowerCase() === "true";
91
+ }
92
+
93
+ const disableModelMatch = rawFm.match(
94
+ /^disable-model-invocation:\s*(true|false)/im,
95
+ );
96
+ if (disableModelMatch) {
97
+ fallbackData["disable-model-invocation"] =
98
+ disableModelMatch[1].toLowerCase() === "true";
99
+ }
100
+
101
+ const toolsMatch = rawFm.match(
102
+ /^allowed-tools:\s*["']?([^"'\r\n]+)["']?/m,
103
+ );
104
+ if (toolsMatch) {
105
+ fallbackData["allowed-tools"] = toolsMatch[1].trim();
106
+ }
107
+
108
+ // Check for bullet list allowed-tools
109
+ const toolListMatch = rawFm.match(
110
+ /allowed-tools:\s*\n((?:\s*-\s*[^\r\n]+\r?\n?)+)/m,
111
+ );
112
+ if (toolListMatch) {
113
+ const tools = toolListMatch[1]
114
+ .split(/\r?\n/)
115
+ .map((l) => l.replace(/^\s*-\s*/, "").trim())
116
+ .filter(Boolean);
117
+ if (tools.length > 0) {
118
+ fallbackData["allowed-tools"] = tools;
119
+ }
120
+ }
121
+
122
+ return { data: fallbackData, content: rest };
123
+ }
124
+
125
+ return { data: {}, content: source };
126
+ }
127
+ }
128
+
129
+ function extractAllowedTools(raw: unknown): string | undefined {
130
+ if (typeof raw === "string") {
131
+ const trimmed = raw.trim();
132
+ return trimmed.length > 0 ? trimmed : undefined;
133
+ }
134
+ if (Array.isArray(raw)) {
135
+ const tools = raw
136
+ .filter((item): item is string => typeof item === "string")
137
+ .map((item) => item.trim())
138
+ .filter((item) => item.length > 0);
139
+ return tools.length > 0 ? tools.join(" ") : undefined;
140
+ }
141
+ return undefined;
142
+ }
143
+
8
144
  export function parseSkill(path: string, source: string): SkillRecord {
9
- const parsed = matter(source);
10
- const data =
11
- parsed.data && typeof parsed.data === "object" ? parsed.data : {};
145
+ const parsed = parseFrontmatterResiliently(source);
146
+ const data = parsed.data;
12
147
  const name = typeof data.name === "string" ? data.name.trim() : "";
13
148
  const description =
14
149
  typeof data.description === "string" ? data.description.trim() : "";
@@ -36,31 +171,45 @@ export function parseSkill(path: string, source: string): SkillRecord {
36
171
  ? (data.metadata as Record<string, unknown>)
37
172
  : undefined;
38
173
 
39
- const metadataEntries = rawMetadata
40
- ? Object.entries(rawMetadata).filter(
41
- ([key, value]) =>
42
- key !== "execution" && value !== null && typeof value !== "object",
43
- )
44
- : [];
174
+ const allowedToolsRaw =
175
+ extractAllowedTools(rawMetadata?.["allowed-tools"]) ||
176
+ extractAllowedTools(rawMetadata?.["allowedTools"]) ||
177
+ extractAllowedTools(data["allowed-tools"]) ||
178
+ extractAllowedTools(data["allowedTools"]);
179
+
180
+ const metadataEntries: [string, string][] = [];
181
+ if (rawMetadata) {
182
+ for (const [key, value] of Object.entries(rawMetadata)) {
183
+ if (key === "execution" || value === null || value === undefined) {
184
+ continue;
185
+ }
186
+ if (key === "allowed-tools" || key === "allowedTools") {
187
+ if (allowedToolsRaw) {
188
+ metadataEntries.push([key, allowedToolsRaw]);
189
+ }
190
+ } else if (
191
+ typeof value === "string" ||
192
+ typeof value === "number" ||
193
+ typeof value === "boolean"
194
+ ) {
195
+ metadataEntries.push([key, String(value)]);
196
+ } else if (Array.isArray(value)) {
197
+ const stringItems = value
198
+ .filter((item): item is string => typeof item === "string")
199
+ .map((item) => item.trim())
200
+ .filter(Boolean);
201
+ if (stringItems.length > 0) {
202
+ metadataEntries.push([key, stringItems.join(" ")]);
203
+ }
204
+ }
205
+ }
206
+ }
45
207
 
46
208
  const metadata =
47
209
  metadataEntries.length > 0
48
- ? Object.fromEntries(
49
- metadataEntries.map(([key, value]) => [key, String(value)]),
50
- )
210
+ ? Object.fromEntries(metadataEntries)
51
211
  : undefined;
52
212
 
53
- const allowedToolsRaw =
54
- (rawMetadata &&
55
- (typeof rawMetadata["allowed-tools"] === "string"
56
- ? rawMetadata["allowed-tools"]
57
- : typeof rawMetadata["allowedTools"] === "string"
58
- ? rawMetadata["allowedTools"]
59
- : undefined)) ||
60
- (typeof data["allowed-tools"] === "string"
61
- ? data["allowed-tools"]
62
- : undefined);
63
-
64
213
  const execution = rawMetadata?.execution;
65
214
 
66
215
  let parsedExecution;
@@ -119,10 +268,21 @@ export function parseSkill(path: string, source: string): SkillRecord {
119
268
  : {}),
120
269
  ...(typeof data["user-invocable"] === "boolean"
121
270
  ? { userInvocable: data["user-invocable"] }
122
- : {}),
271
+ : typeof data["user-invocable"] === "string" &&
272
+ (data["user-invocable"].toLowerCase() === "true" ||
273
+ data["user-invocable"].toLowerCase() === "false")
274
+ ? { userInvocable: data["user-invocable"].toLowerCase() === "true" }
275
+ : {}),
123
276
  ...(typeof data["disable-model-invocation"] === "boolean"
124
277
  ? { disableModelInvocation: data["disable-model-invocation"] }
125
- : {}),
278
+ : typeof data["disable-model-invocation"] === "string" &&
279
+ (data["disable-model-invocation"].toLowerCase() === "true" ||
280
+ data["disable-model-invocation"].toLowerCase() === "false")
281
+ ? {
282
+ disableModelInvocation:
283
+ data["disable-model-invocation"].toLowerCase() === "true",
284
+ }
285
+ : {}),
126
286
  ...(parsedExecution ? { execution: parsedExecution } : {}),
127
287
  body: parsed.content.trim(),
128
288
  path,
@@ -278,10 +278,10 @@ export const search_files: ToolDefinition = {
278
278
  export const send_file: ToolDefinition = {
279
279
  name: "send_file",
280
280
  description:
281
- "Send a workspace file directly to the current peer over the P2P (PeerJS/WebRTC) data channel. " +
282
- "Use this when the user is in a peer conversation and explicitly asks to send or transfer a file to their peer. " +
283
- "Do NOT use this for local-browser or non-peer conversations — it only works when the active conversation " +
284
- "is a peer: group. The file is read from the current group workspace and transferred in binary chunks " +
281
+ "Send a workspace file directly to connected peer(s) over the P2P (PeerJS/WebRTC) data channel. " +
282
+ "Use this when the user is in a peer conversation or room and asks to send or transfer a file. " +
283
+ "Do NOT use this for local-browser or other non-peer conversations — it only works when the active conversation " +
284
+ "is a peer or room session (peer: or room: group). The file is read from the current group workspace and transferred in binary chunks " +
285
285
  "so there is no size limit.",
286
286
  input_schema: {
287
287
  type: "object",
@@ -1,4 +1,3 @@
1
- // @ts-nocheck
2
1
  import { jest } from "@jest/globals";
3
2
 
4
3
  describe("executeSpawnSubagentTool", () => {
@@ -131,7 +130,7 @@ describe("executeSpawnSubagentTool", () => {
131
130
  });
132
131
 
133
132
  it("calls handleInvoke with a subagent groupId starting with 'subagent:'", async () => {
134
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
133
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
135
134
  // Simulate the subagent posting a response message
136
135
  const collectors = mockRegisterSubagentCollector.mock.calls;
137
136
  const lastCall = collectors[collectors.length - 1];
@@ -161,7 +160,7 @@ describe("executeSpawnSubagentTool", () => {
161
160
  it("uses a unique ulid for subagent groupId", async () => {
162
161
  mockUlid.mockReturnValueOnce("ulid-aaa").mockReturnValueOnce("ulid-bbb");
163
162
 
164
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
163
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
165
164
  const collectors = mockRegisterSubagentCollector.mock.calls;
166
165
  const lastCall = collectors[collectors.length - 1];
167
166
  if (lastCall) {
@@ -186,7 +185,7 @@ describe("executeSpawnSubagentTool", () => {
186
185
  });
187
186
 
188
187
  it("excludes spawn_subagent from the subagent's tool list to prevent recursion", async () => {
189
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
188
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
190
189
  const collectors = mockRegisterSubagentCollector.mock.calls;
191
190
  const lastCall = collectors[collectors.length - 1];
192
191
  if (lastCall) {
@@ -212,7 +211,7 @@ describe("executeSpawnSubagentTool", () => {
212
211
  });
213
212
 
214
213
  it("uses the provided tools list when specified in input", async () => {
215
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
214
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
216
215
  const collectors = mockRegisterSubagentCollector.mock.calls;
217
216
  const lastCall = collectors[collectors.length - 1];
218
217
  if (lastCall) {
@@ -238,7 +237,7 @@ describe("executeSpawnSubagentTool", () => {
238
237
  });
239
238
 
240
239
  it("in manual mode, overrides model when specified as pinned model", async () => {
241
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
240
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
242
241
  const collectors = mockRegisterSubagentCollector.mock.calls;
243
242
  const lastCall = collectors[collectors.length - 1];
244
243
  if (lastCall) {
@@ -267,7 +266,7 @@ describe("executeSpawnSubagentTool", () => {
267
266
  });
268
267
 
269
268
  it("in automatic mode, ignores LLM-emitted model and falls back to parent ctx model", async () => {
270
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
269
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
271
270
  const collectors = mockRegisterSubagentCollector.mock.calls;
272
271
  const lastCall = collectors[collectors.length - 1];
273
272
  if (lastCall) {
@@ -299,7 +298,7 @@ describe("executeSpawnSubagentTool", () => {
299
298
  });
300
299
 
301
300
  it("clamps subagent max tokens by selected model limit", async () => {
302
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
301
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
303
302
  const collectors = mockRegisterSubagentCollector.mock.calls;
304
303
  const lastCall = collectors[collectors.length - 1];
305
304
  if (lastCall) {
@@ -329,7 +328,7 @@ describe("executeSpawnSubagentTool", () => {
329
328
  });
330
329
 
331
330
  it("uses conversation subagent max tokens override but keeps model-safe clamp", async () => {
332
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
331
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
333
332
  const collectors = mockRegisterSubagentCollector.mock.calls;
334
333
  const lastCall = collectors[collectors.length - 1];
335
334
  if (lastCall) {
@@ -360,7 +359,7 @@ describe("executeSpawnSubagentTool", () => {
360
359
  });
361
360
 
362
361
  it("uses the selected subagent model limit when auto max tokens is enabled", async () => {
363
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
362
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
364
363
  const collectors = mockRegisterSubagentCollector.mock.calls;
365
364
  const lastCall = collectors[collectors.length - 1];
366
365
  if (lastCall) {
@@ -391,7 +390,7 @@ describe("executeSpawnSubagentTool", () => {
391
390
  });
392
391
 
393
392
  it("in manual mode, overrides provider to a different provider with its api key", async () => {
394
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
393
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
395
394
  const collectors = mockRegisterSubagentCollector.mock.calls;
396
395
  const lastCall = collectors[collectors.length - 1];
397
396
  if (lastCall) {
@@ -421,7 +420,7 @@ describe("executeSpawnSubagentTool", () => {
421
420
  });
422
421
 
423
422
  it("in automatic mode, ignores LLM-emitted provider and falls back to parent ctx provider", async () => {
424
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
423
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
425
424
  const collectors = mockRegisterSubagentCollector.mock.calls;
426
425
  const lastCall = collectors[collectors.length - 1];
427
426
  if (lastCall) {
@@ -452,7 +451,7 @@ describe("executeSpawnSubagentTool", () => {
452
451
  });
453
452
 
454
453
  it("in automatic mode, maps profile 'fast', 'smart', 'powerful' to their configured provider/model", async () => {
455
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
454
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
456
455
  const collectors = mockRegisterSubagentCollector.mock.calls;
457
456
  const lastCall = collectors[collectors.length - 1];
458
457
  if (lastCall) {
@@ -507,7 +506,7 @@ describe("executeSpawnSubagentTool", () => {
507
506
  });
508
507
 
509
508
  it("in automatic mode, falls back to parent model/provider if profile is not configured or current", async () => {
510
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
509
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
511
510
  const collectors = mockRegisterSubagentCollector.mock.calls;
512
511
  const lastCall = collectors[collectors.length - 1];
513
512
  if (lastCall) {
@@ -552,7 +551,7 @@ describe("executeSpawnSubagentTool", () => {
552
551
  });
553
552
 
554
553
  it("in manual mode, ignores profile selection and uses pinned model/provider", async () => {
555
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
554
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
556
555
  const collectors = mockRegisterSubagentCollector.mock.calls;
557
556
  const lastCall = collectors[collectors.length - 1];
558
557
  if (lastCall) {
@@ -609,7 +608,7 @@ describe("executeSpawnSubagentTool", () => {
609
608
  return undefined;
610
609
  });
611
610
 
612
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
611
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
613
612
  const collectors = mockRegisterSubagentCollector.mock.calls;
614
613
  const lastCall = collectors[collectors.length - 1];
615
614
  if (lastCall) {
@@ -642,7 +641,7 @@ describe("executeSpawnSubagentTool", () => {
642
641
  });
643
642
 
644
643
  it("forwards storageHandle from parent context", async () => {
645
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
644
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
646
645
  const collectors = mockRegisterSubagentCollector.mock.calls;
647
646
  const lastCall = collectors[collectors.length - 1];
648
647
  if (lastCall) {
@@ -679,7 +678,7 @@ describe("executeSpawnSubagentTool", () => {
679
678
  return undefined;
680
679
  });
681
680
 
682
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
681
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
683
682
  const collectors = mockRegisterSubagentCollector.mock.calls;
684
683
  const lastCall = collectors[collectors.length - 1];
685
684
  if (lastCall) {
@@ -716,7 +715,7 @@ describe("executeSpawnSubagentTool", () => {
716
715
  return undefined;
717
716
  });
718
717
 
719
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
718
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
720
719
  const collectors = mockRegisterSubagentCollector.mock.calls;
721
720
  const lastCall = collectors[collectors.length - 1];
722
721
  if (lastCall) {
@@ -754,7 +753,7 @@ describe("executeSpawnSubagentTool", () => {
754
753
  });
755
754
 
756
755
  mockUlid.mockReturnValueOnce("iso-123");
757
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
756
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
758
757
  const collectors = mockRegisterSubagentCollector.mock.calls;
759
758
  const lastCall = collectors[collectors.length - 1];
760
759
  if (lastCall) {
@@ -779,7 +778,7 @@ describe("executeSpawnSubagentTool", () => {
779
778
  });
780
779
 
781
780
  it("uses conversation-level manual subagent provider/model defaults when tool input omits them", async () => {
782
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
781
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
783
782
  const collectors = mockRegisterSubagentCollector.mock.calls;
784
783
  const lastCall = collectors[collectors.length - 1];
785
784
  if (lastCall) {
@@ -809,7 +808,7 @@ describe("executeSpawnSubagentTool", () => {
809
808
  });
810
809
 
811
810
  it("manual subagent defaults override per-tool provider/model inputs", async () => {
812
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
811
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
813
812
  const collectors = mockRegisterSubagentCollector.mock.calls;
814
813
  const lastCall = collectors[collectors.length - 1];
815
814
  if (lastCall) {
@@ -947,7 +946,7 @@ describe("executeSpawnSubagentTool", () => {
947
946
  });
948
947
 
949
948
  it("overrides system_prompt when specified", async () => {
950
- mockHandleInvoke.mockImplementation((_db: any, payload: any) => {
949
+ mockHandleInvoke.mockImplementation((_db: any, _payload: any) => {
951
950
  const collectors = mockRegisterSubagentCollector.mock.calls;
952
951
  const lastCall = collectors[collectors.length - 1];
953
952
  if (lastCall) {