shadow-claw 1.59.6 → 1.60.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 (358) hide show
  1. package/.well-known/mcp/server-card.json +1 -1
  2. package/.well-known/mcp.json +1 -1
  3. package/README.md +6 -2
  4. package/dist/cli/build/build.js +1 -1
  5. package/dist/cli/chunk-3C5izdQW.js +1 -0
  6. package/dist/cli/chunk-B-75h9gX.js +1 -0
  7. package/dist/cli/{chunk-C9o6lXP3.js → chunk-B7Kn-otm.js} +1 -1
  8. package/dist/cli/{chunk-YX32FcN7.js → chunk-BBczgswQ.js} +1 -1
  9. package/dist/cli/{chunk-DcNxjqH6.js → chunk-BE-lYWcn.js} +1 -1
  10. package/dist/cli/{chunk-DJqHK-qS.js → chunk-BECr0WxI.js} +11 -11
  11. package/dist/cli/chunk-BEz1PD1_.js +1 -0
  12. package/dist/cli/chunk-BLzI1Fp2.js +1 -0
  13. package/dist/cli/{chunk-yiVdvGCJ.js → chunk-BVSC1MNQ.js} +11 -11
  14. package/dist/cli/{chunk-CX2itile.js → chunk-BdWcep6o.js} +1 -1
  15. package/dist/cli/{chunk-DLde6nuO.js → chunk-BfTpnSS4.js} +1 -1
  16. package/dist/cli/{chunk-D2_eAO83.js → chunk-BgvqTf7w.js} +1 -1
  17. package/dist/cli/chunk-BwsJfUT3.js +1 -0
  18. package/dist/cli/{chunk--PFY91kE.js → chunk-C9b4b7c_.js} +1 -1
  19. package/dist/cli/{chunk-D3y7h9Xe.js → chunk-CAw9XYFe.js} +1 -1
  20. package/dist/cli/chunk-CFCcbFs2.js +396 -0
  21. package/dist/cli/{chunk-Cnjb8Usu.js → chunk-CTarF4FC.js} +1 -1
  22. package/dist/cli/{chunk-DM4xsTry.js → chunk-Cbq5hpjb.js} +4 -4
  23. package/dist/cli/chunk-CjTjKy_v.js +310 -0
  24. package/dist/cli/chunk-Cjyu4cr_.js +36 -0
  25. package/dist/cli/{chunk-DUGZPka_.js → chunk-ClMKygjZ.js} +1 -1
  26. package/dist/cli/chunk-Cppnq1KF.js +1 -0
  27. package/dist/cli/{chunk-DvemF16v.js → chunk-D9QCNFMO.js} +1 -1
  28. package/dist/cli/chunk-DB21BMqt.js +7 -0
  29. package/dist/cli/{chunk-_Vo-o_e3.js → chunk-DHoIWvCc.js} +1 -1
  30. package/dist/cli/chunk-DZEN9T5y.js +1 -0
  31. package/dist/cli/{chunk-5rLO4DWS.js → chunk-Dl14OyYO.js} +9 -9
  32. package/dist/cli/chunk-Dl_vv0dI.js +1 -0
  33. package/dist/cli/chunk-Dpmfhlyl.js +1 -0
  34. package/dist/cli/{chunk-BrR1DOBS.js → chunk-Du7Xtucq.js} +1 -1
  35. package/dist/cli/{chunk-Bc_weULz.js → chunk-DxcDFUi_.js} +1 -1
  36. package/dist/cli/{chunk-Dt7-hzJU.js → chunk-DyyEWbV7.js} +1 -1
  37. package/dist/cli/chunk-N0x3mXU0.js +1 -0
  38. package/dist/cli/{chunk-CGoE4llV.js → chunk-V-w0Bata.js} +1 -1
  39. package/dist/cli/{chunk-C8DBACtx.js → chunk-ZxDxSSn-.js} +1 -1
  40. package/dist/cli/chunk-lPvFUkd5.js +7 -0
  41. package/dist/cli/{chunk-Ctg5L55n.js → chunk-n5s-sCdU.js} +1 -1
  42. package/dist/cli/{chunk-Dw8GndPD.js → chunk-nD9VPVMq.js} +1 -1
  43. package/dist/cli/{chunk-Cq_kQohv.js → chunk-rFuy8aS_.js} +1 -1
  44. package/dist/cli/{chunk-Bq38OubR.js → chunk-wjM6JXWa.js} +1 -1
  45. package/dist/cli/{chunk-3wTukVof.js → chunk-zcES9rut.js} +1 -1
  46. package/dist/cli/cli.js +3 -3
  47. package/dist/headless-agent.js +2 -2
  48. package/dist/lib/{app-routes-DJdIjp2V.js → app-routes-BXiRvlNl.js} +7 -25
  49. package/dist/lib/{app-routes-DJdIjp2V.js.map → app-routes-BXiRvlNl.js.map} +1 -1
  50. package/dist/lib/{attachment-capabilities-Dbb-4ZP5.js → attachment-capabilities-BjkEPip8.js} +2 -2
  51. package/dist/lib/{attachment-capabilities-Dbb-4ZP5.js.map → attachment-capabilities-BjkEPip8.js.map} +1 -1
  52. package/dist/lib/{channel-Dlru5ofR.js → channel-DB77spML.js} +3 -3
  53. package/dist/lib/{channel-Dlru5ofR.js.map → channel-DB77spML.js.map} +1 -1
  54. package/dist/lib/{chat-template-BuuLY8l7.js → chat-template-DPEKGJhB.js} +2 -2
  55. package/dist/lib/{chat-template-BuuLY8l7.js.map → chat-template-DPEKGJhB.js.map} +1 -1
  56. package/dist/lib/{compact-context-BtR55YPU.js → compact-context-Q9t9aL1e.js} +19 -19
  57. package/dist/lib/{compact-context-BtR55YPU.js.map → compact-context-Q9t9aL1e.js.map} +1 -1
  58. package/dist/lib/components/common/shadow-claw-provider-model-picker.js +1 -1
  59. package/dist/lib/components/index.js +27 -27
  60. package/dist/lib/components/settings/shadow-claw-accounts.js +1 -1
  61. package/dist/lib/components/settings/shadow-claw-channel-config.js +1 -1
  62. package/dist/lib/components/settings/shadow-claw-control-plane.js +1 -1
  63. package/dist/lib/components/settings/shadow-claw-git.js +1 -1
  64. package/dist/lib/components/settings/shadow-claw-integrations.js +1 -1
  65. package/dist/lib/components/settings/shadow-claw-llm.js +1 -1
  66. package/dist/lib/components/settings/shadow-claw-mcp-remote.js +1 -1
  67. package/dist/lib/components/settings/shadow-claw-networking.js +1 -1
  68. package/dist/lib/components/settings/shadow-claw-notifications.js +1 -1
  69. package/dist/lib/components/settings/shadow-claw-peerjs.js +1 -1
  70. package/dist/lib/components/settings/shadow-claw-storage.js +1 -1
  71. package/dist/lib/components/settings/shadow-claw-task-server.js +1 -1
  72. package/dist/lib/components/settings/shadow-claw-webvm.js +1 -1
  73. package/dist/lib/components/shadow-claw-a2ui.js +1 -1
  74. package/dist/lib/components/shadow-claw-accounts.js +1 -1
  75. package/dist/lib/components/shadow-claw-channel-config.js +1 -1
  76. package/dist/lib/components/shadow-claw-channels.js +1 -1
  77. package/dist/lib/components/shadow-claw-chat.js +1 -1
  78. package/dist/lib/components/shadow-claw-control-plane.js +1 -1
  79. package/dist/lib/components/shadow-claw-conversations.js +1 -1
  80. package/dist/lib/components/shadow-claw-file-viewer.js +1 -1
  81. package/dist/lib/components/shadow-claw-files.js +1 -1
  82. package/dist/lib/components/shadow-claw-git.js +1 -1
  83. package/dist/lib/components/shadow-claw-integrations.js +1 -1
  84. package/dist/lib/components/shadow-claw-llm.js +1 -1
  85. package/dist/lib/components/shadow-claw-mcp-remote.js +1 -1
  86. package/dist/lib/components/shadow-claw-networking.js +1 -1
  87. package/dist/lib/components/shadow-claw-notifications.js +1 -1
  88. package/dist/lib/components/shadow-claw-page-header.js +1 -1
  89. package/dist/lib/components/shadow-claw-pages.js +1 -1
  90. package/dist/lib/components/shadow-claw-peerjs.js +1 -1
  91. package/dist/lib/components/shadow-claw-provider-model-picker.js +1 -1
  92. package/dist/lib/components/shadow-claw-settings.js +1 -1
  93. package/dist/lib/components/shadow-claw-storage.js +1 -1
  94. package/dist/lib/components/shadow-claw-task-server.js +1 -1
  95. package/dist/lib/components/shadow-claw-tasks.js +1 -1
  96. package/dist/lib/components/shadow-claw-terminal.js +1 -1
  97. package/dist/lib/components/shadow-claw-tools.js +1 -1
  98. package/dist/lib/components/shadow-claw-webvm.js +1 -1
  99. package/dist/lib/components/shadow-claw.js +1 -1
  100. package/dist/lib/{config-DxNI3TlW.js → config-BrHR97zt.js} +2 -2
  101. package/dist/lib/{config-DxNI3TlW.js.map → config-BrHR97zt.js.map} +1 -1
  102. package/dist/lib/{configure-peer-js-ChDhOZU4.js → configure-peer-js-CgFiwoxY.js} +3 -3
  103. package/dist/lib/{configure-peer-js-ChDhOZU4.js.map → configure-peer-js-CgFiwoxY.js.map} +1 -1
  104. package/dist/lib/{connections-DC4NZkJE.js → connections-C1FWsBsE.js} +2 -2
  105. package/dist/lib/{connections-DC4NZkJE.js.map → connections-C1FWsBsE.js.map} +1 -1
  106. package/dist/lib/content/build-attachment-content-blocks.d.ts +2 -0
  107. package/dist/lib/{credentials-5vpz0XPk.js → credentials-CZbngHXW.js} +2 -2
  108. package/dist/lib/{credentials-5vpz0XPk.js.map → credentials-CZbngHXW.js.map} +1 -1
  109. package/dist/lib/{discover-skills-CD0sKvAI.js → discover-skills-CXyaWHKi.js} +13 -13
  110. package/dist/lib/{discover-skills-CD0sKvAI.js.map → discover-skills-CXyaWHKi.js.map} +1 -1
  111. package/dist/lib/{download-group-file-Dk3qaxhJ.js → download-group-file-D0wgg10Q.js} +2 -2
  112. package/dist/lib/{download-group-file-Dk3qaxhJ.js.map → download-group-file-D0wgg10Q.js.map} +1 -1
  113. package/dist/lib/{file-viewer-B4pRW-_G.js → file-viewer-DOfvX6yy.js} +5 -5
  114. package/dist/lib/{file-viewer-B4pRW-_G.js.map → file-viewer-DOfvX6yy.js.map} +1 -1
  115. package/dist/lib/{get-or-create-subscriber-id-HCcgDEPz.js → get-or-create-subscriber-id-wyzaML7Z.js} +2 -2
  116. package/dist/lib/{get-or-create-subscriber-id-HCcgDEPz.js.map → get-or-create-subscriber-id-wyzaML7Z.js.map} +1 -1
  117. package/dist/lib/{git-B3Q1euc5.js → git-CogDRlEz.js} +5 -5
  118. package/dist/lib/{git-B3Q1euc5.js.map → git-CogDRlEz.js.map} +1 -1
  119. package/dist/lib/{iframe-bridge-scripts-D8iuFhUk.js → iframe-bridge-scripts-Dx825LLG.js} +2 -2
  120. package/dist/lib/{iframe-bridge-scripts-D8iuFhUk.js.map → iframe-bridge-scripts-Dx825LLG.js.map} +1 -1
  121. package/dist/lib/index.js +28 -28
  122. package/dist/lib/{init-chat-split-resize-B0ODULx9.js → init-chat-split-resize-Cc0bd2z9.js} +2 -2
  123. package/dist/lib/{init-chat-split-resize-B0ODULx9.js.map → init-chat-split-resize-Cc0bd2z9.js.map} +1 -1
  124. package/dist/lib/{init-control-plane-C1FRRmjC.js → init-control-plane-CEGdzgWX.js} +15 -15
  125. package/dist/lib/{init-control-plane-C1FRRmjC.js.map → init-control-plane-CEGdzgWX.js.map} +1 -1
  126. package/dist/lib/{invoke-agent-CzN7sVh-.js → invoke-agent-cac3gCsj.js} +11 -11
  127. package/dist/lib/{invoke-agent-CzN7sVh-.js.map → invoke-agent-cac3gCsj.js.map} +1 -1
  128. package/dist/lib/{markdown-mbNo7cV3.js → markdown--6vTAPEH.js} +2 -2
  129. package/dist/lib/{markdown-mbNo7cV3.js.map → markdown--6vTAPEH.js.map} +1 -1
  130. package/dist/lib/{mcp-reconnect-3T7yWGEY.js → mcp-reconnect-BeqQvNWO.js} +3 -3
  131. package/dist/lib/{mcp-reconnect-3T7yWGEY.js.map → mcp-reconnect-BeqQvNWO.js.map} +1 -1
  132. package/dist/lib/{model-ranking-DGNSWYwN.js → model-ranking-BhsJV7vb.js} +2 -2
  133. package/dist/lib/{model-ranking-DGNSWYwN.js.map → model-ranking-BhsJV7vb.js.map} +1 -1
  134. package/dist/lib/{move-group-entry-NMTJ59M9.js → move-group-entry-D8dptMg0.js} +5 -5
  135. package/dist/lib/{move-group-entry-NMTJ59M9.js.map → move-group-entry-D8dptMg0.js.map} +1 -1
  136. package/dist/lib/{orchestrator-B8FV1V7x.js → orchestrator-BBAwy9Nm.js} +24 -24
  137. package/dist/lib/{orchestrator-B8FV1V7x.js.map → orchestrator-BBAwy9Nm.js.map} +1 -1
  138. package/dist/lib/{orchestrator-i_QJ-o22.js → orchestrator-cRBe3lhq.js} +11 -11
  139. package/dist/lib/orchestrator-cRBe3lhq.js.map +1 -0
  140. package/dist/lib/{parse-path-DPCn-HwI.js → parse-path-BOHQP_IQ.js} +3 -3
  141. package/dist/lib/{parse-path-DPCn-HwI.js.map → parse-path-BOHQP_IQ.js.map} +1 -1
  142. package/dist/lib/{peerjs-z5zeioPV.js → peerjs-BLg8aGUj.js} +8 -8
  143. package/dist/lib/{peerjs-z5zeioPV.js.map → peerjs-BLg8aGUj.js.map} +1 -1
  144. package/dist/lib/{process-peer-query-param-CJp7w7AU.js → process-peer-query-param-BnsVnxzH.js} +5 -5
  145. package/dist/lib/{process-peer-query-param-CJp7w7AU.js.map → process-peer-query-param-BnsVnxzH.js.map} +1 -1
  146. package/dist/lib/{process-pending-shared-payloads-B6_TlBFA.js → process-pending-shared-payloads-DBZfZOOa.js} +4 -4
  147. package/dist/lib/{process-pending-shared-payloads-B6_TlBFA.js.map → process-pending-shared-payloads-DBZfZOOa.js.map} +1 -1
  148. package/dist/lib/{process-room-query-param-C3FFGGn6.js → process-room-query-param-B8EYg_-r.js} +4 -4
  149. package/dist/lib/{process-room-query-param-C3FFGGn6.js.map → process-room-query-param-B8EYg_-r.js.map} +1 -1
  150. package/dist/lib/{provider-DcQZypu5.js → provider-BC9KPI14.js} +3 -3
  151. package/dist/lib/{provider-DcQZypu5.js.map → provider-BC9KPI14.js.map} +1 -1
  152. package/dist/lib/{push-client-Cx5rMs6J.js → push-client-CAm6UMvE.js} +5 -5
  153. package/dist/lib/{push-client-Cx5rMs6J.js.map → push-client-CAm6UMvE.js.map} +1 -1
  154. package/dist/lib/{read-group-file-bytes-CXOG_YyM.js → read-group-file-bytes-UQIk1eJG.js} +2 -2
  155. package/dist/lib/{read-group-file-bytes-CXOG_YyM.js.map → read-group-file-bytes-UQIk1eJG.js.map} +1 -1
  156. package/dist/lib/{rooms-CwlkYLDU.js → rooms-Dzphx3rK.js} +2 -2
  157. package/dist/lib/{rooms-CwlkYLDU.js.map → rooms-Dzphx3rK.js.map} +1 -1
  158. package/dist/lib/{shadow-claw-DoQ7fgl5.js → shadow-claw-CGl8tXtG.js} +17 -20
  159. package/dist/lib/shadow-claw-CGl8tXtG.js.map +1 -0
  160. package/dist/lib/{shadow-claw-a2ui-Br6qJMs1.js → shadow-claw-a2ui-lG0vQbW8.js} +2 -2
  161. package/dist/lib/{shadow-claw-a2ui-Br6qJMs1.js.map → shadow-claw-a2ui-lG0vQbW8.js.map} +1 -1
  162. package/dist/lib/{shadow-claw-accounts-BTDILfWw.js → shadow-claw-accounts-CkqyCxwp.js} +3 -3
  163. package/dist/lib/{shadow-claw-accounts-BTDILfWw.js.map → shadow-claw-accounts-CkqyCxwp.js.map} +1 -1
  164. package/dist/lib/{shadow-claw-channel-config-IKiL34tI.js → shadow-claw-channel-config-BNIWCdsL.js} +4 -4
  165. package/dist/lib/{shadow-claw-channel-config-IKiL34tI.js.map → shadow-claw-channel-config-BNIWCdsL.js.map} +1 -1
  166. package/dist/lib/{shadow-claw-channels-JgEzuHWK.js → shadow-claw-channels-C2QSn4Ew.js} +3 -3
  167. package/dist/lib/{shadow-claw-channels-JgEzuHWK.js.map → shadow-claw-channels-C2QSn4Ew.js.map} +1 -1
  168. package/dist/lib/{shadow-claw-chat-SGUDT31r.js → shadow-claw-chat-Wx3y9y6c.js} +15 -15
  169. package/dist/lib/{shadow-claw-chat-SGUDT31r.js.map → shadow-claw-chat-Wx3y9y6c.js.map} +1 -1
  170. package/dist/lib/{shadow-claw-control-plane-CRWFZ3vD.js → shadow-claw-control-plane-D5E4cFGu.js} +7 -7
  171. package/dist/lib/{shadow-claw-control-plane-CRWFZ3vD.js.map → shadow-claw-control-plane-D5E4cFGu.js.map} +1 -1
  172. package/dist/lib/{shadow-claw-conversations-D23GJ7qo.js → shadow-claw-conversations-BtDv7GRW.js} +7 -7
  173. package/dist/lib/{shadow-claw-conversations-D23GJ7qo.js.map → shadow-claw-conversations-BtDv7GRW.js.map} +1 -1
  174. package/dist/lib/{shadow-claw-file-viewer-C1V8WTiU.js → shadow-claw-file-viewer-CG40kwWV.js} +10 -10
  175. package/dist/lib/{shadow-claw-file-viewer-C1V8WTiU.js.map → shadow-claw-file-viewer-CG40kwWV.js.map} +1 -1
  176. package/dist/lib/{shadow-claw-files-DN7irmE1.js → shadow-claw-files-BOUULrlX.js} +11 -11
  177. package/dist/lib/{shadow-claw-files-DN7irmE1.js.map → shadow-claw-files-BOUULrlX.js.map} +1 -1
  178. package/dist/lib/{shadow-claw-git-D-1oIh65.js → shadow-claw-git-BeHV73_9.js} +6 -6
  179. package/dist/lib/{shadow-claw-git-D-1oIh65.js.map → shadow-claw-git-BeHV73_9.js.map} +1 -1
  180. package/dist/lib/{shadow-claw-integrations-CZjnm7cM.js → shadow-claw-integrations-RZZ-m-Id.js} +4 -4
  181. package/dist/lib/{shadow-claw-integrations-CZjnm7cM.js.map → shadow-claw-integrations-RZZ-m-Id.js.map} +1 -1
  182. package/dist/lib/{shadow-claw-llm-4Gefh5FN.js → shadow-claw-llm-KONyWKZM.js} +9 -9
  183. package/dist/lib/{shadow-claw-llm-4Gefh5FN.js.map → shadow-claw-llm-KONyWKZM.js.map} +1 -1
  184. package/dist/lib/{shadow-claw-mcp-remote-B9ssb3YV.js → shadow-claw-mcp-remote-BKFROurv.js} +4 -4
  185. package/dist/lib/{shadow-claw-mcp-remote-B9ssb3YV.js.map → shadow-claw-mcp-remote-BKFROurv.js.map} +1 -1
  186. package/dist/lib/{shadow-claw-networking-BN5BB4hb.js → shadow-claw-networking-Diy3JJkc.js} +2 -2
  187. package/dist/lib/{shadow-claw-networking-BN5BB4hb.js.map → shadow-claw-networking-Diy3JJkc.js.map} +1 -1
  188. package/dist/lib/{shadow-claw-notifications-71KARtkY.js → shadow-claw-notifications-C-upPa-4.js} +3 -3
  189. package/dist/lib/{shadow-claw-notifications-71KARtkY.js.map → shadow-claw-notifications-C-upPa-4.js.map} +1 -1
  190. package/dist/lib/{shadow-claw-page-header-DMGO-TSe.js → shadow-claw-page-header-C_Qr3xZM.js} +2 -2
  191. package/dist/lib/{shadow-claw-page-header-DMGO-TSe.js.map → shadow-claw-page-header-C_Qr3xZM.js.map} +1 -1
  192. package/dist/lib/{shadow-claw-pages-BiRM6qiA.js → shadow-claw-pages-CfAjUKgd.js} +11 -11
  193. package/dist/lib/{shadow-claw-pages-BiRM6qiA.js.map → shadow-claw-pages-CfAjUKgd.js.map} +1 -1
  194. package/dist/lib/{shadow-claw-peerjs-BZu7jNSe.js → shadow-claw-peerjs-t4YibS9s.js} +6 -6
  195. package/dist/lib/{shadow-claw-peerjs-BZu7jNSe.js.map → shadow-claw-peerjs-t4YibS9s.js.map} +1 -1
  196. package/dist/lib/{shadow-claw-provider-model-picker-BXYXEobD.js → shadow-claw-provider-model-picker-B-Ct4yW-.js} +2 -2
  197. package/dist/lib/{shadow-claw-provider-model-picker-BXYXEobD.js.map → shadow-claw-provider-model-picker-B-Ct4yW-.js.map} +1 -1
  198. package/dist/lib/{shadow-claw-settings-CcT5EK08.js → shadow-claw-settings-Cg5V0e9g.js} +7 -7
  199. package/dist/lib/{shadow-claw-settings-CcT5EK08.js.map → shadow-claw-settings-Cg5V0e9g.js.map} +1 -1
  200. package/dist/lib/{shadow-claw-storage-eTOpbvpi.js → shadow-claw-storage-C7tCnsSG.js} +5 -5
  201. package/dist/lib/{shadow-claw-storage-eTOpbvpi.js.map → shadow-claw-storage-C7tCnsSG.js.map} +1 -1
  202. package/dist/lib/{shadow-claw-task-server-DFImTUbw.js → shadow-claw-task-server-BObsRdf8.js} +2 -2
  203. package/dist/lib/{shadow-claw-task-server-DFImTUbw.js.map → shadow-claw-task-server-BObsRdf8.js.map} +1 -1
  204. package/dist/lib/{shadow-claw-tasks-BjaxsmUx.js → shadow-claw-tasks-B2EEqrcY.js} +9 -9
  205. package/dist/lib/{shadow-claw-tasks-BjaxsmUx.js.map → shadow-claw-tasks-B2EEqrcY.js.map} +1 -1
  206. package/dist/lib/{shadow-claw-terminal-C-4wreFe.js → shadow-claw-terminal-DSHfO2b9.js} +2 -2
  207. package/dist/lib/{shadow-claw-terminal-C-4wreFe.js.map → shadow-claw-terminal-DSHfO2b9.js.map} +1 -1
  208. package/dist/lib/{shadow-claw-tools-COdrGZJk.js → shadow-claw-tools-DwPBADua.js} +7 -7
  209. package/dist/lib/{shadow-claw-tools-COdrGZJk.js.map → shadow-claw-tools-DwPBADua.js.map} +1 -1
  210. package/dist/lib/{shadow-claw-webvm-sxqVjO0L.js → shadow-claw-webvm-CY4qGaMB.js} +3 -3
  211. package/dist/lib/{shadow-claw-webvm-sxqVjO0L.js.map → shadow-claw-webvm-CY4qGaMB.js.map} +1 -1
  212. package/dist/lib/{sync-web-mcp-registration-D4hdUwtv.js → sync-web-mcp-registration-BiOZvW-R.js} +6 -6
  213. package/dist/lib/{sync-web-mcp-registration-D4hdUwtv.js.map → sync-web-mcp-registration-BiOZvW-R.js.map} +1 -1
  214. package/dist/lib/{system-prompt-DT_KeYaL.js → system-prompt-CxJ3Nx4c.js} +9 -8
  215. package/dist/lib/system-prompt-CxJ3Nx4c.js.map +1 -0
  216. package/dist/lib/{tools-Beuyh8y1.js → tools-B8OJ4sMF.js} +4 -4
  217. package/dist/lib/{tools-Beuyh8y1.js.map → tools-B8OJ4sMF.js.map} +1 -1
  218. package/dist/lib/{transformers-DydnReu4.js → transformers-BMURofG6.js} +2 -2
  219. package/dist/lib/{transformers-DydnReu4.js.map → transformers-BMURofG6.js.map} +1 -1
  220. package/dist/lib/{trusted-types-CfwZl_rr.js → trusted-types-HwsGS5Nj.js} +19 -17
  221. package/dist/lib/{trusted-types-CfwZl_rr.js.map → trusted-types-HwsGS5Nj.js.map} +1 -1
  222. package/dist/lib/{upload-group-file-BbBzjTcN.js → upload-group-file-CJpoNjEb.js} +3 -3
  223. package/dist/lib/{upload-group-file-BbBzjTcN.js.map → upload-group-file-CJpoNjEb.js.map} +1 -1
  224. package/dist/lib/utils/index.js +1 -1
  225. package/dist/lib/utils/namespaced-storage.js +1 -1
  226. package/dist/lib/utils/runtime-assets.js +1 -1
  227. package/dist/lib/utils/utils.js +1 -1
  228. package/dist/lib/{webmcp-DCfAFiIO.js → webmcp-BoMTvgmX.js} +3 -3
  229. package/dist/lib/{webmcp-DCfAFiIO.js.map → webmcp-BoMTvgmX.js.map} +1 -1
  230. package/dist/lib/{write-group-file-bytes-Ccn-VFUU.js → write-group-file-bytes-CNT7DqOZ.js} +3 -3
  231. package/dist/lib/{write-group-file-bytes-Ccn-VFUU.js.map → write-group-file-bytes-CNT7DqOZ.js.map} +1 -1
  232. package/dist/public/.well-known/mcp/server-card.json +1 -1
  233. package/dist/public/.well-known/mcp.json +1 -1
  234. package/dist/public/AGENTS.md +3 -1
  235. package/dist/public/README.md +6 -2
  236. package/dist/public/agent.worker.js +1 -1
  237. package/dist/public/attachment-capabilities-AdwXt3--.js +1 -0
  238. package/dist/public/{channel-BylT3rJC.js → channel-DIpDQekL.js} +1 -1
  239. package/dist/public/{chat-template-DPHJy7tr.js → chat-template-CXKs8lFR.js} +1 -1
  240. package/dist/public/compact-context-BQ2ZXoAc.js +5 -0
  241. package/dist/public/{compact-context-BINQh64w.js → compact-context-dHitmPsV.js} +2 -2
  242. package/dist/public/config-C16fFWtP.js +1 -0
  243. package/dist/public/{configure-peer-js-DChhcOfe.js → configure-peer-js-DV1rqvFX.js} +1 -1
  244. package/dist/public/{connections-CHaw0VqP.js → connections-Dxwj8yK_.js} +1 -1
  245. package/dist/public/{create-model-cache-fetch-DQebkoPL.js → create-model-cache-fetch-B0mSCEk6.js} +1 -1
  246. package/dist/public/{credentials-CgVqS119.js → credentials-CJUQ5Ep2.js} +1 -1
  247. package/dist/public/{custom-element-security-kiDhPfb8.js → custom-element-security-B2daIE5r.js} +2 -2
  248. package/dist/public/{discover-skills-Cvmx5I9V.js → discover-skills-BWJB8HUA.js} +6 -6
  249. package/dist/public/docs/architecture/overview.md +1 -1
  250. package/dist/public/docs/example/article/index.html +29 -30
  251. package/dist/public/docs/example/article.html +29 -30
  252. package/dist/public/docs/publishing/index.html +29 -30
  253. package/dist/public/docs/publishing.html +29 -30
  254. package/dist/public/docs/skill-creator/index.html +29 -30
  255. package/dist/public/docs/skill-creator.html +29 -30
  256. package/dist/public/docs/subsystems/attachment-capabilities.md +14 -1
  257. package/dist/public/docs/subsystems/cli.md +95 -51
  258. package/dist/public/docs/subsystems/pages.md +5 -0
  259. package/dist/public/{download-group-file-BapoRgfU.js → download-group-file-BkMH-JKi.js} +1 -1
  260. package/dist/public/e2e/README.md +1 -1
  261. package/dist/public/{e2e-bridge-C0g8vZKr.js → e2e-bridge-lP2qqiv3.js} +1 -1
  262. package/dist/public/get-group-dir-D--BiEyk.js +1 -0
  263. package/dist/public/{get-or-create-subscriber-id-GvRZYXwA.js → get-or-create-subscriber-id-jVHnQfbr.js} +1 -1
  264. package/dist/public/{git-CaAAZfVd.js → git-DjmQ16rm.js} +2 -2
  265. package/dist/public/{iframe-bridge-scripts-BnqtKhE4.js → iframe-bridge-scripts-CO0izGjW.js} +1 -1
  266. package/dist/public/index.html +29 -30
  267. package/dist/public/index.js +1 -1
  268. package/dist/public/{init-chat-split-resize-Btonoy8u.js → init-chat-split-resize-C8AqCCiK.js} +1 -1
  269. package/dist/public/init-control-plane-Ctz7FI8M.js +1 -0
  270. package/dist/public/{invoke-agent-B3Osw6K7.js → invoke-agent-C_geruwq.js} +1 -1
  271. package/dist/public/llms.txt +1 -1
  272. package/dist/public/main/index.html +29 -30
  273. package/dist/public/main/memory/index.html +29 -30
  274. package/dist/public/main/memory.html +29 -30
  275. package/dist/public/main.html +29 -30
  276. package/dist/public/{markdown-CPbU4r1U.js → markdown-CDSb5Hrl.js} +1 -1
  277. package/dist/public/{mcp-reconnect-CzROVsXG.js → mcp-reconnect-iPZPihwX.js} +1 -1
  278. package/dist/public/{memory-storage-BkoMlxOr.js → memory-storage-2m7KZ-aP.js} +1 -1
  279. package/dist/public/{model-ranking-CK0iBo3Z.js → model-ranking-BgOSaNIy.js} +1 -1
  280. package/dist/public/{move-group-entry-CTxoq7lw.js → move-group-entry-QQ9Hkk54.js} +1 -1
  281. package/dist/public/{orchestrator-BrDjQbGf.js → orchestrator-C1kaTltu.js} +2 -2
  282. package/dist/public/orchestrator-Li1UAsv7.js +63 -0
  283. package/dist/public/{peerjs-CgF4Iz5W.js → peerjs-DbBryE-9.js} +1 -1
  284. package/dist/public/{process-peer-query-param-BL2k0Hu-.js → process-peer-query-param-DQIgr3KL.js} +1 -1
  285. package/dist/public/{process-pending-shared-payloads-C1AgGvn8.js → process-pending-shared-payloads-Ctb-TFqB.js} +1 -1
  286. package/dist/public/{process-room-query-param-DM0QCq3_.js → process-room-query-param-F-XnIVoZ.js} +1 -1
  287. package/dist/public/provider-YPZmsuHR.js +1 -0
  288. package/dist/public/{push-client-DJEOz7bi.js → push-client-DRx9Eggz.js} +1 -1
  289. package/dist/public/{rooms-C6LXIJl4.js → rooms-BurBI7is.js} +1 -1
  290. package/dist/public/service-worker/init.js +1 -1
  291. package/dist/public/service-worker.js +1 -1
  292. package/dist/public/shadow-claw-Bg9AQ5x_.js +1176 -0
  293. package/dist/public/{shadow-claw-accounts--4hd_oCz.js → shadow-claw-accounts-B3mjYI0M.js} +1 -1
  294. package/dist/public/{shadow-claw-card-IbNlZAdK.js → shadow-claw-card-tcXRS1GF.js} +1 -1
  295. package/dist/public/{shadow-claw-channels-Vq_pPGa2.js → shadow-claw-channels-BiSfLvWv.js} +1 -1
  296. package/dist/public/{shadow-claw-chat-D7_GS25e.js → shadow-claw-chat-N5jMsXZZ.js} +3 -3
  297. package/dist/public/{shadow-claw-control-plane-WTMEV8_p.js → shadow-claw-control-plane-DFVe_Xdq.js} +2 -2
  298. package/dist/public/{shadow-claw-conversations-CLQgU1IT.js → shadow-claw-conversations-wAR06_ya.js} +1 -1
  299. package/dist/public/{shadow-claw-empty-state-D4CrFGsN.js → shadow-claw-empty-state-CnPm3NVM.js} +1 -1
  300. package/dist/public/{shadow-claw-file-viewer-BhqiqLWQ.js → shadow-claw-file-viewer-sZN_FCDW.js} +4 -4
  301. package/dist/public/{shadow-claw-files-senDiG9l.js → shadow-claw-files-CnvkCbd4.js} +2 -2
  302. package/dist/public/{shadow-claw-git-DOOCqY23.js → shadow-claw-git-BBHfClGk.js} +2 -2
  303. package/dist/public/{shadow-claw-integrations-Bsvc3Agq.js → shadow-claw-integrations-DvdBqzRJ.js} +1 -1
  304. package/dist/public/{shadow-claw-llm-actYICAk.js → shadow-claw-llm-YfohG519.js} +2 -2
  305. package/dist/public/{shadow-claw-mcp-remote-BYUgrK3v.js → shadow-claw-mcp-remote-BAVbf5pi.js} +1 -1
  306. package/dist/public/{shadow-claw-networking-Dk3p5Ny_.js → shadow-claw-networking-CZ4LWPW7.js} +1 -1
  307. package/dist/public/{shadow-claw-notifications-CzPAlay8.js → shadow-claw-notifications-BHwyREkG.js} +1 -1
  308. package/dist/public/{shadow-claw-page-header-CjJpVkyL.js → shadow-claw-page-header-De6Qf6eY.js} +1 -1
  309. package/dist/public/{shadow-claw-page-header-action-button-2DH5O1TD.js → shadow-claw-page-header-action-button-FSOhTc9z.js} +1 -1
  310. package/dist/public/{shadow-claw-pages-3r5I-wI8.js → shadow-claw-pages-D_oPyDca.js} +6 -6
  311. package/dist/public/{shadow-claw-pdf-viewer-BiCEwsoY.js → shadow-claw-pdf-viewer-CrU4wqRq.js} +1 -1
  312. package/dist/public/{shadow-claw-settings-DgB9RSZN.js → shadow-claw-settings-DkUhvxVr.js} +2 -2
  313. package/dist/public/{shadow-claw-storage-JB_43nd8.js → shadow-claw-storage-D0o56Tjw.js} +1 -1
  314. package/dist/public/{shadow-claw-task-server-oi5UIxdA.js → shadow-claw-task-server-4rkroO9K.js} +1 -1
  315. package/dist/public/{shadow-claw-tasks-CnyiOt81.js → shadow-claw-tasks-BdP7lmvu.js} +3 -3
  316. package/dist/public/{shadow-claw-terminal-BC3RynHt.js → shadow-claw-terminal-DVHX7Fsu.js} +1 -1
  317. package/dist/public/{shadow-claw-toast-YjG--2Za.js → shadow-claw-toast-B9Y9tSkW.js} +1 -1
  318. package/dist/public/{shadow-claw-tools-Bbwk4vlT.js → shadow-claw-tools-BwwY53Lr.js} +1 -1
  319. package/dist/public/{shadow-claw-webvm-HZqzl2H5.js → shadow-claw-webvm-CXGdkCNM.js} +1 -1
  320. package/dist/public/{sync-web-mcp-registration-BaH2nAP0.js → sync-web-mcp-registration-DVK_IhXZ.js} +1 -1
  321. package/dist/public/{system-prompt-Dck3N8T0.js → system-prompt-BmswoQwF.js} +2 -2
  322. package/dist/public/{tools-DHA1dK2I.js → tools-D-52Zmfc.js} +1 -1
  323. package/dist/public/{transformers-C-DuTM2K.js → transformers-CQ9ss9rD.js} +1 -1
  324. package/dist/public/{upload-group-file-Cejr3zo1.js → upload-group-file-A8kB7lvO.js} +1 -1
  325. package/dist/public/{webmcp-CMRtu57-.js → webmcp-DIUZjVF5.js} +1 -1
  326. package/dist/public/{workbox-92eae37e.js → workbox-e4022e15.js} +1 -1
  327. package/dist/public/{write-group-file-CmJuVQNO.js → write-group-file-R67DjJ-q.js} +1 -1
  328. package/dist/public/{write-group-file-bytes-Cejr3zo1.js → write-group-file-bytes-A8kB7lvO.js} +1 -1
  329. package/dist/public/{zip-reader-CuQ13eLe.js → zip-reader-JHoTbATw.js} +1 -1
  330. package/dist/server.js +6 -6
  331. package/package.json +1 -1
  332. package/dist/cli/chunk-2gZFafgY.js +0 -1
  333. package/dist/cli/chunk-BFziiMKt.js +0 -7
  334. package/dist/cli/chunk-BM3llsxb.js +0 -1
  335. package/dist/cli/chunk-BUNoeMKY.js +0 -36
  336. package/dist/cli/chunk-Bj5qFsDi.js +0 -7
  337. package/dist/cli/chunk-Bj95zm-y.js +0 -1
  338. package/dist/cli/chunk-BpyP-esT.js +0 -1
  339. package/dist/cli/chunk-CX696s3_.js +0 -1
  340. package/dist/cli/chunk-DRxCrCAA.js +0 -139
  341. package/dist/cli/chunk-DjbCHa0h.js +0 -1
  342. package/dist/cli/chunk-Ds5-K-9o.js +0 -1
  343. package/dist/cli/chunk-DsQhAF31.js +0 -1
  344. package/dist/cli/chunk-VM-dECyG.js +0 -1
  345. package/dist/cli/chunk-gvNsvav0.js +0 -225
  346. package/dist/cli/chunk-heu2xRw1.js +0 -1
  347. package/dist/lib/orchestrator-i_QJ-o22.js.map +0 -1
  348. package/dist/lib/shadow-claw-DoQ7fgl5.js.map +0 -1
  349. package/dist/lib/system-prompt-DT_KeYaL.js.map +0 -1
  350. package/dist/public/app-routes-V_-URXc5.js +0 -1
  351. package/dist/public/attachment-capabilities-B6ibLwQB.js +0 -1
  352. package/dist/public/compact-context-CX4H8V57.js +0 -5
  353. package/dist/public/config-C-YdSFZB.js +0 -1
  354. package/dist/public/get-group-dir-DL44kvqW.js +0 -1
  355. package/dist/public/init-control-plane-BoJijVtf.js +0 -1
  356. package/dist/public/orchestrator-CaUpEVkQ.js +0 -63
  357. package/dist/public/provider-DNIL4-Hw.js +0 -1
  358. package/dist/public/shadow-claw-DdgeYPg5.js +0 -1176
@@ -1,9 +1,9 @@
1
- import { t as orchestratorStore } from "./orchestrator-i_QJ-o22.js";
1
+ import { t as orchestratorStore } from "./orchestrator-cRBe3lhq.js";
2
2
  import { ulid } from "./utils/ulid.js";
3
3
  import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
4
- import { a as showPage } from "./shadow-claw-DoQ7fgl5.js";
5
- import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-Dlru5ofR.js";
6
- import { t as configurePeerJs } from "./configure-peer-js-ChDhOZU4.js";
4
+ import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
5
+ import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-DB77spML.js";
6
+ import { t as configurePeerJs } from "./configure-peer-js-CgFiwoxY.js";
7
7
 
8
8
  //#region src/components/shadow-claw/utils/process-peer-query-param.ts
9
9
  async function processPeerQueryParam(shadow, shadowClaw, db, orchestrator) {
@@ -36,4 +36,4 @@ async function processPeerQueryParam(shadow, shadowClaw, db, orchestrator) {
36
36
 
37
37
  //#endregion
38
38
  export { processPeerQueryParam };
39
- //# sourceMappingURL=process-peer-query-param-CJp7w7AU.js.map
39
+ //# sourceMappingURL=process-peer-query-param-BnsVnxzH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-peer-query-param-CJp7w7AU.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-peer-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\n\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\n\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"../utils/show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPeerQueryParam(\n shadow: ShadowRoot,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase | null,\n orchestrator: Orchestrator,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const peerParam = currentUrl.searchParams.get(\"peer\");\n if (!peerParam) {\n return;\n }\n\n const remotePeerId = peerParam.trim();\n if (!remotePeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and configured\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n // Automatically trust the remote peer we are connecting to\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(remotePeerId);\n\n // Save/configure\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Ensure peer conversation exists in the list\n const targetGroupId = await orchestratorStore.ensurePeerConversation(\n db,\n remotePeerId,\n );\n\n // 3. Switch conversation and navigate to chat\n await orchestratorStore.switchConversation(db, targetGroupId);\n showPage(shadow, shadowClaw, db, orchestratorStore, \"chat\");\n\n // 4. Remove 'peer' from URL params to prevent re-triggering\n currentUrl.searchParams.delete(\"peer\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n window.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Connected to Peer: ${remotePeerId.substring(0, 8)}`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to process peer parameter: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAgBA,eAAsB,sBACpB,QACA,YACA,IACA,cACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM;CACpD,IAAI,CAAC,WACH;CAGF,MAAM,eAAe,UAAU,KAAK;CACpC,IAAI,CAAC,cACH;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAIhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,YAAY;EAGxB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,MAAM,gBAAgB,MAAM,kBAAkB,uBAC5C,IACA,YACF;EAGA,MAAM,kBAAkB,mBAAmB,IAAI,aAAa;EAC5D,SAAS,QAAQ,YAAY,IAAI,mBAAmB,MAAM;EAG1D,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,OAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAElD,YAAY,sBAAsB,aAAa,UAAU,GAAG,CAAC,GAAG;CAClE,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,qCAAqC,WAAW,GAAI;CAChE;AACF"}
1
+ {"version":3,"file":"process-peer-query-param-BnsVnxzH.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-peer-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\n\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\n\nimport { orchestratorStore } from \"../../../stores/orchestrator.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"../utils/show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPeerQueryParam(\n shadow: ShadowRoot,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase | null,\n orchestrator: Orchestrator,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const peerParam = currentUrl.searchParams.get(\"peer\");\n if (!peerParam) {\n return;\n }\n\n const remotePeerId = peerParam.trim();\n if (!remotePeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and configured\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n // Automatically trust the remote peer we are connecting to\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(remotePeerId);\n\n // Save/configure\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Ensure peer conversation exists in the list\n const targetGroupId = await orchestratorStore.ensurePeerConversation(\n db,\n remotePeerId,\n );\n\n // 3. Switch conversation and navigate to chat\n await orchestratorStore.switchConversation(db, targetGroupId);\n showPage(shadow, shadowClaw, db, orchestratorStore, \"chat\");\n\n // 4. Remove 'peer' from URL params to prevent re-triggering\n currentUrl.searchParams.delete(\"peer\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n window.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Connected to Peer: ${remotePeerId.substring(0, 8)}`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to process peer parameter: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAgBA,eAAsB,sBACpB,QACA,YACA,IACA,cACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM;CACpD,IAAI,CAAC,WACH;CAGF,MAAM,eAAe,UAAU,KAAK;CACpC,IAAI,CAAC,cACH;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAIhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,YAAY;EAGxB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,MAAM,gBAAgB,MAAM,kBAAkB,uBAC5C,IACA,YACF;EAGA,MAAM,kBAAkB,mBAAmB,IAAI,aAAa;EAC5D,SAAS,QAAQ,YAAY,IAAI,mBAAmB,MAAM;EAG1D,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,OAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAElD,YAAY,sBAAsB,aAAa,UAAU,GAAG,CAAC,GAAG;CAClE,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,qCAAqC,WAAW,GAAI;CAChE;AACF"}
@@ -1,7 +1,7 @@
1
- import { o as writeGroupFile } from "./tools-Beuyh8y1.js";
1
+ import { o as writeGroupFile } from "./tools-B8OJ4sMF.js";
2
2
  import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
3
- import { a as showPage } from "./shadow-claw-DoQ7fgl5.js";
4
- import { t as writeGroupFileBytes } from "./write-group-file-bytes-Ccn-VFUU.js";
3
+ import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
4
+ import { t as writeGroupFileBytes } from "./write-group-file-bytes-CNT7DqOZ.js";
5
5
 
6
6
  //#region src/share-target/pending-shares.ts
7
7
  const PENDING_SHARES_STORE = "pendingShares";
@@ -128,4 +128,4 @@ async function processPendingSharedPayloads(win, shadow, shadowClaw, oStore, fSt
128
128
 
129
129
  //#endregion
130
130
  export { processPendingSharedPayloads };
131
- //# sourceMappingURL=process-pending-shared-payloads-B6_TlBFA.js.map
131
+ //# sourceMappingURL=process-pending-shared-payloads-DBZfZOOa.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-pending-shared-payloads-B6_TlBFA.js","names":[],"sources":["../../src/share-target/pending-shares.ts","../../src/components/shadow-claw/utils/build-shared-text-payload.ts","../../src/components/shadow-claw/utils/resolve-shared-files-conversation-id.ts","../../src/components/shadow-claw/utils/sanitize-shared-file-name.ts","../../src/components/shadow-claw/utils/process-pending-shared-payloads.ts"],"sourcesContent":["import type { ShadowClawDatabase } from \"../db/types.js\";\n\nconst PENDING_SHARES_STORE = \"pendingShares\";\n\nexport interface PendingShareRecord {\n id: string;\n createdAt: number;\n title: string;\n text: string;\n url: string;\n fileName: string;\n fileType: string;\n fileBytes: ArrayBuffer | null;\n}\n\nfunction normalizeRecord(raw: any): PendingShareRecord {\n return {\n id: typeof raw?.id === \"string\" ? raw.id : \"\",\n createdAt: typeof raw?.createdAt === \"number\" ? raw.createdAt : 0,\n title: typeof raw?.title === \"string\" ? raw.title : \"\",\n text: typeof raw?.text === \"string\" ? raw.text : \"\",\n url: typeof raw?.url === \"string\" ? raw.url : \"\",\n fileName: typeof raw?.fileName === \"string\" ? raw.fileName : \"\",\n fileType: typeof raw?.fileType === \"string\" ? raw.fileType : \"\",\n fileBytes: raw?.fileBytes instanceof ArrayBuffer ? raw.fileBytes : null,\n };\n}\n\n/**\n * Read and clear pending Web Share Target payloads in FIFO order.\n */\nexport async function consumePendingShares(\n db: ShadowClawDatabase,\n): Promise<PendingShareRecord[]> {\n if (!db || typeof (db as any).transaction !== \"function\") {\n return [];\n }\n\n return new Promise((resolve, reject) => {\n let tx: IDBTransaction;\n\n try {\n tx = (db as IDBDatabase).transaction(PENDING_SHARES_STORE, \"readwrite\");\n } catch (error) {\n if (error instanceof DOMException && error.name === \"NotFoundError\") {\n resolve([]);\n\n return;\n }\n\n reject(error);\n\n return;\n }\n\n const store = tx.objectStore(PENDING_SHARES_STORE);\n const getAllRequest = store.getAll();\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error || new Error(\"Failed to read pending shares\"));\n };\n\n getAllRequest.onsuccess = () => {\n const rows = Array.isArray(getAllRequest.result)\n ? getAllRequest.result\n .map(normalizeRecord)\n .filter(\n (record) => typeof record.id === \"string\" && record.id.length > 0,\n )\n .sort((a, b) => a.createdAt - b.createdAt)\n : [];\n\n const clearRequest = store.clear();\n clearRequest.onerror = () => {\n reject(\n clearRequest.error || new Error(\"Failed to clear pending shares\"),\n );\n };\n\n clearRequest.onsuccess = () => {\n resolve(rows);\n };\n };\n\n tx.onabort = () => {\n reject(tx.error || new Error(\"Pending share transaction aborted\"));\n };\n });\n}\n","export function buildSharedTextPayload(share: {\n title: string;\n text: string;\n url: string;\n}): string {\n const lines: string[] = [\"# Shared Content\", \"\"];\n\n if (share.title) {\n lines.push(`Title: ${share.title}`);\n }\n\n if (share.url) {\n lines.push(`URL: ${share.url}`);\n }\n\n if (share.text) {\n lines.push(\"\", share.text);\n }\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","import type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\n\nexport async function resolveSharedFilesConversationId(\n db: ShadowClawDatabase,\n oStore: OrchestratorStore,\n): Promise<string> {\n const now = new Date();\n const year = String(now.getFullYear());\n const month = String(now.getMonth() + 1).padStart(2, \"0\");\n const day = String(now.getDate()).padStart(2, \"0\");\n const isoDate = `${year}-${month}-${day}`;\n const conversationName = `Shared Files ${isoDate}`;\n const existing = oStore.groups.find(\n (group) => group.name === conversationName,\n );\n\n if (existing) {\n await oStore.switchConversation(db, existing.groupId);\n\n return existing.groupId;\n }\n\n const group = await oStore.createConversation(db, conversationName);\n\n return group.groupId;\n}\n","export function sanitizeSharedFileName(\n name: string,\n fallbackBase: string,\n): string {\n const normalized =\n name.replace(/\\\\/g, \"/\").split(\"/\").filter(Boolean).pop() || \"\";\n\n const collapsed = normalized\n .replace(/\\s+/g, \"-\")\n .replace(/[^A-Za-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n if (collapsed) {\n return collapsed;\n }\n\n return `${fallbackBase}.txt`;\n}\n","import { consumePendingShares } from \"../../../share-target/pending-shares.js\";\nimport { writeGroupFile } from \"../../../storage/write-group-file.js\";\nimport { writeGroupFileBytes } from \"../../../storage/write-group-file-bytes.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { buildSharedTextPayload } from \"./build-shared-text-payload.js\";\nimport { resolveSharedFilesConversationId } from \"./resolve-shared-files-conversation-id.js\";\nimport { sanitizeSharedFileName } from \"./sanitize-shared-file-name.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { FileViewerStore } from \"../../../stores/file-viewer.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPendingSharedPayloads(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n oStore: OrchestratorStore,\n fStore: FileViewerStore,\n db: ShadowClawDatabase,\n url: URL,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const pendingShares = await consumePendingShares(db);\n if (pendingShares.length === 0) {\n return;\n }\n\n try {\n const targetGroupId = await resolveSharedFilesConversationId(db, oStore);\n const savedPaths: string[] = [];\n\n for (let i = 0; i < pendingShares.length; i++) {\n const share = pendingShares[i];\n const baseName = `shared-${Date.now()}-${i + 1}`;\n\n if (share.fileBytes instanceof ArrayBuffer) {\n const preferredName =\n share.fileName ||\n (share.fileType === \"application/pdf\"\n ? `${baseName}.pdf`\n : `${baseName}.bin`);\n const fileName = sanitizeSharedFileName(preferredName, baseName);\n\n await writeGroupFileBytes(\n db,\n targetGroupId,\n fileName,\n new Uint8Array(share.fileBytes),\n );\n savedPaths.push(fileName);\n\n continue;\n }\n\n const textFileName = sanitizeSharedFileName(\n share.fileName || `${baseName}.md`,\n baseName,\n );\n const textPayload = buildSharedTextPayload(share);\n await writeGroupFile(db, targetGroupId, textFileName, textPayload);\n savedPaths.push(textFileName);\n }\n\n await oStore.loadFiles(db);\n showPage(shadow, shadowClaw, db, oStore, \"files\");\n\n if (savedPaths.length > 0) {\n await fStore.openFile(db, savedPaths[0], targetGroupId);\n }\n\n showSuccess(\n `Imported ${savedPaths.length} shared item${savedPaths.length === 1 ? \"\" : \"s\"}.`,\n );\n\n const currentUrl = url;\n if (currentUrl.searchParams.has(\"share-target\")) {\n currentUrl.searchParams.delete(\"share-target\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to import shared content: ${message}`, 6000);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-pending-shared-payloads-DBZfZOOa.js","names":[],"sources":["../../src/share-target/pending-shares.ts","../../src/components/shadow-claw/utils/build-shared-text-payload.ts","../../src/components/shadow-claw/utils/resolve-shared-files-conversation-id.ts","../../src/components/shadow-claw/utils/sanitize-shared-file-name.ts","../../src/components/shadow-claw/utils/process-pending-shared-payloads.ts"],"sourcesContent":["import type { ShadowClawDatabase } from \"../db/types.js\";\n\nconst PENDING_SHARES_STORE = \"pendingShares\";\n\nexport interface PendingShareRecord {\n id: string;\n createdAt: number;\n title: string;\n text: string;\n url: string;\n fileName: string;\n fileType: string;\n fileBytes: ArrayBuffer | null;\n}\n\nfunction normalizeRecord(raw: any): PendingShareRecord {\n return {\n id: typeof raw?.id === \"string\" ? raw.id : \"\",\n createdAt: typeof raw?.createdAt === \"number\" ? raw.createdAt : 0,\n title: typeof raw?.title === \"string\" ? raw.title : \"\",\n text: typeof raw?.text === \"string\" ? raw.text : \"\",\n url: typeof raw?.url === \"string\" ? raw.url : \"\",\n fileName: typeof raw?.fileName === \"string\" ? raw.fileName : \"\",\n fileType: typeof raw?.fileType === \"string\" ? raw.fileType : \"\",\n fileBytes: raw?.fileBytes instanceof ArrayBuffer ? raw.fileBytes : null,\n };\n}\n\n/**\n * Read and clear pending Web Share Target payloads in FIFO order.\n */\nexport async function consumePendingShares(\n db: ShadowClawDatabase,\n): Promise<PendingShareRecord[]> {\n if (!db || typeof (db as any).transaction !== \"function\") {\n return [];\n }\n\n return new Promise((resolve, reject) => {\n let tx: IDBTransaction;\n\n try {\n tx = (db as IDBDatabase).transaction(PENDING_SHARES_STORE, \"readwrite\");\n } catch (error) {\n if (error instanceof DOMException && error.name === \"NotFoundError\") {\n resolve([]);\n\n return;\n }\n\n reject(error);\n\n return;\n }\n\n const store = tx.objectStore(PENDING_SHARES_STORE);\n const getAllRequest = store.getAll();\n\n getAllRequest.onerror = () => {\n reject(getAllRequest.error || new Error(\"Failed to read pending shares\"));\n };\n\n getAllRequest.onsuccess = () => {\n const rows = Array.isArray(getAllRequest.result)\n ? getAllRequest.result\n .map(normalizeRecord)\n .filter(\n (record) => typeof record.id === \"string\" && record.id.length > 0,\n )\n .sort((a, b) => a.createdAt - b.createdAt)\n : [];\n\n const clearRequest = store.clear();\n clearRequest.onerror = () => {\n reject(\n clearRequest.error || new Error(\"Failed to clear pending shares\"),\n );\n };\n\n clearRequest.onsuccess = () => {\n resolve(rows);\n };\n };\n\n tx.onabort = () => {\n reject(tx.error || new Error(\"Pending share transaction aborted\"));\n };\n });\n}\n","export function buildSharedTextPayload(share: {\n title: string;\n text: string;\n url: string;\n}): string {\n const lines: string[] = [\"# Shared Content\", \"\"];\n\n if (share.title) {\n lines.push(`Title: ${share.title}`);\n }\n\n if (share.url) {\n lines.push(`URL: ${share.url}`);\n }\n\n if (share.text) {\n lines.push(\"\", share.text);\n }\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","import type { ShadowClawDatabase } from \"../../../db/db.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\n\nexport async function resolveSharedFilesConversationId(\n db: ShadowClawDatabase,\n oStore: OrchestratorStore,\n): Promise<string> {\n const now = new Date();\n const year = String(now.getFullYear());\n const month = String(now.getMonth() + 1).padStart(2, \"0\");\n const day = String(now.getDate()).padStart(2, \"0\");\n const isoDate = `${year}-${month}-${day}`;\n const conversationName = `Shared Files ${isoDate}`;\n const existing = oStore.groups.find(\n (group) => group.name === conversationName,\n );\n\n if (existing) {\n await oStore.switchConversation(db, existing.groupId);\n\n return existing.groupId;\n }\n\n const group = await oStore.createConversation(db, conversationName);\n\n return group.groupId;\n}\n","export function sanitizeSharedFileName(\n name: string,\n fallbackBase: string,\n): string {\n const normalized =\n name.replace(/\\\\/g, \"/\").split(\"/\").filter(Boolean).pop() || \"\";\n\n const collapsed = normalized\n .replace(/\\s+/g, \"-\")\n .replace(/[^A-Za-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n if (collapsed) {\n return collapsed;\n }\n\n return `${fallbackBase}.txt`;\n}\n","import { consumePendingShares } from \"../../../share-target/pending-shares.js\";\nimport { writeGroupFile } from \"../../../storage/write-group-file.js\";\nimport { writeGroupFileBytes } from \"../../../storage/write-group-file-bytes.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { buildSharedTextPayload } from \"./build-shared-text-payload.js\";\nimport { resolveSharedFilesConversationId } from \"./resolve-shared-files-conversation-id.js\";\nimport { sanitizeSharedFileName } from \"./sanitize-shared-file-name.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { FileViewerStore } from \"../../../stores/file-viewer.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processPendingSharedPayloads(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n oStore: OrchestratorStore,\n fStore: FileViewerStore,\n db: ShadowClawDatabase,\n url: URL,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const pendingShares = await consumePendingShares(db);\n if (pendingShares.length === 0) {\n return;\n }\n\n try {\n const targetGroupId = await resolveSharedFilesConversationId(db, oStore);\n const savedPaths: string[] = [];\n\n for (let i = 0; i < pendingShares.length; i++) {\n const share = pendingShares[i];\n const baseName = `shared-${Date.now()}-${i + 1}`;\n\n if (share.fileBytes instanceof ArrayBuffer) {\n const preferredName =\n share.fileName ||\n (share.fileType === \"application/pdf\"\n ? `${baseName}.pdf`\n : `${baseName}.bin`);\n const fileName = sanitizeSharedFileName(preferredName, baseName);\n\n await writeGroupFileBytes(\n db,\n targetGroupId,\n fileName,\n new Uint8Array(share.fileBytes),\n );\n savedPaths.push(fileName);\n\n continue;\n }\n\n const textFileName = sanitizeSharedFileName(\n share.fileName || `${baseName}.md`,\n baseName,\n );\n const textPayload = buildSharedTextPayload(share);\n await writeGroupFile(db, targetGroupId, textFileName, textPayload);\n savedPaths.push(textFileName);\n }\n\n await oStore.loadFiles(db);\n showPage(shadow, shadowClaw, db, oStore, \"files\");\n\n if (savedPaths.length > 0) {\n await fStore.openFile(db, savedPaths[0], targetGroupId);\n }\n\n showSuccess(\n `Imported ${savedPaths.length} shared item${savedPaths.length === 1 ? \"\" : \"s\"}.`,\n );\n\n const currentUrl = url;\n if (currentUrl.searchParams.has(\"share-target\")) {\n currentUrl.searchParams.delete(\"share-target\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to import shared content: ${message}`, 6000);\n }\n}\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { ulid } from "./utils/ulid.js";
2
2
  import { a as showSuccess, r as showError } from "./toast-Ck7OIKDf.js";
3
- import { a as showPage } from "./shadow-claw-DoQ7fgl5.js";
3
+ import { a as showPage } from "./shadow-claw-CGl8tXtG.js";
4
4
  import { i as joinRoomViaLink } from "./room-QujMjoxG.js";
5
- import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-Dlru5ofR.js";
6
- import { t as configurePeerJs } from "./configure-peer-js-ChDhOZU4.js";
5
+ import { c as getPeerJsConfig, d as setChannelEnabled } from "./channel-DB77spML.js";
6
+ import { t as configurePeerJs } from "./configure-peer-js-CgFiwoxY.js";
7
7
 
8
8
  //#region src/components/shadow-claw/utils/process-room-query-param.ts
9
9
  async function processRoomQueryParam(win, shadow, shadowClaw, db, orchestrator, oStore) {
@@ -38,4 +38,4 @@ async function processRoomQueryParam(win, shadow, shadowClaw, db, orchestrator,
38
38
 
39
39
  //#endregion
40
40
  export { processRoomQueryParam };
41
- //# sourceMappingURL=process-room-query-param-C3FFGGn6.js.map
41
+ //# sourceMappingURL=process-room-query-param-B8EYg_-r.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-room-query-param-C3FFGGn6.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-room-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\nimport { joinRoomViaLink } from \"../../../core/orchestrator/utils/operations/room.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processRoomQueryParam(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase,\n orchestrator: Orchestrator,\n oStore: OrchestratorStore,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const roomId = (currentUrl.searchParams.get(\"room\") || \"\").trim();\n const hostPeerId = (currentUrl.searchParams.get(\"host\") || \"\").trim();\n const roomName = (currentUrl.searchParams.get(\"name\") || \"\").trim() || \"Room\";\n\n if (!roomId || !hostPeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and the host is trusted\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(hostPeerId);\n\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Join the room (connects to host + announces membership)\n joinRoomViaLink(orchestrator, roomId, hostPeerId, roomName);\n\n // 3. Navigate to the room conversation\n await oStore.switchConversation(db, `room:${roomId}`);\n showPage(shadow, shadowClaw, db, oStore, \"chat\");\n\n // 4. Clean the URL to prevent re-triggering\n currentUrl.searchParams.delete(\"room\");\n currentUrl.searchParams.delete(\"host\");\n currentUrl.searchParams.delete(\"name\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Joined room \"${roomName}\"`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to join room: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAeA,eAAsB,sBACpB,KACA,QACA,YACA,IACA,cACA,QACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,UAAU,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CAChE,MAAM,cAAc,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CACpE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK,KAAK;CAEvE,IAAI,CAAC,UAAU,CAAC,YACd;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAGhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,UAAU;EAEtB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,gBAAgB,cAAc,QAAQ,YAAY,QAAQ;EAG1D,MAAM,OAAO,mBAAmB,IAAI,QAAQ,QAAQ;EACpD,SAAS,QAAQ,YAAY,IAAI,QAAQ,MAAM;EAG/C,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,IAAI,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAE/C,YAAY,gBAAgB,SAAS,EAAE;CACzC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,wBAAwB,WAAW,GAAI;CACnD;AACF"}
1
+ {"version":3,"file":"process-room-query-param-B8EYg_-r.js","names":[],"sources":["../../src/components/shadow-claw/utils/process-room-query-param.ts"],"sourcesContent":["import { configurePeerJs } from \"../../../core/orchestrator/utils/configure-peer-js.js\";\nimport {\n getPeerJsConfig,\n setChannelEnabled,\n} from \"../../../core/orchestrator/utils/operations/channel.js\";\nimport { joinRoomViaLink } from \"../../../core/orchestrator/utils/operations/room.js\";\nimport { showError, showSuccess } from \"../../../ui/toast.js\";\nimport { ulid } from \"../../../utils/ulid.js\";\nimport { showPage } from \"./show-page.js\";\n\nimport type { Orchestrator } from \"../../../core/orchestrator/orchestrator.js\";\nimport type { ShadowClawDatabase } from \"../../../db/types.js\";\nimport type { OrchestratorStore } from \"../../../stores/orchestrator.js\";\nimport type { ShadowClaw } from \"../shadow-claw.js\";\n\nexport async function processRoomQueryParam(\n win: Window,\n shadow: ShadowRoot | null,\n shadowClaw: ShadowClaw,\n db: ShadowClawDatabase,\n orchestrator: Orchestrator,\n oStore: OrchestratorStore,\n): Promise<void> {\n if (!db) {\n return;\n }\n\n const currentUrl = new URL(window.location?.href || \"http://localhost/\");\n const roomId = (currentUrl.searchParams.get(\"room\") || \"\").trim();\n const hostPeerId = (currentUrl.searchParams.get(\"host\") || \"\").trim();\n const roomName = (currentUrl.searchParams.get(\"name\") || \"\").trim() || \"Room\";\n\n if (!roomId || !hostPeerId) {\n return;\n }\n\n try {\n // 1. Ensure PeerJS channel is enabled and the host is trusted\n const cfg = getPeerJsConfig(orchestrator);\n let myPeerId = cfg.myPeerId;\n if (!myPeerId) {\n myPeerId = ulid().toLowerCase();\n }\n\n const trusted = new Set(cfg.trustedPeerIds);\n trusted.add(hostPeerId);\n\n await configurePeerJs(\n orchestrator,\n db,\n myPeerId,\n Array.from(trusted),\n cfg.serverHost,\n cfg.serverPort,\n cfg.serverPath,\n cfg.serverSecure,\n );\n\n if (!cfg.enabled) {\n await setChannelEnabled(orchestrator, db, \"peerjs\", true);\n }\n\n // 2. Join the room (connects to host + announces membership)\n joinRoomViaLink(orchestrator, roomId, hostPeerId, roomName);\n\n // 3. Navigate to the room conversation\n await oStore.switchConversation(db, `room:${roomId}`);\n showPage(shadow, shadowClaw, db, oStore, \"chat\");\n\n // 4. Clean the URL to prevent re-triggering\n currentUrl.searchParams.delete(\"room\");\n currentUrl.searchParams.delete(\"host\");\n currentUrl.searchParams.delete(\"name\");\n const cleaned = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;\n win.history.replaceState({}, \"\", cleaned || \"/\");\n\n showSuccess(`Joined room \"${roomName}\"`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n showError(`Failed to join room: ${message}`, 6000);\n }\n}\n"],"mappings":";;;;;;;;AAeA,eAAsB,sBACpB,KACA,QACA,YACA,IACA,cACA,QACe;CACf,IAAI,CAAC,IACH;CAGF,MAAM,aAAa,IAAI,IAAI,OAAO,UAAU,QAAQ,mBAAmB;CACvE,MAAM,UAAU,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CAChE,MAAM,cAAc,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK;CACpE,MAAM,YAAY,WAAW,aAAa,IAAI,MAAM,KAAK,GAAE,CAAE,KAAK,KAAK;CAEvE,IAAI,CAAC,UAAU,CAAC,YACd;CAGF,IAAI;EAEF,MAAM,MAAM,gBAAgB,YAAY;EACxC,IAAI,WAAW,IAAI;EACnB,IAAI,CAAC,UACH,WAAW,KAAK,CAAC,CAAC,YAAY;EAGhC,MAAM,UAAU,IAAI,IAAI,IAAI,cAAc;EAC1C,QAAQ,IAAI,UAAU;EAEtB,MAAM,gBACJ,cACA,IACA,UACA,MAAM,KAAK,OAAO,GAClB,IAAI,YACJ,IAAI,YACJ,IAAI,YACJ,IAAI,YACN;EAEA,IAAI,CAAC,IAAI,SACP,MAAM,kBAAkB,cAAc,IAAI,UAAU,IAAI;EAI1D,gBAAgB,cAAc,QAAQ,YAAY,QAAQ;EAG1D,MAAM,OAAO,mBAAmB,IAAI,QAAQ,QAAQ;EACpD,SAAS,QAAQ,YAAY,IAAI,QAAQ,MAAM;EAG/C,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,WAAW,aAAa,OAAO,MAAM;EACrC,MAAM,UAAU,GAAG,WAAW,WAAW,WAAW,SAAS,WAAW;EACxE,IAAI,QAAQ,aAAa,CAAC,GAAG,IAAI,WAAW,GAAG;EAE/C,YAAY,gBAAgB,SAAS,EAAE;CACzC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,UAAU,wBAAwB,WAAW,GAAI;CACnD;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { t as getConfig } from "./get-config-BWhs5HFF.js";
2
- import { C as PROVIDERS, F as getProvider, O as buildTriggerPattern, P as getModelMaxTokens, R as modelRegistry, c as DEFAULT_PROMPT_API_FALLBACK_MODEL, r as CONFIG_KEYS, y as LLAMAFILE_PROXY_URL } from "./config-DxNI3TlW.js";
3
- import { t as toolsStore } from "./tools-Beuyh8y1.js";
2
+ import { C as PROVIDERS, F as getProvider, O as buildTriggerPattern, P as getModelMaxTokens, R as modelRegistry, c as DEFAULT_PROMPT_API_FALLBACK_MODEL, r as CONFIG_KEYS, y as LLAMAFILE_PROXY_URL } from "./config-BrHR97zt.js";
3
+ import { t as toolsStore } from "./tools-B8OJ4sMF.js";
4
4
  import { t as setConfig } from "./set-config-CUadvYZ1.js";
5
5
 
6
6
  //#region src/subsystems/providers/utils/is-prompt-api-supported.ts
@@ -258,4 +258,4 @@ async function cancelLlamafileRequest(requestId) {
258
258
 
259
259
  //#endregion
260
260
  export { isPromptApiSupported as S, setPeerjsPeerAliases as _, getApiKeyForRequest as a, stopTransformersProgressPolling as b, getLlamafileSettings as c, setAssistantName as d, setBedrockSettings as f, setPeerjsMyAlias as g, setModel as h, getApiKeyForHeaders as i, getProviderRuntimeHeaders as l, setMeshLlmSettings as m, applyMeshLlmHeaders as n, getAvailableProviders as o, setLlamafileSettings as p, cancelLlamafileRequest as r, getBedrockSettings as s, applyLlamafileHeaders as t, getReasoningConfig as u, setProvider as v, getLanguageModelApi as x, startTransformersProgressPolling as y };
261
- //# sourceMappingURL=provider-DcQZypu5.js.map
261
+ //# sourceMappingURL=provider-BC9KPI14.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider-DcQZypu5.js","names":["_defaultSetConfig"],"sources":["../../src/subsystems/providers/utils/is-prompt-api-supported.ts","../../src/core/orchestrator/utils/operations/provider.ts"],"sourcesContent":["export function getLanguageModelApi(): {\n availability: Function;\n create: Function;\n} | null {\n const candidate = (globalThis as any).LanguageModel;\n if (!candidate || typeof candidate !== \"function\") {\n return null;\n }\n\n if (\n typeof candidate.availability !== \"function\" ||\n typeof candidate.create !== \"function\"\n ) {\n return null;\n }\n\n return candidate;\n}\n\n/**\n * Lightweight feature detection for the browser Prompt API.\n */\nexport function isPromptApiSupported(): boolean {\n return !!getLanguageModelApi();\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n LLAMAFILE_PROXY_URL,\n PROVIDERS,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../../config/config.js\";\n\nimport type { ProviderConfig } from \"../../../../config/config.js\";\nimport { getConfig } from \"../../../../db/get-config.js\";\nimport { setConfig as _defaultSetConfig } from \"../../../../db/set-config.js\";\nimport { toolsStore } from \"../../../../stores/tools.js\";\nimport { modelRegistry } from \"../../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../../subsystems/providers/utils/is-prompt-api-supported.js\";\n\nimport type { ShadowClawDatabase } from \"../../../../db/db.js\";\nimport type { LLMProvider } from \"../../../../subsystems/providers/types.js\";\nimport type { ModelDownloadProgressPayload } from \"../../../../subsystems/worker/types.js\";\nimport type { OrchestratorState } from \"../../orchestrator-state.js\";\nimport type { EventBus } from \"../event-bus.js\";\n\ntype SetConfigFn = (\n db: ShadowClawDatabase,\n key: string,\n value: string,\n) => Promise<void>;\n\nexport async function getApiKeyForHeaders(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string | undefined> {\n return (await orchestrator.getApiKey()) || undefined;\n}\n\nexport async function getApiKeyForRequest(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string> {\n return (await orchestrator.getApiKey()) || \"\";\n}\n\nexport function getLlamafileSettings(\n state: Pick<\n OrchestratorState,\n \"llamafileMode\" | \"llamafileHost\" | \"llamafilePort\" | \"llamafileOffline\"\n >,\n): {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n} {\n return {\n mode: state.llamafileMode,\n host: state.llamafileHost,\n port: state.llamafilePort,\n offline: state.llamafileOffline,\n };\n}\n\nexport function getMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\">,\n): { host: string } {\n return {\n host: state.meshLlmHost,\n };\n}\n\nexport function getBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n): {\n authMode: string;\n profile: string;\n region: string;\n} {\n return {\n authMode: state.bedrockAuthMode,\n profile: state.bedrockProfileFallback,\n region: state.bedrockRegionFallback,\n };\n}\n\nexport function getAvailableProviders(): LLMProvider[] {\n return Object.entries(PROVIDERS).map(([id, config]) => ({\n id,\n name: config.name,\n ...(!config.modelsUrl && {\n models:\n Array.isArray(config.models) && config.models.length > 0\n ? config.models\n : [config.defaultModel],\n }),\n ...(config.modelsUrl && { modelsUrl: config.modelsUrl }),\n ...(config.headers && { headers: config.headers }),\n ...(config.apiKeyHeader && { apiKeyHeader: config.apiKeyHeader }),\n ...(config.apiKeyHeaderFormat && {\n apiKeyHeaderFormat: config.apiKeyHeaderFormat,\n }),\n ...(typeof config.requiresApiKey === \"boolean\" && {\n requiresApiKey: config.requiresApiKey,\n }),\n }));\n}\n\nexport function getReasoningConfig(\n state: Pick<OrchestratorState, \"reasoningEffort\">,\n): { effort: string } | undefined {\n const effort =\n typeof state.reasoningEffort === \"string\"\n ? state.reasoningEffort.trim().toLowerCase()\n : \"none\";\n if (!effort || effort === \"none\") {\n return undefined;\n }\n\n return { effort };\n}\n\nexport function getProviderRuntimeHeaders(\n state: Pick<\n OrchestratorState,\n | \"bedrockAuthMode\"\n | \"bedrockProfileFallback\"\n | \"bedrockRegionFallback\"\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n >,\n providerId: string,\n requestId = \"\",\n overrides?: {\n bedrock_proxy?: {\n authMode?: \"provider_chain\" | \"sso\";\n profile?: string;\n region?: string;\n };\n llamafile?: {\n host?: string;\n mode?: \"cli\" | \"server\";\n offline?: boolean;\n port?: number;\n };\n },\n): Record<string, string> {\n if (providerId === \"llamafile\") {\n const llama = overrides?.llamafile;\n const headers: Record<string, string> = {\n \"x-llamafile-mode\":\n llama?.mode === \"server\" || llama?.mode === \"cli\"\n ? llama.mode\n : state.llamafileMode,\n \"x-llamafile-host\": llama?.host || state.llamafileHost,\n \"x-llamafile-port\": String(llama?.port || state.llamafilePort),\n \"x-llamafile-offline\":\n (llama?.offline ?? state.llamafileOffline) ? \"true\" : \"false\",\n };\n\n if (requestId) {\n headers[\"x-shadowclaw-request-id\"] = requestId;\n }\n\n return headers;\n }\n\n if (providerId === \"bedrock_proxy\") {\n const bedrock = overrides?.bedrock_proxy;\n const headers: Record<string, string> = {};\n if (bedrock?.region || state.bedrockRegionFallback) {\n headers[\"x-bedrock-region\"] =\n bedrock?.region || state.bedrockRegionFallback;\n }\n\n if (bedrock?.profile || state.bedrockProfileFallback) {\n headers[\"x-bedrock-profile\"] =\n bedrock?.profile || state.bedrockProfileFallback;\n }\n\n headers[\"x-bedrock-auth-mode\"] = bedrock?.authMode || state.bedrockAuthMode;\n\n return headers;\n }\n\n return {};\n}\n\nexport function applyLlamafileHeaders(\n state: Pick<\n OrchestratorState,\n | \"providerConfig\"\n | \"llamafileMode\"\n | \"llamafileHost\"\n | \"llamafilePort\"\n | \"llamafileOffline\"\n >,\n): void {\n if (state.providerConfig?.id !== \"llamafile\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-llamafile-mode\": state.llamafileMode,\n \"x-llamafile-host\": state.llamafileHost,\n \"x-llamafile-port\": String(state.llamafilePort),\n \"x-llamafile-offline\": state.llamafileOffline ? \"true\" : \"false\",\n },\n };\n}\n\nexport function applyMeshLlmHeaders(\n state: Pick<OrchestratorState, \"providerConfig\" | \"meshLlmHost\">,\n): void {\n if (state.providerConfig?.id !== \"mesh-llm\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-mesh-llm-host\": state.meshLlmHost,\n },\n };\n}\n\nexport function getTransformersStatusUrl(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n groupId?: string,\n): string {\n // If we have a groupId, check if there is an in-flight effective provider config for it\n if (groupId && state.inFlightEffectiveProviderByGroup) {\n const info = state.inFlightEffectiveProviderByGroup.get(groupId);\n if (info?.providerId === \"transformers_js_local\") {\n const base = info.providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n }\n\n // If the current providerConfig is transformers_js_local (or undefined for mock tests), use its baseUrl\n const providerConfig = state.providerConfig;\n if (\n providerConfig &&\n (!providerConfig.id || providerConfig.id === \"transformers_js_local\")\n ) {\n const base = providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n\n // Fallback to local transformers.js proxy status\n const localProvider = getProvider(\"transformers_js_local\");\n const base = localProvider?.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n\n return \"http://localhost:8888/transformers-js-proxy/status\";\n}\n\n// ── Async setters ───────────────────────────────────────────────────────────\n\nexport async function setAssistantName(\n state: Pick<OrchestratorState, \"assistantName\" | \"triggerPattern\">,\n db: ShadowClawDatabase,\n name: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.assistantName = name;\n state.triggerPattern = buildTriggerPattern(name);\n\n await _setConfig(db, CONFIG_KEYS.ASSISTANT_NAME, name);\n}\n\nexport async function setBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n db: ShadowClawDatabase,\n settings: { authMode: string; profile: string; region: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const region =\n typeof settings.region === \"string\" ? settings.region.trim() : \"\";\n const profile =\n typeof settings.profile === \"string\" ? settings.profile.trim() : \"\";\n const authMode = settings.authMode === \"sso\" ? \"sso\" : \"provider_chain\";\n\n state.bedrockRegionFallback = region;\n state.bedrockProfileFallback = profile;\n state.bedrockAuthMode = authMode;\n\n await _setConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK, region);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK, profile);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE, authMode);\n}\n\nexport async function setLlamafileSettings(\n state: Pick<\n OrchestratorState,\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n | \"providerConfig\"\n >,\n db: ShadowClawDatabase,\n settings: {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.llamafileMode = settings.mode;\n state.llamafileHost = settings.host;\n state.llamafilePort = settings.port;\n state.llamafileOffline = settings.offline;\n\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, settings.mode);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_HOST, settings.host);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_PORT, String(settings.port));\n await _setConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n settings.offline ? \"true\" : \"false\",\n );\n\n applyLlamafileHeaders(state);\n}\n\nexport async function setMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\" | \"providerConfig\">,\n db: ShadowClawDatabase,\n settings: { host: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.meshLlmHost = settings.host;\n\n await _setConfig(db, CONFIG_KEYS.MESH_LLM_HOST, settings.host);\n\n applyMeshLlmHeaders(state);\n}\n\nexport async function setModel(\n state: Pick<OrchestratorState, \"model\" | \"maxTokens\" | \"provider\">,\n db: ShadowClawDatabase,\n model: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.model = model;\n let effectiveModelForLimits = model;\n if (\n state.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (model === \"browser-built-in\" || !model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.MODEL, model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function setPeerjsMyAlias(\n state: Pick<OrchestratorState, \"peerjsMyAlias\">,\n db: ShadowClawDatabase,\n alias: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsMyAlias = alias.trim();\n\n await _setConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS, state.peerjsMyAlias);\n}\n\nexport async function setPeerjsPeerAliases(\n state: Pick<OrchestratorState, \"peerjsPeerAliases\">,\n db: ShadowClawDatabase,\n aliases: Record<string, string>,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsPeerAliases = { ...aliases };\n\n await _setConfig(\n db,\n CONFIG_KEYS.PEERJS_PEER_ALIASES,\n JSON.stringify(state.peerjsPeerAliases),\n );\n}\n\nexport async function autoActivateProfile(\n state: Pick<OrchestratorState, \"provider\" | \"model\">,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Preserve an explicit manual \"no tools\" configuration.\n if (!toolsStore.activeProfileId && toolsStore.enabledToolNames.size === 0) {\n return;\n }\n\n const candidates = toolsStore.findProfilesForProvider(\n state.provider,\n state.model,\n );\n\n if (candidates.length === 0) {\n return;\n }\n\n const exact = candidates.find(\n (p) => p.providerId === state.provider && p.model === state.model,\n );\n\n if (exact) {\n await toolsStore.activateProfile(db, exact.id);\n\n return;\n }\n\n const providerOnly = candidates.find(\n (p) => p.providerId === state.provider && !p.model,\n );\n\n if (providerOnly) {\n await toolsStore.activateProfile(db, providerOnly.id);\n }\n}\n\n/**\n * Switch the active LLM provider. This is more complex than the simple\n * settings because it also fetches model info and auto-activates profiles.\n */\nexport async function setProvider(\n state: OrchestratorState,\n db: ShadowClawDatabase,\n providerId: string,\n deps: {\n loadApiKeyForProvider: (\n db: ShadowClawDatabase,\n providerId: string,\n ) => Promise<void>;\n getApiKeyForHeaders: () => Promise<string | undefined>;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const newProvider = getProvider(providerId);\n if (!newProvider) {\n throw new Error(`Unknown provider: ${providerId}`);\n }\n\n state.provider = providerId;\n state.providerConfig = newProvider;\n state.model = newProvider.defaultModel;\n applyLlamafileHeaders(state);\n applyMeshLlmHeaders(state);\n\n await deps.loadApiKeyForProvider(db, providerId);\n\n await modelRegistry.fetchModelInfo(\n newProvider,\n (await deps.getApiKeyForHeaders()) || undefined,\n getProviderRuntimeHeaders(state, providerId),\n );\n\n let effectiveModelForLimits = state.model;\n if (\n providerId === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (state.model === \"browser-built-in\" || !state.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.PROVIDER, providerId);\n await _setConfig(db, CONFIG_KEYS.MODEL, state.model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function pollTransformersProgress(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n stopPolling: (groupId: string) => void,\n): Promise<void> {\n try {\n const url = getTransformersStatusUrl(state, groupId);\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!res.ok) {\n return;\n }\n\n const status = await res.json();\n const raw = Number(status?.progress);\n const normalizedProgress =\n Number.isFinite(raw) && raw > 1\n ? Math.max(0, Math.min(1, raw / 100))\n : Number.isFinite(raw)\n ? Math.max(0, Math.min(1, raw))\n : null;\n\n const payload: ModelDownloadProgressPayload = {\n groupId,\n message:\n typeof status?.message === \"string\" && status.message\n ? status.message\n : undefined,\n progress: normalizedProgress,\n status:\n status?.status === \"done\" || status?.status === \"error\"\n ? status.status\n : \"running\",\n };\n\n events.emit(\"model-download-progress\", payload);\n\n if (payload.status === \"done\" || payload.status === \"error\") {\n stopPolling(groupId);\n }\n } catch {\n // Ignore status polling failures so inference can continue uninterrupted.\n }\n}\n\nexport function startTransformersProgressPolling(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n transformersProgressPollers: Map<string, number>;\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n): void {\n stopTransformersProgressPolling(state, groupId);\n\n // Show immediate feedback while the first network poll is in flight.\n events.emit(\"model-download-progress\", {\n groupId,\n message: \"Preparing local model download...\",\n progress: null,\n status: \"running\",\n });\n\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n\n const timer = setInterval(() => {\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n }, 1000);\n\n state.transformersProgressPollers.set(groupId, timer as unknown as number);\n}\n\nexport function stopTransformersProgressPolling(\n state: { transformersProgressPollers: Map<string, number> },\n groupId: string,\n): void {\n const timer = state.transformersProgressPollers.get(groupId);\n if (typeof timer === \"number\") {\n clearInterval(timer);\n\n state.transformersProgressPollers.delete(groupId);\n }\n}\n\nexport async function cancelLlamafileRequest(requestId: string): Promise<void> {\n try {\n await fetch(LLAMAFILE_PROXY_URL.replace(\"/chat/completions\", \"/cancel\"), {\n body: JSON.stringify({ requestId }),\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-shadowclaw-request-id\": requestId,\n },\n keepalive: true,\n method: \"POST\",\n });\n } catch {\n // Best-effort cancellation only.\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"provider-BC9KPI14.js","names":["_defaultSetConfig"],"sources":["../../src/subsystems/providers/utils/is-prompt-api-supported.ts","../../src/core/orchestrator/utils/operations/provider.ts"],"sourcesContent":["export function getLanguageModelApi(): {\n availability: Function;\n create: Function;\n} | null {\n const candidate = (globalThis as any).LanguageModel;\n if (!candidate || typeof candidate !== \"function\") {\n return null;\n }\n\n if (\n typeof candidate.availability !== \"function\" ||\n typeof candidate.create !== \"function\"\n ) {\n return null;\n }\n\n return candidate;\n}\n\n/**\n * Lightweight feature detection for the browser Prompt API.\n */\nexport function isPromptApiSupported(): boolean {\n return !!getLanguageModelApi();\n}\n","import {\n CONFIG_KEYS,\n DEFAULT_PROMPT_API_FALLBACK_MODEL,\n LLAMAFILE_PROXY_URL,\n PROVIDERS,\n buildTriggerPattern,\n getModelMaxTokens,\n getProvider,\n} from \"../../../../config/config.js\";\n\nimport type { ProviderConfig } from \"../../../../config/config.js\";\nimport { getConfig } from \"../../../../db/get-config.js\";\nimport { setConfig as _defaultSetConfig } from \"../../../../db/set-config.js\";\nimport { toolsStore } from \"../../../../stores/tools.js\";\nimport { modelRegistry } from \"../../../../subsystems/providers/model-registry.js\";\nimport { isPromptApiSupported } from \"../../../../subsystems/providers/utils/is-prompt-api-supported.js\";\n\nimport type { ShadowClawDatabase } from \"../../../../db/db.js\";\nimport type { LLMProvider } from \"../../../../subsystems/providers/types.js\";\nimport type { ModelDownloadProgressPayload } from \"../../../../subsystems/worker/types.js\";\nimport type { OrchestratorState } from \"../../orchestrator-state.js\";\nimport type { EventBus } from \"../event-bus.js\";\n\ntype SetConfigFn = (\n db: ShadowClawDatabase,\n key: string,\n value: string,\n) => Promise<void>;\n\nexport async function getApiKeyForHeaders(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string | undefined> {\n return (await orchestrator.getApiKey()) || undefined;\n}\n\nexport async function getApiKeyForRequest(orchestrator: {\n getApiKey: () => Promise<string | null>;\n}): Promise<string> {\n return (await orchestrator.getApiKey()) || \"\";\n}\n\nexport function getLlamafileSettings(\n state: Pick<\n OrchestratorState,\n \"llamafileMode\" | \"llamafileHost\" | \"llamafilePort\" | \"llamafileOffline\"\n >,\n): {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n} {\n return {\n mode: state.llamafileMode,\n host: state.llamafileHost,\n port: state.llamafilePort,\n offline: state.llamafileOffline,\n };\n}\n\nexport function getMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\">,\n): { host: string } {\n return {\n host: state.meshLlmHost,\n };\n}\n\nexport function getBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n): {\n authMode: string;\n profile: string;\n region: string;\n} {\n return {\n authMode: state.bedrockAuthMode,\n profile: state.bedrockProfileFallback,\n region: state.bedrockRegionFallback,\n };\n}\n\nexport function getAvailableProviders(): LLMProvider[] {\n return Object.entries(PROVIDERS).map(([id, config]) => ({\n id,\n name: config.name,\n ...(!config.modelsUrl && {\n models:\n Array.isArray(config.models) && config.models.length > 0\n ? config.models\n : [config.defaultModel],\n }),\n ...(config.modelsUrl && { modelsUrl: config.modelsUrl }),\n ...(config.headers && { headers: config.headers }),\n ...(config.apiKeyHeader && { apiKeyHeader: config.apiKeyHeader }),\n ...(config.apiKeyHeaderFormat && {\n apiKeyHeaderFormat: config.apiKeyHeaderFormat,\n }),\n ...(typeof config.requiresApiKey === \"boolean\" && {\n requiresApiKey: config.requiresApiKey,\n }),\n }));\n}\n\nexport function getReasoningConfig(\n state: Pick<OrchestratorState, \"reasoningEffort\">,\n): { effort: string } | undefined {\n const effort =\n typeof state.reasoningEffort === \"string\"\n ? state.reasoningEffort.trim().toLowerCase()\n : \"none\";\n if (!effort || effort === \"none\") {\n return undefined;\n }\n\n return { effort };\n}\n\nexport function getProviderRuntimeHeaders(\n state: Pick<\n OrchestratorState,\n | \"bedrockAuthMode\"\n | \"bedrockProfileFallback\"\n | \"bedrockRegionFallback\"\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n >,\n providerId: string,\n requestId = \"\",\n overrides?: {\n bedrock_proxy?: {\n authMode?: \"provider_chain\" | \"sso\";\n profile?: string;\n region?: string;\n };\n llamafile?: {\n host?: string;\n mode?: \"cli\" | \"server\";\n offline?: boolean;\n port?: number;\n };\n },\n): Record<string, string> {\n if (providerId === \"llamafile\") {\n const llama = overrides?.llamafile;\n const headers: Record<string, string> = {\n \"x-llamafile-mode\":\n llama?.mode === \"server\" || llama?.mode === \"cli\"\n ? llama.mode\n : state.llamafileMode,\n \"x-llamafile-host\": llama?.host || state.llamafileHost,\n \"x-llamafile-port\": String(llama?.port || state.llamafilePort),\n \"x-llamafile-offline\":\n (llama?.offline ?? state.llamafileOffline) ? \"true\" : \"false\",\n };\n\n if (requestId) {\n headers[\"x-shadowclaw-request-id\"] = requestId;\n }\n\n return headers;\n }\n\n if (providerId === \"bedrock_proxy\") {\n const bedrock = overrides?.bedrock_proxy;\n const headers: Record<string, string> = {};\n if (bedrock?.region || state.bedrockRegionFallback) {\n headers[\"x-bedrock-region\"] =\n bedrock?.region || state.bedrockRegionFallback;\n }\n\n if (bedrock?.profile || state.bedrockProfileFallback) {\n headers[\"x-bedrock-profile\"] =\n bedrock?.profile || state.bedrockProfileFallback;\n }\n\n headers[\"x-bedrock-auth-mode\"] = bedrock?.authMode || state.bedrockAuthMode;\n\n return headers;\n }\n\n return {};\n}\n\nexport function applyLlamafileHeaders(\n state: Pick<\n OrchestratorState,\n | \"providerConfig\"\n | \"llamafileMode\"\n | \"llamafileHost\"\n | \"llamafilePort\"\n | \"llamafileOffline\"\n >,\n): void {\n if (state.providerConfig?.id !== \"llamafile\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-llamafile-mode\": state.llamafileMode,\n \"x-llamafile-host\": state.llamafileHost,\n \"x-llamafile-port\": String(state.llamafilePort),\n \"x-llamafile-offline\": state.llamafileOffline ? \"true\" : \"false\",\n },\n };\n}\n\nexport function applyMeshLlmHeaders(\n state: Pick<OrchestratorState, \"providerConfig\" | \"meshLlmHost\">,\n): void {\n if (state.providerConfig?.id !== \"mesh-llm\") {\n return;\n }\n\n state.providerConfig = {\n ...state.providerConfig,\n headers: {\n ...(state.providerConfig.headers || {}),\n \"x-mesh-llm-host\": state.meshLlmHost,\n },\n };\n}\n\nexport function getTransformersStatusUrl(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n groupId?: string,\n): string {\n // If we have a groupId, check if there is an in-flight effective provider config for it\n if (groupId && state.inFlightEffectiveProviderByGroup) {\n const info = state.inFlightEffectiveProviderByGroup.get(groupId);\n if (info?.providerId === \"transformers_js_local\") {\n const base = info.providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n }\n\n // If the current providerConfig is transformers_js_local (or undefined for mock tests), use its baseUrl\n const providerConfig = state.providerConfig;\n if (\n providerConfig &&\n (!providerConfig.id || providerConfig.id === \"transformers_js_local\")\n ) {\n const base = providerConfig.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n }\n\n // Fallback to local transformers.js proxy status\n const localProvider = getProvider(\"transformers_js_local\");\n const base = localProvider?.baseUrl || \"\";\n if (base.includes(\"/chat/completions\")) {\n return base.replace(\"/chat/completions\", \"/status\");\n }\n\n return \"http://localhost:8888/transformers-js-proxy/status\";\n}\n\n// ── Async setters ───────────────────────────────────────────────────────────\n\nexport async function setAssistantName(\n state: Pick<OrchestratorState, \"assistantName\" | \"triggerPattern\">,\n db: ShadowClawDatabase,\n name: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.assistantName = name;\n state.triggerPattern = buildTriggerPattern(name);\n\n await _setConfig(db, CONFIG_KEYS.ASSISTANT_NAME, name);\n}\n\nexport async function setBedrockSettings(\n state: Pick<\n OrchestratorState,\n \"bedrockAuthMode\" | \"bedrockProfileFallback\" | \"bedrockRegionFallback\"\n >,\n db: ShadowClawDatabase,\n settings: { authMode: string; profile: string; region: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const region =\n typeof settings.region === \"string\" ? settings.region.trim() : \"\";\n const profile =\n typeof settings.profile === \"string\" ? settings.profile.trim() : \"\";\n const authMode = settings.authMode === \"sso\" ? \"sso\" : \"provider_chain\";\n\n state.bedrockRegionFallback = region;\n state.bedrockProfileFallback = profile;\n state.bedrockAuthMode = authMode;\n\n await _setConfig(db, CONFIG_KEYS.BEDROCK_REGION_FALLBACK, region);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_PROFILE_FALLBACK, profile);\n await _setConfig(db, CONFIG_KEYS.BEDROCK_AUTH_MODE, authMode);\n}\n\nexport async function setLlamafileSettings(\n state: Pick<\n OrchestratorState,\n | \"llamafileHost\"\n | \"llamafileMode\"\n | \"llamafileOffline\"\n | \"llamafilePort\"\n | \"providerConfig\"\n >,\n db: ShadowClawDatabase,\n settings: {\n host: string;\n mode: \"server\" | \"cli\";\n offline: boolean;\n port: number;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.llamafileMode = settings.mode;\n state.llamafileHost = settings.host;\n state.llamafilePort = settings.port;\n state.llamafileOffline = settings.offline;\n\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_MODE, settings.mode);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_HOST, settings.host);\n await _setConfig(db, CONFIG_KEYS.LLAMAFILE_PORT, String(settings.port));\n await _setConfig(\n db,\n CONFIG_KEYS.LLAMAFILE_OFFLINE,\n settings.offline ? \"true\" : \"false\",\n );\n\n applyLlamafileHeaders(state);\n}\n\nexport async function setMeshLlmSettings(\n state: Pick<OrchestratorState, \"meshLlmHost\" | \"providerConfig\">,\n db: ShadowClawDatabase,\n settings: { host: string },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.meshLlmHost = settings.host;\n\n await _setConfig(db, CONFIG_KEYS.MESH_LLM_HOST, settings.host);\n\n applyMeshLlmHeaders(state);\n}\n\nexport async function setModel(\n state: Pick<OrchestratorState, \"model\" | \"maxTokens\" | \"provider\">,\n db: ShadowClawDatabase,\n model: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.model = model;\n let effectiveModelForLimits = model;\n if (\n state.provider === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (model === \"browser-built-in\" || !model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.MODEL, model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function setPeerjsMyAlias(\n state: Pick<OrchestratorState, \"peerjsMyAlias\">,\n db: ShadowClawDatabase,\n alias: string,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsMyAlias = alias.trim();\n\n await _setConfig(db, CONFIG_KEYS.PEERJS_MY_ALIAS, state.peerjsMyAlias);\n}\n\nexport async function setPeerjsPeerAliases(\n state: Pick<OrchestratorState, \"peerjsPeerAliases\">,\n db: ShadowClawDatabase,\n aliases: Record<string, string>,\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n state.peerjsPeerAliases = { ...aliases };\n\n await _setConfig(\n db,\n CONFIG_KEYS.PEERJS_PEER_ALIASES,\n JSON.stringify(state.peerjsPeerAliases),\n );\n}\n\nexport async function autoActivateProfile(\n state: Pick<OrchestratorState, \"provider\" | \"model\">,\n db: ShadowClawDatabase,\n): Promise<void> {\n // Preserve an explicit manual \"no tools\" configuration.\n if (!toolsStore.activeProfileId && toolsStore.enabledToolNames.size === 0) {\n return;\n }\n\n const candidates = toolsStore.findProfilesForProvider(\n state.provider,\n state.model,\n );\n\n if (candidates.length === 0) {\n return;\n }\n\n const exact = candidates.find(\n (p) => p.providerId === state.provider && p.model === state.model,\n );\n\n if (exact) {\n await toolsStore.activateProfile(db, exact.id);\n\n return;\n }\n\n const providerOnly = candidates.find(\n (p) => p.providerId === state.provider && !p.model,\n );\n\n if (providerOnly) {\n await toolsStore.activateProfile(db, providerOnly.id);\n }\n}\n\n/**\n * Switch the active LLM provider. This is more complex than the simple\n * settings because it also fetches model info and auto-activates profiles.\n */\nexport async function setProvider(\n state: OrchestratorState,\n db: ShadowClawDatabase,\n providerId: string,\n deps: {\n loadApiKeyForProvider: (\n db: ShadowClawDatabase,\n providerId: string,\n ) => Promise<void>;\n getApiKeyForHeaders: () => Promise<string | undefined>;\n },\n _setConfig: SetConfigFn = _defaultSetConfig,\n): Promise<void> {\n const newProvider = getProvider(providerId);\n if (!newProvider) {\n throw new Error(`Unknown provider: ${providerId}`);\n }\n\n state.provider = providerId;\n state.providerConfig = newProvider;\n state.model = newProvider.defaultModel;\n applyLlamafileHeaders(state);\n applyMeshLlmHeaders(state);\n\n await deps.loadApiKeyForProvider(db, providerId);\n\n await modelRegistry.fetchModelInfo(\n newProvider,\n (await deps.getApiKeyForHeaders()) || undefined,\n getProviderRuntimeHeaders(state, providerId),\n );\n\n let effectiveModelForLimits = state.model;\n if (\n providerId === \"prompt_api\" &&\n !isPromptApiSupported() &&\n (state.model === \"browser-built-in\" || !state.model)\n ) {\n const configuredFallback = await getConfig(\n db,\n CONFIG_KEYS.PROMPT_API_FALLBACK_MODEL,\n );\n effectiveModelForLimits =\n configuredFallback || DEFAULT_PROMPT_API_FALLBACK_MODEL;\n }\n\n state.maxTokens = getModelMaxTokens(effectiveModelForLimits);\n\n await _setConfig(db, CONFIG_KEYS.PROVIDER, providerId);\n await _setConfig(db, CONFIG_KEYS.MODEL, state.model);\n\n await autoActivateProfile(state, db);\n}\n\nexport async function pollTransformersProgress(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n stopPolling: (groupId: string) => void,\n): Promise<void> {\n try {\n const url = getTransformersStatusUrl(state, groupId);\n const res = await fetch(url, {\n headers: {\n Accept: \"application/json\",\n },\n method: \"GET\",\n });\n\n if (!res.ok) {\n return;\n }\n\n const status = await res.json();\n const raw = Number(status?.progress);\n const normalizedProgress =\n Number.isFinite(raw) && raw > 1\n ? Math.max(0, Math.min(1, raw / 100))\n : Number.isFinite(raw)\n ? Math.max(0, Math.min(1, raw))\n : null;\n\n const payload: ModelDownloadProgressPayload = {\n groupId,\n message:\n typeof status?.message === \"string\" && status.message\n ? status.message\n : undefined,\n progress: normalizedProgress,\n status:\n status?.status === \"done\" || status?.status === \"error\"\n ? status.status\n : \"running\",\n };\n\n events.emit(\"model-download-progress\", payload);\n\n if (payload.status === \"done\" || payload.status === \"error\") {\n stopPolling(groupId);\n }\n } catch {\n // Ignore status polling failures so inference can continue uninterrupted.\n }\n}\n\nexport function startTransformersProgressPolling(\n state: Pick<\n OrchestratorState,\n \"providerConfig\" | \"inFlightEffectiveProviderByGroup\"\n > & {\n transformersProgressPollers: Map<string, number>;\n inFlightEffectiveProviderByGroup?: Map<\n string,\n { providerId: string; providerConfig: ProviderConfig; model: string }\n >;\n },\n events: EventBus,\n groupId: string,\n): void {\n stopTransformersProgressPolling(state, groupId);\n\n // Show immediate feedback while the first network poll is in flight.\n events.emit(\"model-download-progress\", {\n groupId,\n message: \"Preparing local model download...\",\n progress: null,\n status: \"running\",\n });\n\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n\n const timer = setInterval(() => {\n void pollTransformersProgress(state, events, groupId, (gid) =>\n stopTransformersProgressPolling(state, gid),\n );\n }, 1000);\n\n state.transformersProgressPollers.set(groupId, timer as unknown as number);\n}\n\nexport function stopTransformersProgressPolling(\n state: { transformersProgressPollers: Map<string, number> },\n groupId: string,\n): void {\n const timer = state.transformersProgressPollers.get(groupId);\n if (typeof timer === \"number\") {\n clearInterval(timer);\n\n state.transformersProgressPollers.delete(groupId);\n }\n}\n\nexport async function cancelLlamafileRequest(requestId: string): Promise<void> {\n try {\n await fetch(LLAMAFILE_PROXY_URL.replace(\"/chat/completions\", \"/cancel\"), {\n body: JSON.stringify({ requestId }),\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-shadowclaw-request-id\": requestId,\n },\n keepalive: true,\n method: \"POST\",\n });\n } catch {\n // Best-effort cancellation only.\n }\n}\n"],"mappings":";;;;;;AAAA,SAAgB,sBAGP;CACP,MAAM,YAAa,WAAmB;CACtC,IAAI,CAAC,aAAa,OAAO,cAAc,YACrC,OAAO;CAGT,IACE,OAAO,UAAU,iBAAiB,cAClC,OAAO,UAAU,WAAW,YAE5B,OAAO;CAGT,OAAO;AACT;;;;AAKA,SAAgB,uBAAgC;CAC9C,OAAO,CAAC,CAAC,oBAAoB;AAC/B;;;;ACKA,eAAsB,oBAAoB,cAEV;CAC9B,OAAQ,MAAM,aAAa,UAAU,KAAM;AAC7C;AAEA,eAAsB,oBAAoB,cAEtB;CAClB,OAAQ,MAAM,aAAa,UAAU,KAAM;AAC7C;AAEA,SAAgB,qBACd,OASA;CACA,OAAO;EACL,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,SAAS,MAAM;CACjB;AACF;AAUA,SAAgB,mBACd,OAQA;CACA,OAAO;EACL,UAAU,MAAM;EAChB,SAAS,MAAM;EACf,QAAQ,MAAM;CAChB;AACF;AAEA,SAAgB,wBAAuC;CACrD,OAAO,OAAO,QAAQ,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,aAAa;EACtD;EACA,MAAM,OAAO;EACb,GAAI,CAAC,OAAO,aAAa,EACvB,QACE,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,OAAO,SAAS,IACnD,OAAO,SACP,CAAC,OAAO,YAAY,EAC5B;EACA,GAAI,OAAO,aAAa,EAAE,WAAW,OAAO,UAAU;EACtD,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,QAAQ;EAChD,GAAI,OAAO,gBAAgB,EAAE,cAAc,OAAO,aAAa;EAC/D,GAAI,OAAO,sBAAsB,EAC/B,oBAAoB,OAAO,mBAC7B;EACA,GAAI,OAAO,OAAO,mBAAmB,aAAa,EAChD,gBAAgB,OAAO,eACzB;CACF,EAAE;AACJ;AAEA,SAAgB,mBACd,OACgC;CAChC,MAAM,SACJ,OAAO,MAAM,oBAAoB,WAC7B,MAAM,gBAAgB,KAAK,CAAC,CAAC,YAAY,IACzC;CACN,IAAI,CAAC,UAAU,WAAW,QACxB;CAGF,OAAO,EAAE,OAAO;AAClB;AAEA,SAAgB,0BACd,OAUA,YACA,YAAY,IACZ,WAawB;CACxB,IAAI,eAAe,aAAa;EAC9B,MAAM,QAAQ,WAAW;EACzB,MAAM,UAAkC;GACtC,oBACE,OAAO,SAAS,YAAY,OAAO,SAAS,QACxC,MAAM,OACN,MAAM;GACZ,oBAAoB,OAAO,QAAQ,MAAM;GACzC,oBAAoB,OAAO,OAAO,QAAQ,MAAM,aAAa;GAC7D,uBACG,OAAO,WAAW,MAAM,mBAAoB,SAAS;EAC1D;EAEA,IAAI,WACF,QAAQ,6BAA6B;EAGvC,OAAO;CACT;CAEA,IAAI,eAAe,iBAAiB;EAClC,MAAM,UAAU,WAAW;EAC3B,MAAM,UAAkC,CAAC;EACzC,IAAI,SAAS,UAAU,MAAM,uBAC3B,QAAQ,sBACN,SAAS,UAAU,MAAM;EAG7B,IAAI,SAAS,WAAW,MAAM,wBAC5B,QAAQ,uBACN,SAAS,WAAW,MAAM;EAG9B,QAAQ,yBAAyB,SAAS,YAAY,MAAM;EAE5D,OAAO;CACT;CAEA,OAAO,CAAC;AACV;AAEA,SAAgB,sBACd,OAQM;CACN,IAAI,MAAM,gBAAgB,OAAO,aAC/B;CAGF,MAAM,iBAAiB;EACrB,GAAG,MAAM;EACT,SAAS;GACP,GAAI,MAAM,eAAe,WAAW,CAAC;GACrC,oBAAoB,MAAM;GAC1B,oBAAoB,MAAM;GAC1B,oBAAoB,OAAO,MAAM,aAAa;GAC9C,uBAAuB,MAAM,mBAAmB,SAAS;EAC3D;CACF;AACF;AAEA,SAAgB,oBACd,OACM;CACN,IAAI,MAAM,gBAAgB,OAAO,YAC/B;CAGF,MAAM,iBAAiB;EACrB,GAAG,MAAM;EACT,SAAS;GACP,GAAI,MAAM,eAAe,WAAW,CAAC;GACrC,mBAAmB,MAAM;EAC3B;CACF;AACF;AAEA,SAAgB,yBACd,OASA,SACQ;CAER,IAAI,WAAW,MAAM,kCAAkC;EACrD,MAAM,OAAO,MAAM,iCAAiC,IAAI,OAAO;EAC/D,IAAI,MAAM,eAAe,yBAAyB;GAChD,MAAM,OAAO,KAAK,eAAe,WAAW;GAC5C,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;EAEtD;CACF;CAGA,MAAM,iBAAiB,MAAM;CAC7B,IACE,mBACC,CAAC,eAAe,MAAM,eAAe,OAAO,0BAC7C;EACA,MAAM,OAAO,eAAe,WAAW;EACvC,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;CAEtD;CAIA,MAAM,OADgB,YAAY,uBACT,CAAC,EAAE,WAAW;CACvC,IAAI,KAAK,SAAS,mBAAmB,GACnC,OAAO,KAAK,QAAQ,qBAAqB,SAAS;CAGpD,OAAO;AACT;AAIA,eAAsB,iBACpB,OACA,IACA,MACA,aAA0BA,WACX;CACf,MAAM,gBAAgB;CACtB,MAAM,iBAAiB,oBAAoB,IAAI;CAE/C,MAAM,WAAW,IAAI,YAAY,gBAAgB,IAAI;AACvD;AAEA,eAAsB,mBACpB,OAIA,IACA,UACA,aAA0BA,WACX;CACf,MAAM,SACJ,OAAO,SAAS,WAAW,WAAW,SAAS,OAAO,KAAK,IAAI;CACjE,MAAM,UACJ,OAAO,SAAS,YAAY,WAAW,SAAS,QAAQ,KAAK,IAAI;CACnE,MAAM,WAAW,SAAS,aAAa,QAAQ,QAAQ;CAEvD,MAAM,wBAAwB;CAC9B,MAAM,yBAAyB;CAC/B,MAAM,kBAAkB;CAExB,MAAM,WAAW,IAAI,YAAY,yBAAyB,MAAM;CAChE,MAAM,WAAW,IAAI,YAAY,0BAA0B,OAAO;CAClE,MAAM,WAAW,IAAI,YAAY,mBAAmB,QAAQ;AAC9D;AAEA,eAAsB,qBACpB,OAQA,IACA,UAMA,aAA0BA,WACX;CACf,MAAM,gBAAgB,SAAS;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,MAAM,gBAAgB,SAAS;CAC/B,MAAM,mBAAmB,SAAS;CAElC,MAAM,WAAW,IAAI,YAAY,gBAAgB,SAAS,IAAI;CAC9D,MAAM,WAAW,IAAI,YAAY,gBAAgB,SAAS,IAAI;CAC9D,MAAM,WAAW,IAAI,YAAY,gBAAgB,OAAO,SAAS,IAAI,CAAC;CACtE,MAAM,WACJ,IACA,YAAY,mBACZ,SAAS,UAAU,SAAS,OAC9B;CAEA,sBAAsB,KAAK;AAC7B;AAEA,eAAsB,mBACpB,OACA,IACA,UACA,aAA0BA,WACX;CACf,MAAM,cAAc,SAAS;CAE7B,MAAM,WAAW,IAAI,YAAY,eAAe,SAAS,IAAI;CAE7D,oBAAoB,KAAK;AAC3B;AAEA,eAAsB,SACpB,OACA,IACA,OACA,aAA0BA,WACX;CACf,MAAM,QAAQ;CACd,IAAI,0BAA0B;CAC9B,IACE,MAAM,aAAa,gBACnB,CAAC,qBAAqB,MACrB,UAAU,sBAAsB,CAAC,QAMlC,0BACE,MAL+B,UAC/B,IACA,YAAY,yBACd;CAIF,MAAM,YAAY,kBAAkB,uBAAuB;CAE3D,MAAM,WAAW,IAAI,YAAY,OAAO,KAAK;CAE7C,MAAM,oBAAoB,OAAO,EAAE;AACrC;AAEA,eAAsB,iBACpB,OACA,IACA,OACA,aAA0BA,WACX;CACf,MAAM,gBAAgB,MAAM,KAAK;CAEjC,MAAM,WAAW,IAAI,YAAY,iBAAiB,MAAM,aAAa;AACvE;AAEA,eAAsB,qBACpB,OACA,IACA,SACA,aAA0BA,WACX;CACf,MAAM,oBAAoB,EAAE,GAAG,QAAQ;CAEvC,MAAM,WACJ,IACA,YAAY,qBACZ,KAAK,UAAU,MAAM,iBAAiB,CACxC;AACF;AAEA,eAAsB,oBACpB,OACA,IACe;CAEf,IAAI,CAAC,WAAW,mBAAmB,WAAW,iBAAiB,SAAS,GACtE;CAGF,MAAM,aAAa,WAAW,wBAC5B,MAAM,UACN,MAAM,KACR;CAEA,IAAI,WAAW,WAAW,GACxB;CAGF,MAAM,QAAQ,WAAW,MACtB,MAAM,EAAE,eAAe,MAAM,YAAY,EAAE,UAAU,MAAM,KAC9D;CAEA,IAAI,OAAO;EACT,MAAM,WAAW,gBAAgB,IAAI,MAAM,EAAE;EAE7C;CACF;CAEA,MAAM,eAAe,WAAW,MAC7B,MAAM,EAAE,eAAe,MAAM,YAAY,CAAC,EAAE,KAC/C;CAEA,IAAI,cACF,MAAM,WAAW,gBAAgB,IAAI,aAAa,EAAE;AAExD;;;;;AAMA,eAAsB,YACpB,OACA,IACA,YACA,MAOA,aAA0BA,WACX;CACf,MAAM,cAAc,YAAY,UAAU;CAC1C,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,qBAAqB,YAAY;CAGnD,MAAM,WAAW;CACjB,MAAM,iBAAiB;CACvB,MAAM,QAAQ,YAAY;CAC1B,sBAAsB,KAAK;CAC3B,oBAAoB,KAAK;CAEzB,MAAM,KAAK,sBAAsB,IAAI,UAAU;CAE/C,MAAM,cAAc,eAClB,aACC,MAAM,KAAK,oBAAoB,KAAM,QACtC,0BAA0B,OAAO,UAAU,CAC7C;CAEA,IAAI,0BAA0B,MAAM;CACpC,IACE,eAAe,gBACf,CAAC,qBAAqB,MACrB,MAAM,UAAU,sBAAsB,CAAC,MAAM,QAM9C,0BACE,MAL+B,UAC/B,IACA,YAAY,yBACd;CAKF,MAAM,YAAY,kBAAkB,uBAAuB;CAE3D,MAAM,WAAW,IAAI,YAAY,UAAU,UAAU;CACrD,MAAM,WAAW,IAAI,YAAY,OAAO,MAAM,KAAK;CAEnD,MAAM,oBAAoB,OAAO,EAAE;AACrC;AAEA,eAAsB,yBACpB,OASA,QACA,SACA,aACe;CACf,IAAI;EACF,MAAM,MAAM,yBAAyB,OAAO,OAAO;EACnD,MAAM,MAAM,MAAM,MAAM,KAAK;GAC3B,SAAS,EACP,QAAQ,mBACV;GACA,QAAQ;EACV,CAAC;EAED,IAAI,CAAC,IAAI,IACP;EAGF,MAAM,SAAS,MAAM,IAAI,KAAK;EAC9B,MAAM,MAAM,OAAO,QAAQ,QAAQ;EACnC,MAAM,qBACJ,OAAO,SAAS,GAAG,KAAK,MAAM,IAC1B,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,IAClC,OAAO,SAAS,GAAG,IACjB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC,IAC5B;EAER,MAAM,UAAwC;GAC5C;GACA,SACE,OAAO,QAAQ,YAAY,YAAY,OAAO,UAC1C,OAAO,UACP;GACN,UAAU;GACV,QACE,QAAQ,WAAW,UAAU,QAAQ,WAAW,UAC5C,OAAO,SACP;EACR;EAEA,OAAO,KAAK,2BAA2B,OAAO;EAE9C,IAAI,QAAQ,WAAW,UAAU,QAAQ,WAAW,SAClD,YAAY,OAAO;CAEvB,QAAQ,CAER;AACF;AAEA,SAAgB,iCACd,OAUA,QACA,SACM;CACN,gCAAgC,OAAO,OAAO;CAG9C,OAAO,KAAK,2BAA2B;EACrC;EACA,SAAS;EACT,UAAU;EACV,QAAQ;CACV,CAAC;CAED,AAAK,yBAAyB,OAAO,QAAQ,UAAU,QACrD,gCAAgC,OAAO,GAAG,CAC5C;CAEA,MAAM,QAAQ,kBAAkB;EAC9B,AAAK,yBAAyB,OAAO,QAAQ,UAAU,QACrD,gCAAgC,OAAO,GAAG,CAC5C;CACF,GAAG,GAAI;CAEP,MAAM,4BAA4B,IAAI,SAAS,KAA0B;AAC3E;AAEA,SAAgB,gCACd,OACA,SACM;CACN,MAAM,QAAQ,MAAM,4BAA4B,IAAI,OAAO;CAC3D,IAAI,OAAO,UAAU,UAAU;EAC7B,cAAc,KAAK;EAEnB,MAAM,4BAA4B,OAAO,OAAO;CAClD;AACF;AAEA,eAAsB,uBAAuB,WAAkC;CAC7E,IAAI;EACF,MAAM,MAAM,oBAAoB,QAAQ,qBAAqB,SAAS,GAAG;GACvE,MAAM,KAAK,UAAU,EAAE,UAAU,CAAC;GAClC,SAAS;IACP,gBAAgB;IAChB,2BAA2B;GAC7B;GACA,WAAW;GACX,QAAQ;EACV,CAAC;CACH,QAAQ,CAER;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { o as getDb, t as getConfig } from "./get-config-BWhs5HFF.js";
2
- import { r as CONFIG_KEYS } from "./config-DxNI3TlW.js";
3
- import { t as getOrCreateSubscriberId } from "./get-or-create-subscriber-id-HCcgDEPz.js";
2
+ import { r as CONFIG_KEYS } from "./config-BrHR97zt.js";
3
+ import { t as getOrCreateSubscriberId } from "./get-or-create-subscriber-id-wyzaML7Z.js";
4
4
 
5
5
  //#region src/subsystems/notifications/push-client.ts
6
6
  /**
@@ -61,7 +61,7 @@ async function subscribeToPush(clientId, deviceLabel, subscriberId) {
61
61
  let resolvedDeviceLabel = deviceLabel;
62
62
  let resolvedSubscriberId = subscriberId;
63
63
  if (!resolvedClientId || !resolvedDeviceLabel) try {
64
- const initCp = await import("./init-control-plane-C1FRRmjC.js");
64
+ const initCp = await import("./init-control-plane-CEGdzgWX.js");
65
65
  if (!resolvedClientId && typeof initCp.getOrCreateControlPlaneClientId === "function") resolvedClientId = initCp.getOrCreateControlPlaneClientId();
66
66
  if (!resolvedDeviceLabel && typeof initCp.detectDeviceLabel === "function") resolvedDeviceLabel = initCp.detectDeviceLabel();
67
67
  } catch (_) {}
@@ -97,7 +97,7 @@ async function syncExistingPushSubscription(subscriberId) {
97
97
  let resolvedSubscriberId = subscriberId;
98
98
  if (typeof localStorage !== "undefined") resolvedClientId = localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || void 0;
99
99
  try {
100
- const initCp = await import("./init-control-plane-C1FRRmjC.js");
100
+ const initCp = await import("./init-control-plane-CEGdzgWX.js");
101
101
  if (!resolvedClientId && typeof initCp.getOrCreateControlPlaneClientId === "function") resolvedClientId = initCp.getOrCreateControlPlaneClientId();
102
102
  if (typeof initCp.detectDeviceLabel === "function") resolvedDeviceLabel = initCp.detectDeviceLabel();
103
103
  } catch (_) {}
@@ -144,4 +144,4 @@ async function getCurrentSubscription() {
144
144
 
145
145
  //#endregion
146
146
  export { syncExistingPushSubscription as a, subscribeToPush as i, getPushFetchOptions as n, unsubscribeFromPush as o, getPushUrl as r, getCurrentSubscription as t };
147
- //# sourceMappingURL=push-client-Cx5rMs6J.js.map
147
+ //# sourceMappingURL=push-client-CAm6UMvE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"push-client-Cx5rMs6J.js","names":[],"sources":["../../src/subsystems/notifications/push-client.ts"],"sourcesContent":["/**\n * Client-side Web Push subscription management.\n * Runs in the browser — communicates with the server's push routes.\n */\n\nimport { CONFIG_KEYS } from \"../../config/config.js\";\nimport { getDb } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { getOrCreateSubscriberId } from \"../../db/get-or-create-subscriber-id.js\";\n\n/**\n * Resolve a push route URL, optionally using a configured proxy.\n */\nexport async function getPushUrl(path: string): Promise<string> {\n const db = await getDb();\n let proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n\n if (!proxyUrl && typeof localStorage !== \"undefined\") {\n try {\n proxyUrl = localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL) || undefined;\n } catch (_) {}\n }\n\n if (!proxyUrl) {\n return path;\n }\n\n // Ensure path starts with /\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n // Ensure proxyUrl doesn't end with /\n const normalizedProxy = proxyUrl.endsWith(\"/\")\n ? proxyUrl.slice(0, -1)\n : proxyUrl;\n\n return `${normalizedProxy}${normalizedPath}`;\n}\n\nexport function getPushFetchOptions(\n url: string,\n baseOptions: RequestInit = {},\n): RequestInit {\n const opts: any = { ...baseOptions };\n try {\n const locOrigin =\n typeof location !== \"undefined\"\n ? location.origin\n : \"http://127.0.0.1:8888\";\n const u = new URL(url, locOrigin);\n const host = u.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host === \"[::1]\"\n ) {\n opts.targetAddressSpace = \"loopback\";\n } else if (\n /^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.)/.test(host) ||\n !host.includes(\".\") ||\n host.endsWith(\".local\") ||\n host.endsWith(\".lan\") ||\n host.endsWith(\".home\") ||\n host.endsWith(\".internal\")\n ) {\n opts.targetAddressSpace = \"private\";\n }\n } catch (_) {}\n return opts;\n}\n\n/**\n * Convert a URL-safe base64 string to a Uint8Array.\n * Required for PushManager.subscribe() applicationServerKey.\n */\nexport function urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n\n return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)));\n}\n\n/**\n * Fetch the VAPID public key from the server.\n */\nexport async function getVapidPublicKey(): Promise<string> {\n const url = await getPushUrl(\"/push/vapid-public-key\");\n const res = await fetch(url, getPushFetchOptions(url));\n const data = await res.json();\n\n return data.publicKey;\n}\n\n/**\n * Subscribe to push notifications.\n * Requests permission, creates a push subscription, and sends it to the server.\n */\nexport async function subscribeToPush(\n clientId?: string,\n deviceLabel?: string,\n subscriberId?: string,\n): Promise<PushSubscription> {\n const registration = await navigator.serviceWorker.ready;\n const publicKey = await getVapidPublicKey();\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(publicKey) as any,\n });\n\n let resolvedClientId =\n clientId ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined\n : undefined);\n\n let resolvedDeviceLabel = deviceLabel;\n let resolvedSubscriberId = subscriberId;\n\n if (!resolvedClientId || !resolvedDeviceLabel) {\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (\n !resolvedDeviceLabel &&\n typeof initCp.detectDeviceLabel === \"function\"\n ) {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n }\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof subscription.toJSON === \"function\"\n ? subscription.toJSON()\n : JSON.parse(JSON.stringify(subscription));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId ? { subscriberId: resolvedSubscriberId } : {}),\n }),\n }),\n );\n\n return subscription;\n}\n\n/**\n * Re-register an existing push subscription with the server if one exists,\n * ensuring clientId, deviceLabel, and subscriberId are up-to-date.\n */\nexport async function syncExistingPushSubscription(\n subscriberId?: string,\n): Promise<void> {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n try {\n const reg = await navigator.serviceWorker.ready;\n const sub = await reg.pushManager.getSubscription();\n if (!sub) {\n return;\n }\n\n let resolvedClientId: string | undefined;\n let resolvedDeviceLabel: string | undefined;\n let resolvedSubscriberId = subscriberId;\n\n if (typeof localStorage !== \"undefined\") {\n resolvedClientId =\n localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined;\n }\n\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (typeof initCp.detectDeviceLabel === \"function\") {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof sub.toJSON === \"function\"\n ? sub.toJSON()\n : JSON.parse(JSON.stringify(sub));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId\n ? { subscriberId: resolvedSubscriberId }\n : {}),\n }),\n }),\n );\n } catch (_) {\n // Non-fatal if server is unreachable\n }\n}\n\n/**\n * Unsubscribe from push notifications.\n * Removes the push subscription locally and notifies the server.\n */\nexport async function unsubscribeFromPush(): Promise<void> {\n const registration = await navigator.serviceWorker.ready;\n const subscription = await registration.pushManager.getSubscription();\n\n if (!subscription) {\n return;\n }\n\n const { endpoint } = subscription;\n await subscription.unsubscribe();\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint }),\n }),\n );\n}\n\n/**\n * Get the current push subscription (or null if not subscribed).\n */\nexport async function getCurrentSubscription(): Promise<PushSubscription | null> {\n const registration = await navigator.serviceWorker.ready;\n\n return registration.pushManager.getSubscription();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"push-client-CAm6UMvE.js","names":[],"sources":["../../src/subsystems/notifications/push-client.ts"],"sourcesContent":["/**\n * Client-side Web Push subscription management.\n * Runs in the browser — communicates with the server's push routes.\n */\n\nimport { CONFIG_KEYS } from \"../../config/config.js\";\nimport { getDb } from \"../../db/db.js\";\nimport { getConfig } from \"../../db/get-config.js\";\nimport { getOrCreateSubscriberId } from \"../../db/get-or-create-subscriber-id.js\";\n\n/**\n * Resolve a push route URL, optionally using a configured proxy.\n */\nexport async function getPushUrl(path: string): Promise<string> {\n const db = await getDb();\n let proxyUrl = await getConfig(db, CONFIG_KEYS.PUSH_PROXY_URL);\n\n if (!proxyUrl && typeof localStorage !== \"undefined\") {\n try {\n proxyUrl = localStorage.getItem(CONFIG_KEYS.PUSH_PROXY_URL) || undefined;\n } catch (_) {}\n }\n\n if (!proxyUrl) {\n return path;\n }\n\n // Ensure path starts with /\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n // Ensure proxyUrl doesn't end with /\n const normalizedProxy = proxyUrl.endsWith(\"/\")\n ? proxyUrl.slice(0, -1)\n : proxyUrl;\n\n return `${normalizedProxy}${normalizedPath}`;\n}\n\nexport function getPushFetchOptions(\n url: string,\n baseOptions: RequestInit = {},\n): RequestInit {\n const opts: any = { ...baseOptions };\n try {\n const locOrigin =\n typeof location !== \"undefined\"\n ? location.origin\n : \"http://127.0.0.1:8888\";\n const u = new URL(url, locOrigin);\n const host = u.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host === \"[::1]\"\n ) {\n opts.targetAddressSpace = \"loopback\";\n } else if (\n /^(10\\.|172\\.(1[6-9]|2\\d|3[01])\\.|192\\.168\\.)/.test(host) ||\n !host.includes(\".\") ||\n host.endsWith(\".local\") ||\n host.endsWith(\".lan\") ||\n host.endsWith(\".home\") ||\n host.endsWith(\".internal\")\n ) {\n opts.targetAddressSpace = \"private\";\n }\n } catch (_) {}\n return opts;\n}\n\n/**\n * Convert a URL-safe base64 string to a Uint8Array.\n * Required for PushManager.subscribe() applicationServerKey.\n */\nexport function urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n\n return Uint8Array.from([...rawData].map((c) => c.charCodeAt(0)));\n}\n\n/**\n * Fetch the VAPID public key from the server.\n */\nexport async function getVapidPublicKey(): Promise<string> {\n const url = await getPushUrl(\"/push/vapid-public-key\");\n const res = await fetch(url, getPushFetchOptions(url));\n const data = await res.json();\n\n return data.publicKey;\n}\n\n/**\n * Subscribe to push notifications.\n * Requests permission, creates a push subscription, and sends it to the server.\n */\nexport async function subscribeToPush(\n clientId?: string,\n deviceLabel?: string,\n subscriberId?: string,\n): Promise<PushSubscription> {\n const registration = await navigator.serviceWorker.ready;\n const publicKey = await getVapidPublicKey();\n\n const subscription = await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: urlBase64ToUint8Array(publicKey) as any,\n });\n\n let resolvedClientId =\n clientId ||\n (typeof localStorage !== \"undefined\"\n ? localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined\n : undefined);\n\n let resolvedDeviceLabel = deviceLabel;\n let resolvedSubscriberId = subscriberId;\n\n if (!resolvedClientId || !resolvedDeviceLabel) {\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (\n !resolvedDeviceLabel &&\n typeof initCp.detectDeviceLabel === \"function\"\n ) {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n }\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof subscription.toJSON === \"function\"\n ? subscription.toJSON()\n : JSON.parse(JSON.stringify(subscription));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId ? { subscriberId: resolvedSubscriberId } : {}),\n }),\n }),\n );\n\n return subscription;\n}\n\n/**\n * Re-register an existing push subscription with the server if one exists,\n * ensuring clientId, deviceLabel, and subscriberId are up-to-date.\n */\nexport async function syncExistingPushSubscription(\n subscriberId?: string,\n): Promise<void> {\n if (typeof navigator === \"undefined\" || !navigator.serviceWorker) {\n return;\n }\n try {\n const reg = await navigator.serviceWorker.ready;\n const sub = await reg.pushManager.getSubscription();\n if (!sub) {\n return;\n }\n\n let resolvedClientId: string | undefined;\n let resolvedDeviceLabel: string | undefined;\n let resolvedSubscriberId = subscriberId;\n\n if (typeof localStorage !== \"undefined\") {\n resolvedClientId =\n localStorage.getItem(CONFIG_KEYS.CONTROL_PLANE_CLIENT_ID) || undefined;\n }\n\n try {\n const initCp = await import(\"../../core/utils/init-control-plane.js\");\n if (\n !resolvedClientId &&\n typeof initCp.getOrCreateControlPlaneClientId === \"function\"\n ) {\n resolvedClientId = initCp.getOrCreateControlPlaneClientId();\n }\n if (typeof initCp.detectDeviceLabel === \"function\") {\n resolvedDeviceLabel = initCp.detectDeviceLabel();\n }\n } catch (_) {}\n\n if (!resolvedSubscriberId) {\n try {\n const db = await Promise.race([\n getDb(),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 500)),\n ]);\n if (db) {\n resolvedSubscriberId = await getOrCreateSubscriberId(db);\n }\n } catch (_) {}\n }\n\n const subJson =\n typeof sub.toJSON === \"function\"\n ? sub.toJSON()\n : JSON.parse(JSON.stringify(sub));\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ...subJson,\n ...(resolvedClientId ? { clientId: resolvedClientId } : {}),\n ...(resolvedDeviceLabel ? { deviceLabel: resolvedDeviceLabel } : {}),\n ...(resolvedSubscriberId\n ? { subscriberId: resolvedSubscriberId }\n : {}),\n }),\n }),\n );\n } catch (_) {\n // Non-fatal if server is unreachable\n }\n}\n\n/**\n * Unsubscribe from push notifications.\n * Removes the push subscription locally and notifies the server.\n */\nexport async function unsubscribeFromPush(): Promise<void> {\n const registration = await navigator.serviceWorker.ready;\n const subscription = await registration.pushManager.getSubscription();\n\n if (!subscription) {\n return;\n }\n\n const { endpoint } = subscription;\n await subscription.unsubscribe();\n\n const url = await getPushUrl(\"/push/subscribe\");\n await fetch(\n url,\n getPushFetchOptions(url, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ endpoint }),\n }),\n );\n}\n\n/**\n * Get the current push subscription (or null if not subscribed).\n */\nexport async function getCurrentSubscription(): Promise<PushSubscription | null> {\n const registration = await navigator.serviceWorker.ready;\n\n return registration.pushManager.getSubscription();\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as getGroupDir, t as parsePath } from "./parse-path-DPCn-HwI.js";
1
+ import { n as getGroupDir, t as parsePath } from "./parse-path-BOHQP_IQ.js";
2
2
 
3
3
  //#region src/storage/read-group-file-bytes.ts
4
4
  /**
@@ -25,4 +25,4 @@ async function readGroupFileBytes(db, groupId, filePath) {
25
25
 
26
26
  //#endregion
27
27
  export { readGroupFileBytes as t };
28
- //# sourceMappingURL=read-group-file-bytes-CXOG_YyM.js.map
28
+ //# sourceMappingURL=read-group-file-bytes-UQIk1eJG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-group-file-bytes-CXOG_YyM.js","names":[],"sources":["../../src/storage/read-group-file-bytes.ts"],"sourcesContent":["import { getGroupDir } from \"./get-group-dir.js\";\nimport { parsePath } from \"./parse-path.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Read raw bytes from a file in a group's workspace.\n */\nexport async function readGroupFileBytes(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<Uint8Array> {\n const groupDir = await getGroupDir(db, groupId);\n const { dirs, filename } = parsePath(filePath);\n\n let dir = groupDir;\n for (const seg of dirs) {\n dir = await dir.getDirectoryHandle(seg);\n }\n\n const fileHandle = await dir.getFileHandle(filename);\n\n try {\n const syncHandle = await (fileHandle as any).createSyncAccessHandle();\n const size = syncHandle.getSize();\n const buf = new Uint8Array(size);\n\n syncHandle.read(buf, { at: 0 });\n syncHandle.close();\n\n return buf;\n } catch {\n const file = await fileHandle.getFile();\n const arrayBuffer = await file.arrayBuffer();\n\n return new Uint8Array(arrayBuffer);\n }\n}\n"],"mappings":";;;;;;AAOA,eAAsB,mBACpB,IACA,SACA,UACqB;CACrB,MAAM,WAAW,MAAM,YAAY,IAAI,OAAO;CAC9C,MAAM,EAAE,MAAM,aAAa,UAAU,QAAQ;CAE7C,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,MAChB,MAAM,MAAM,IAAI,mBAAmB,GAAG;CAGxC,MAAM,aAAa,MAAM,IAAI,cAAc,QAAQ;CAEnD,IAAI;EACF,MAAM,aAAa,MAAO,WAAmB,uBAAuB;EACpE,MAAM,OAAO,WAAW,QAAQ;EAChC,MAAM,MAAM,IAAI,WAAW,IAAI;EAE/B,WAAW,KAAK,KAAK,EAAE,IAAI,EAAE,CAAC;EAC9B,WAAW,MAAM;EAEjB,OAAO;CACT,QAAQ;EAEN,MAAM,cAAc,OAAM,MADP,WAAW,QAAQ,EACR,CAAC,YAAY;EAE3C,OAAO,IAAI,WAAW,WAAW;CACnC;AACF"}
1
+ {"version":3,"file":"read-group-file-bytes-UQIk1eJG.js","names":[],"sources":["../../src/storage/read-group-file-bytes.ts"],"sourcesContent":["import { getGroupDir } from \"./get-group-dir.js\";\nimport { parsePath } from \"./parse-path.js\";\nimport type { ShadowClawDatabase } from \"../db/types.js\";\n\n/**\n * Read raw bytes from a file in a group's workspace.\n */\nexport async function readGroupFileBytes(\n db: ShadowClawDatabase,\n groupId: string,\n filePath: string,\n): Promise<Uint8Array> {\n const groupDir = await getGroupDir(db, groupId);\n const { dirs, filename } = parsePath(filePath);\n\n let dir = groupDir;\n for (const seg of dirs) {\n dir = await dir.getDirectoryHandle(seg);\n }\n\n const fileHandle = await dir.getFileHandle(filename);\n\n try {\n const syncHandle = await (fileHandle as any).createSyncAccessHandle();\n const size = syncHandle.getSize();\n const buf = new Uint8Array(size);\n\n syncHandle.read(buf, { at: 0 });\n syncHandle.close();\n\n return buf;\n } catch {\n const file = await fileHandle.getFile();\n const arrayBuffer = await file.arrayBuffer();\n\n return new Uint8Array(arrayBuffer);\n }\n}\n"],"mappings":";;;;;;AAOA,eAAsB,mBACpB,IACA,SACA,UACqB;CACrB,MAAM,WAAW,MAAM,YAAY,IAAI,OAAO;CAC9C,MAAM,EAAE,MAAM,aAAa,UAAU,QAAQ;CAE7C,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,MAChB,MAAM,MAAM,IAAI,mBAAmB,GAAG;CAGxC,MAAM,aAAa,MAAM,IAAI,cAAc,QAAQ;CAEnD,IAAI;EACF,MAAM,aAAa,MAAO,WAAmB,uBAAuB;EACpE,MAAM,OAAO,WAAW,QAAQ;EAChC,MAAM,MAAM,IAAI,WAAW,IAAI;EAE/B,WAAW,KAAK,KAAK,EAAE,IAAI,EAAE,CAAC;EAC9B,WAAW,MAAM;EAEjB,OAAO;CACT,QAAQ;EAEN,MAAM,cAAc,OAAM,MADP,WAAW,QAAQ,EACR,CAAC,YAAY;EAE3C,OAAO,IAAI,WAAW,WAAW;CACnC;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { t as getConfig } from "./get-config-BWhs5HFF.js";
2
2
  import { t as setConfig } from "./set-config-CUadvYZ1.js";
3
- import { _ as createGroup, v as getGroupMetadata } from "./orchestrator-i_QJ-o22.js";
3
+ import { _ as createGroup, v as getGroupMetadata } from "./orchestrator-cRBe3lhq.js";
4
4
 
5
5
  //#region src/db/rooms.ts
6
6
  /**
@@ -66,4 +66,4 @@ async function deleteRoom(db, roomId) {
66
66
 
67
67
  //#endregion
68
68
  export { roomIdFromGroupId as a, roomGroupId as i, deleteRoom as n, upsertRoom as o, getRoomMetadata as r, ROOM_PREFIX as t };
69
- //# sourceMappingURL=rooms-CwlkYLDU.js.map
69
+ //# sourceMappingURL=rooms-Dzphx3rK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rooms-CwlkYLDU.js","names":[],"sources":["../../src/db/rooms.ts"],"sourcesContent":["/**\n * ShadowClaw — Room (multi-party conversation) metadata management\n *\n * A room is layered on top of a {@link GroupMeta} whose groupId is\n * `room:<roomId>` (so existing message storage, OPFS workspace, unread state,\n * and the conversation list work unchanged). This module persists the room\n * roster / host separately under a dedicated config key.\n */\n\nimport { getConfig } from \"./get-config.js\";\nimport { setConfig } from \"./set-config.js\";\nimport { createGroup, getGroupMetadata } from \"./groups.js\";\nimport { ulid } from \"../utils/ulid.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\nimport type { RoomMember, RoomMeta } from \"../subsystems/channels/types.js\";\n\nconst CONFIG_KEY = \"room_metadata\";\n\n/** The groupId prefix used for room conversations. */\nexport const ROOM_PREFIX = \"room:\";\n\n/** Build the conversation groupId for a bare room id. */\nexport function roomGroupId(roomId: string): string {\n return `${ROOM_PREFIX}${roomId}`;\n}\n\n/** Extract the bare room id from a `room:<id>` groupId. */\nexport function roomIdFromGroupId(groupId: string): string {\n return groupId.startsWith(ROOM_PREFIX)\n ? groupId.slice(ROOM_PREFIX.length)\n : groupId;\n}\n\n/** Get all room metadata from config. */\nexport async function getRoomMetadata(\n db: ShadowClawDatabase,\n): Promise<RoomMeta[]> {\n const raw = await getConfig(db, CONFIG_KEY);\n if (!raw) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(raw);\n\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/** Save all room metadata to config. */\nexport async function saveRoomMetadata(\n db: ShadowClawDatabase,\n metadata: RoomMeta[],\n): Promise<void> {\n await setConfig(db, CONFIG_KEY, JSON.stringify(metadata));\n}\n\n/** Get a single room by its bare room id. */\nexport async function getRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n\n return rooms.find((r) => r.roomId === roomId) ?? null;\n}\n\n/**\n * Persist (insert or replace) a single room record and ensure a matching\n * conversation group exists.\n */\nexport async function upsertRoom(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n const index = rooms.findIndex((r) => r.roomId === room.roomId);\n if (index >= 0) {\n rooms[index] = room;\n } else {\n rooms.push(room);\n }\n\n await saveRoomMetadata(db, rooms);\n await ensureRoomGroup(db, room);\n}\n\n/**\n * Ensure a `room:<roomId>` GroupMeta exists for the given room so the\n * conversation, message history and workspace are available.\n */\nasync function ensureRoomGroup(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const groups = await getGroupMetadata(db);\n const groupId = roomGroupId(room.roomId);\n if (groups.some((g) => g.groupId === groupId)) {\n return;\n }\n\n await createGroup(db, room.name, ROOM_PREFIX, room.roomId);\n}\n\n/**\n * Create a new room (as host) and persist it along with its conversation group.\n */\nexport async function createRoom(\n db: ShadowClawDatabase,\n name: string,\n hostPeerId: string,\n hostMember: RoomMember,\n): Promise<RoomMeta> {\n const room: RoomMeta = {\n roomId: ulid(),\n name,\n hostPeerId,\n members: [hostMember],\n createdAt: Date.now(),\n };\n\n await upsertRoom(db, room);\n\n return room;\n}\n\n/** Add or update a member in a room's roster. Returns the updated room. */\nexport async function addRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n member: RoomMember,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n const index = room.members.findIndex((m) => m.peerId === member.peerId);\n if (index >= 0) {\n room.members[index] = member;\n } else {\n room.members.push(member);\n }\n\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Remove a member from a room's roster. Returns the updated room. */\nexport async function removeRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n peerId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n room.members = room.members.filter((m) => m.peerId !== peerId);\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Delete a room record (does not delete its conversation group/messages). */\nexport async function deleteRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n await saveRoomMetadata(\n db,\n rooms.filter((r) => r.roomId !== roomId),\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,aAAa;;AAGnB,MAAa,cAAc;;AAG3B,SAAgB,YAAY,QAAwB;CAClD,OAAO,GAAG,cAAc;AAC1B;;AAGA,SAAgB,kBAAkB,SAAyB;CACzD,OAAO,QAAQ,kBAAsB,IACjC,QAAQ,MAAM,CAAkB,IAChC;AACN;;AAGA,eAAsB,gBACpB,IACqB;CACrB,MAAM,MAAM,MAAM,UAAU,IAAI,UAAU;CAC1C,IAAI,CAAC,KACH,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAE7B,OAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;CAC3C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;AAGA,eAAsB,iBACpB,IACA,UACe;CACf,MAAM,UAAU,IAAI,YAAY,KAAK,UAAU,QAAQ,CAAC;AAC1D;;;;;AAgBA,eAAsB,WACpB,IACA,MACe;CACf,MAAM,QAAQ,MAAM,gBAAgB,EAAE;CACtC,MAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,WAAW,KAAK,MAAM;CAC7D,IAAI,SAAS,GACX,MAAM,SAAS;MAEf,MAAM,KAAK,IAAI;CAGjB,MAAM,iBAAiB,IAAI,KAAK;CAChC,MAAM,gBAAgB,IAAI,IAAI;AAChC;;;;;AAMA,eAAe,gBACb,IACA,MACe;CACf,MAAM,SAAS,MAAM,iBAAiB,EAAE;CACxC,MAAM,UAAU,YAAY,KAAK,MAAM;CACvC,IAAI,OAAO,MAAM,MAAM,EAAE,YAAY,OAAO,GAC1C;CAGF,MAAM,YAAY,IAAI,KAAK,MAAM,aAAa,KAAK,MAAM;AAC3D;;AAmEA,eAAsB,WACpB,IACA,QACe;CAEf,MAAM,iBACJ,KACA,MAHkB,gBAAgB,EAAE,EAG/B,CAAC,QAAQ,MAAM,EAAE,WAAW,MAAM,CACzC;AACF"}
1
+ {"version":3,"file":"rooms-Dzphx3rK.js","names":[],"sources":["../../src/db/rooms.ts"],"sourcesContent":["/**\n * ShadowClaw — Room (multi-party conversation) metadata management\n *\n * A room is layered on top of a {@link GroupMeta} whose groupId is\n * `room:<roomId>` (so existing message storage, OPFS workspace, unread state,\n * and the conversation list work unchanged). This module persists the room\n * roster / host separately under a dedicated config key.\n */\n\nimport { getConfig } from \"./get-config.js\";\nimport { setConfig } from \"./set-config.js\";\nimport { createGroup, getGroupMetadata } from \"./groups.js\";\nimport { ulid } from \"../utils/ulid.js\";\nimport type { ShadowClawDatabase } from \"./types.js\";\nimport type { RoomMember, RoomMeta } from \"../subsystems/channels/types.js\";\n\nconst CONFIG_KEY = \"room_metadata\";\n\n/** The groupId prefix used for room conversations. */\nexport const ROOM_PREFIX = \"room:\";\n\n/** Build the conversation groupId for a bare room id. */\nexport function roomGroupId(roomId: string): string {\n return `${ROOM_PREFIX}${roomId}`;\n}\n\n/** Extract the bare room id from a `room:<id>` groupId. */\nexport function roomIdFromGroupId(groupId: string): string {\n return groupId.startsWith(ROOM_PREFIX)\n ? groupId.slice(ROOM_PREFIX.length)\n : groupId;\n}\n\n/** Get all room metadata from config. */\nexport async function getRoomMetadata(\n db: ShadowClawDatabase,\n): Promise<RoomMeta[]> {\n const raw = await getConfig(db, CONFIG_KEY);\n if (!raw) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(raw);\n\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/** Save all room metadata to config. */\nexport async function saveRoomMetadata(\n db: ShadowClawDatabase,\n metadata: RoomMeta[],\n): Promise<void> {\n await setConfig(db, CONFIG_KEY, JSON.stringify(metadata));\n}\n\n/** Get a single room by its bare room id. */\nexport async function getRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n\n return rooms.find((r) => r.roomId === roomId) ?? null;\n}\n\n/**\n * Persist (insert or replace) a single room record and ensure a matching\n * conversation group exists.\n */\nexport async function upsertRoom(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n const index = rooms.findIndex((r) => r.roomId === room.roomId);\n if (index >= 0) {\n rooms[index] = room;\n } else {\n rooms.push(room);\n }\n\n await saveRoomMetadata(db, rooms);\n await ensureRoomGroup(db, room);\n}\n\n/**\n * Ensure a `room:<roomId>` GroupMeta exists for the given room so the\n * conversation, message history and workspace are available.\n */\nasync function ensureRoomGroup(\n db: ShadowClawDatabase,\n room: RoomMeta,\n): Promise<void> {\n const groups = await getGroupMetadata(db);\n const groupId = roomGroupId(room.roomId);\n if (groups.some((g) => g.groupId === groupId)) {\n return;\n }\n\n await createGroup(db, room.name, ROOM_PREFIX, room.roomId);\n}\n\n/**\n * Create a new room (as host) and persist it along with its conversation group.\n */\nexport async function createRoom(\n db: ShadowClawDatabase,\n name: string,\n hostPeerId: string,\n hostMember: RoomMember,\n): Promise<RoomMeta> {\n const room: RoomMeta = {\n roomId: ulid(),\n name,\n hostPeerId,\n members: [hostMember],\n createdAt: Date.now(),\n };\n\n await upsertRoom(db, room);\n\n return room;\n}\n\n/** Add or update a member in a room's roster. Returns the updated room. */\nexport async function addRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n member: RoomMember,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n const index = room.members.findIndex((m) => m.peerId === member.peerId);\n if (index >= 0) {\n room.members[index] = member;\n } else {\n room.members.push(member);\n }\n\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Remove a member from a room's roster. Returns the updated room. */\nexport async function removeRoomMember(\n db: ShadowClawDatabase,\n roomId: string,\n peerId: string,\n): Promise<RoomMeta | null> {\n const rooms = await getRoomMetadata(db);\n const room = rooms.find((r) => r.roomId === roomId);\n if (!room) {\n return null;\n }\n\n room.members = room.members.filter((m) => m.peerId !== peerId);\n await saveRoomMetadata(db, rooms);\n\n return room;\n}\n\n/** Delete a room record (does not delete its conversation group/messages). */\nexport async function deleteRoom(\n db: ShadowClawDatabase,\n roomId: string,\n): Promise<void> {\n const rooms = await getRoomMetadata(db);\n await saveRoomMetadata(\n db,\n rooms.filter((r) => r.roomId !== roomId),\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,aAAa;;AAGnB,MAAa,cAAc;;AAG3B,SAAgB,YAAY,QAAwB;CAClD,OAAO,GAAG,cAAc;AAC1B;;AAGA,SAAgB,kBAAkB,SAAyB;CACzD,OAAO,QAAQ,kBAAsB,IACjC,QAAQ,MAAM,CAAkB,IAChC;AACN;;AAGA,eAAsB,gBACpB,IACqB;CACrB,MAAM,MAAM,MAAM,UAAU,IAAI,UAAU;CAC1C,IAAI,CAAC,KACH,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAE7B,OAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;CAC3C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;AAGA,eAAsB,iBACpB,IACA,UACe;CACf,MAAM,UAAU,IAAI,YAAY,KAAK,UAAU,QAAQ,CAAC;AAC1D;;;;;AAgBA,eAAsB,WACpB,IACA,MACe;CACf,MAAM,QAAQ,MAAM,gBAAgB,EAAE;CACtC,MAAM,QAAQ,MAAM,WAAW,MAAM,EAAE,WAAW,KAAK,MAAM;CAC7D,IAAI,SAAS,GACX,MAAM,SAAS;MAEf,MAAM,KAAK,IAAI;CAGjB,MAAM,iBAAiB,IAAI,KAAK;CAChC,MAAM,gBAAgB,IAAI,IAAI;AAChC;;;;;AAMA,eAAe,gBACb,IACA,MACe;CACf,MAAM,SAAS,MAAM,iBAAiB,EAAE;CACxC,MAAM,UAAU,YAAY,KAAK,MAAM;CACvC,IAAI,OAAO,MAAM,MAAM,EAAE,YAAY,OAAO,GAC1C;CAGF,MAAM,YAAY,IAAI,KAAK,MAAM,aAAa,KAAK,MAAM;AAC3D;;AAmEA,eAAsB,WACpB,IACA,QACe;CAEf,MAAM,iBACJ,KACA,MAHkB,gBAAgB,EAAE,EAG/B,CAAC,QAAQ,MAAM,EAAE,WAAW,MAAM,CACzC;AACF"}