@saluzi/saluzi-edu 0.4.7 → 0.4.9

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 (230) hide show
  1. package/dist/cli.js +59 -68
  2. package/dist/guide/guide-data.json +1 -1
  3. package/dist/rcs-web/assets/{AdminPanel-CpzAO2vZ.js → AdminPanel-CAK-wqCu.js} +1 -1
  4. package/dist/rcs-web/assets/{ArtifactView-CEyKbOJh.js → ArtifactView-DJxpXvlH.js} +1 -1
  5. package/{packages/remote-control-server/web/dist/assets/ArtifactsGallery-B_JcCYh1.js → dist/rcs-web/assets/ArtifactsGallery-CykyoUxk.js} +1 -1
  6. package/{packages/remote-control-server/web/dist/assets/Claim-CGxjGaui.js → dist/rcs-web/assets/Claim-DZQ8sfWt.js} +1 -1
  7. package/dist/rcs-web/assets/{Dashboard-DCq-h_y9.js → Dashboard-Cm9ZAh-6.js} +1 -1
  8. package/dist/rcs-web/assets/{Join-BM43XjA0.js → Join-D1X0Ji0b.js} +1 -1
  9. package/dist/rcs-web/assets/{Login-CPx4Dc28.js → Login-lDaHrIa-.js} +1 -1
  10. package/dist/rcs-web/assets/{Register-BV3xfUvd.js → Register-12ki3lPq.js} +1 -1
  11. package/dist/rcs-web/assets/{SessionDetail-DgMDo7Ge.js → SessionDetail-BZjIjZKu.js} +23 -23
  12. package/dist/rcs-web/assets/{SessionVisibilityBadge-CvqFRTea.js → SessionVisibilityBadge-BkZImPBJ.js} +1 -1
  13. package/dist/rcs-web/assets/{Setup-GfWdRpvh.js → Setup-Cpyfr8Pi.js} +1 -1
  14. package/dist/rcs-web/assets/{ShareLanding-BuEXTqqz.js → ShareLanding-Dh3_QdhD.js} +1 -1
  15. package/dist/rcs-web/assets/{TeamCreate-DalKoyLy.js → TeamCreate-CZC2EjYw.js} +1 -1
  16. package/dist/rcs-web/assets/{TeamDetail-DevkNiHQ.js → TeamDetail-umrDhcwG.js} +1 -1
  17. package/dist/rcs-web/assets/{TeamList-B1pHxRaK.js → TeamList-CI_ppYJz.js} +1 -1
  18. package/dist/rcs-web/assets/{TeamSettings-DWnEJMTx.js → TeamSettings-D_y3NFLr.js} +1 -1
  19. package/dist/rcs-web/assets/{UserSearchInput-DgktGnh2.js → UserSearchInput-BJTMnFdQ.js} +1 -1
  20. package/dist/rcs-web/assets/{UserSettings-DPhvsn9k.js → UserSettings-m2SsR0jt.js} +1 -1
  21. package/dist/rcs-web/assets/{arc-C7foUDWz.js → arc-B-w-om5W.js} +1 -1
  22. package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-BzsYecpv.js → architectureDiagram-3BPJPVTR-A0JqD49y.js} +1 -1
  23. package/{packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-D4BSEcZT.js → dist/rcs-web/assets/blockDiagram-GPEHLZMM-CRmWH6Kh.js} +1 -1
  24. package/{packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-CIap7aYJ.js → dist/rcs-web/assets/c4Diagram-AAUBKEIU-Dil5npJC.js} +1 -1
  25. package/dist/rcs-web/assets/channel-BAxtMvz9.js +1 -0
  26. package/dist/rcs-web/assets/{chunk-2J33WTMH-s9V4oCUf.js → chunk-2J33WTMH-B0U3olYO.js} +1 -1
  27. package/dist/rcs-web/assets/{chunk-4BX2VUAB-CJrYwRaR.js → chunk-4BX2VUAB-D8eZOxCq.js} +1 -1
  28. package/dist/rcs-web/assets/{chunk-55IACEB6-D8swZDnP.js → chunk-55IACEB6-BCg1yqKV.js} +1 -1
  29. package/{packages/remote-control-server/web/dist/assets/chunk-727SXJPM-vJ6LjIbB.js → dist/rcs-web/assets/chunk-727SXJPM-C9GSmRyu.js} +1 -1
  30. package/{packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-COrMlHZr.js → dist/rcs-web/assets/chunk-AQP2D5EJ-CDNB1DxJ.js} +1 -1
  31. package/dist/rcs-web/assets/{chunk-FMBD7UC4-0lUT-961.js → chunk-FMBD7UC4-CUyVgVhv.js} +1 -1
  32. package/dist/rcs-web/assets/{chunk-ND2GUHAM-BWqVDbg4.js → chunk-ND2GUHAM-DWUadZ9h.js} +1 -1
  33. package/dist/rcs-web/assets/{chunk-QZHKN3VN-CfeMmsaw.js → chunk-QZHKN3VN-De-swXbY.js} +1 -1
  34. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DAE_PUq2.js +1 -0
  35. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DAE_PUq2.js +1 -0
  36. package/dist/rcs-web/assets/{code-block-IT6T5CEO-FipRU7Gt.js → code-block-IT6T5CEO-DHPrRtQH.js} +1 -1
  37. package/dist/rcs-web/assets/{copy-RtDWH7m7.js → copy-CFPy3H8V.js} +1 -1
  38. package/{packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-wlwIwiSf.js → dist/rcs-web/assets/cose-bilkent-S5V4N54A-CZjBoqHS.js} +1 -1
  39. package/dist/rcs-web/assets/{dagre-BM42HDAG-FlvB-WBQ.js → dagre-BM42HDAG-Cf5v7qFZ.js} +1 -1
  40. package/dist/rcs-web/assets/{diagram-2AECGRRQ-Dd5G25-Q.js → diagram-2AECGRRQ-C7UJVkwm.js} +1 -1
  41. package/dist/rcs-web/assets/{diagram-5GNKFQAL-CnS79Wiq.js → diagram-5GNKFQAL-DyOsGtm_.js} +1 -1
  42. package/dist/rcs-web/assets/{diagram-KO2AKTUF-oeffrVzV.js → diagram-KO2AKTUF-rj-dLm4C.js} +1 -1
  43. package/dist/rcs-web/assets/{diagram-LMA3HP47-Dc4rRllI.js → diagram-LMA3HP47-5IBISrVO.js} +1 -1
  44. package/dist/rcs-web/assets/{diagram-OG6HWLK6-QYKwztsm.js → diagram-OG6HWLK6-CvKsIOGI.js} +1 -1
  45. package/dist/rcs-web/assets/{dialog-C6bSop75.js → dialog-D3djNDCB.js} +1 -1
  46. package/{packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-CFoDAbeH.js → dist/rcs-web/assets/erDiagram-TEJ5UH35-DN3O1WDD.js} +1 -1
  47. package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-zOHsjkHO.js → flowDiagram-I6XJVG4X-CXmRfzEy.js} +1 -1
  48. package/{packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-DmdYR8vQ.js → dist/rcs-web/assets/ganttDiagram-6RSMTGT7-6uA2-PAt.js} +1 -1
  49. package/{packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-ChNq0nxK.js → dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-DWYRvHtj.js} +1 -1
  50. package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-CTOfXwsH.js → infoDiagram-5YYISTIA-CJt4bepj.js} +1 -1
  51. package/dist/rcs-web/assets/{ishikawaDiagram-YF4QCWOH-AbFaqfWq.js → ishikawaDiagram-YF4QCWOH-DYHvIeSs.js} +1 -1
  52. package/dist/rcs-web/assets/{journeyDiagram-JHISSGLW-BZ5YDbY5.js → journeyDiagram-JHISSGLW-DWQeWDV-.js} +1 -1
  53. package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-2ujiDLTJ.js → kanban-definition-UN3LZRKU-D1vYCpGq.js} +1 -1
  54. package/dist/rcs-web/assets/{linear-hvc2NcTZ.js → linear-DEn8Cs7O.js} +1 -1
  55. package/dist/rcs-web/assets/{main-2KqxLOVo.js → main-COET8kmB.js} +3 -3
  56. package/{packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-CjE066pc.js → dist/rcs-web/assets/mermaid-VLURNSYL-DJIytlGH.js} +4 -4
  57. package/dist/rcs-web/assets/{mermaid.core-D0z5iBed.js → mermaid.core-DVQA7rXK.js} +5 -5
  58. package/{packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-DN_a_x4Q.js → dist/rcs-web/assets/mindmap-definition-RKZ34NQL-Dhv_wo7x.js} +1 -1
  59. package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-EaZYytph.js → pieDiagram-4H26LBE5-C86veflr.js} +1 -1
  60. package/dist/rcs-web/assets/{quadrantDiagram-W4KKPZXB-BbYaZQ_j.js → quadrantDiagram-W4KKPZXB-DJmcygzl.js} +1 -1
  61. package/dist/rcs-web/assets/{refresh-cw-2QNtciSF.js → refresh-cw-BRNwaL3w.js} +1 -1
  62. package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-sQpG_uMR.js → requirementDiagram-4Y6WPE33-PDkq_ITC.js} +1 -1
  63. package/dist/rcs-web/assets/{sankeyDiagram-5OEKKPKP-Dk-ywMbO.js → sankeyDiagram-5OEKKPKP-DvCuhECf.js} +1 -1
  64. package/dist/rcs-web/assets/{sequenceDiagram-3UESZ5HK-B8kXKWV0.js → sequenceDiagram-3UESZ5HK-Co2LWujo.js} +1 -1
  65. package/dist/rcs-web/assets/{stateDiagram-AJRCARHV-BIjc-tAY.js → stateDiagram-AJRCARHV-CDTXzmhr.js} +1 -1
  66. package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-BjJyk52d.js → stateDiagram-v2-BHNVJYJU-Sdqiqtes.js} +1 -1
  67. package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-9Myr5rlZ.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-Cudtpim6.js} +1 -1
  68. package/dist/rcs-web/assets/{vennDiagram-CIIHVFJN-B_0p3XFw.js → vennDiagram-CIIHVFJN-B_84pCPM.js} +1 -1
  69. package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-JKVEgrM5.js → wardleyDiagram-YWT4CUSO-B_tneRWc.js} +1 -1
  70. package/dist/rcs-web/assets/{xychartDiagram-2RQKCTM6-DUPPleBK.js → xychartDiagram-2RQKCTM6-CNdStpy2.js} +1 -1
  71. package/dist/rcs-web/index.html +1 -1
  72. package/dist/vendor/archify/LICENSE +22 -0
  73. package/dist/vendor/archify/SKILL.md +137 -0
  74. package/dist/vendor/archify/THIRD_PARTY_NOTICES.md +69 -0
  75. package/dist/vendor/archify/assets/JetBrainsMono-OFL.txt +93 -0
  76. package/dist/vendor/archify/assets/template.html +14934 -0
  77. package/dist/vendor/archify/bin/archify.mjs +2687 -0
  78. package/dist/vendor/archify/bin/open-artifact.mjs +95 -0
  79. package/dist/vendor/archify/bin/preview.mjs +764 -0
  80. package/dist/vendor/archify/bin/visual-check.mjs +1012 -0
  81. package/dist/vendor/archify/brand-marks/README.md +31 -0
  82. package/dist/vendor/archify/brand-marks/catalog.json +131 -0
  83. package/dist/vendor/archify/delta/architecture-delta.mjs +1221 -0
  84. package/dist/vendor/archify/examples/agent-run.lifecycle.json +60 -0
  85. package/dist/vendor/archify/examples/agent-tool-call.workflow.json +94 -0
  86. package/dist/vendor/archify/examples/async-job-roundtrip.sequence.json +61 -0
  87. package/dist/vendor/archify/examples/brand-aware-delivery.architecture.json +47 -0
  88. package/dist/vendor/archify/examples/cache-miss-request.sequence.json +82 -0
  89. package/dist/vendor/archify/examples/checkout-platform.base.architecture.json +31 -0
  90. package/dist/vendor/archify/examples/checkout-platform.head.architecture.json +31 -0
  91. package/dist/vendor/archify/examples/dataflow-product-analytics.html +15045 -0
  92. package/dist/vendor/archify/examples/deployment-release.lifecycle.json +49 -0
  93. package/dist/vendor/archify/examples/event-stream.dataflow.json +57 -0
  94. package/dist/vendor/archify/examples/incident-response.workflow.json +64 -0
  95. package/dist/vendor/archify/examples/lifecycle-agent-run.html +14980 -0
  96. package/dist/vendor/archify/examples/product-analytics.dataflow.json +76 -0
  97. package/dist/vendor/archify/examples/production-deployment.architecture.json +71 -0
  98. package/dist/vendor/archify/examples/release-delivery.workflow.json +62 -0
  99. package/dist/vendor/archify/examples/sequence-cache-miss-request.html +15060 -0
  100. package/dist/vendor/archify/examples/web-app-rendered.html +15009 -0
  101. package/dist/vendor/archify/examples/web-app.architecture.json +46 -0
  102. package/dist/vendor/archify/examples/workflow-agent-tool-call-rendered.html +15051 -0
  103. package/dist/vendor/archify/migrations/workflow-v2.mjs +279 -0
  104. package/dist/vendor/archify/package.json +17 -0
  105. package/dist/vendor/archify/recipes/scenarios.mjs +391 -0
  106. package/dist/vendor/archify/references/authoring-contract.md +243 -0
  107. package/dist/vendor/archify/references/brand-marks.md +65 -0
  108. package/dist/vendor/archify/references/delivery-contract.md +120 -0
  109. package/dist/vendor/archify/references/viewer-runtime.md +45 -0
  110. package/dist/vendor/archify/renderers/architecture/grid.mjs +62 -0
  111. package/dist/vendor/archify/renderers/architecture/render-architecture.mjs +1078 -0
  112. package/dist/vendor/archify/renderers/dataflow/README.md +104 -0
  113. package/dist/vendor/archify/renderers/dataflow/render-dataflow.mjs +483 -0
  114. package/dist/vendor/archify/renderers/lifecycle/README.md +115 -0
  115. package/dist/vendor/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
  116. package/dist/vendor/archify/renderers/sequence/README.md +114 -0
  117. package/dist/vendor/archify/renderers/sequence/render-sequence.mjs +464 -0
  118. package/dist/vendor/archify/renderers/shared/brand-marks.mjs +563 -0
  119. package/dist/vendor/archify/renderers/shared/cli.mjs +218 -0
  120. package/dist/vendor/archify/renderers/shared/desktop-readability.mjs +26 -0
  121. package/dist/vendor/archify/renderers/shared/diagnostics.mjs +127 -0
  122. package/dist/vendor/archify/renderers/shared/engineering-profiles.mjs +157 -0
  123. package/dist/vendor/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
  124. package/dist/vendor/archify/renderers/shared/generated-validators.mjs +13 -0
  125. package/dist/vendor/archify/renderers/shared/geometry.mjs +1423 -0
  126. package/dist/vendor/archify/renderers/shared/i18n.mjs +595 -0
  127. package/dist/vendor/archify/renderers/shared/layout-report.mjs +40 -0
  128. package/dist/vendor/archify/renderers/shared/legend.mjs +217 -0
  129. package/dist/vendor/archify/renderers/shared/output-path.mjs +340 -0
  130. package/dist/vendor/archify/renderers/shared/repository-evidence.mjs +238 -0
  131. package/dist/vendor/archify/renderers/shared/repository-location.mjs +58 -0
  132. package/dist/vendor/archify/renderers/shared/text-fit.mjs +49 -0
  133. package/dist/vendor/archify/renderers/shared/utils.mjs +232 -0
  134. package/dist/vendor/archify/renderers/shared/validator.mjs +86 -0
  135. package/dist/vendor/archify/renderers/workflow/README.md +223 -0
  136. package/dist/vendor/archify/renderers/workflow/render-workflow.mjs +35 -0
  137. package/dist/vendor/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
  138. package/dist/vendor/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
  139. package/dist/vendor/archify/schemas/README.md +211 -0
  140. package/dist/vendor/archify/schemas/architecture.schema.json +178 -0
  141. package/dist/vendor/archify/schemas/common.schema.json +115 -0
  142. package/dist/vendor/archify/schemas/dataflow.schema.json +243 -0
  143. package/dist/vendor/archify/schemas/lifecycle.schema.json +266 -0
  144. package/dist/vendor/archify/schemas/sequence.schema.json +223 -0
  145. package/dist/vendor/archify/schemas/workflow.schema.json +428 -0
  146. package/dist/vendor/archify/scripts/check-render-output.mjs +836 -0
  147. package/dist/vendor/archify/scripts/check-update.mjs +1667 -0
  148. package/dist/vendor/archify/scripts/render-examples.mjs +26 -0
  149. package/dist/vendor/archify/scripts/update-contract.mjs +182 -0
  150. package/dist/vendor/archify/skill-release.json +10 -0
  151. package/package.json +1 -1
  152. package/packages/remote-control-server/src/__tests__/stuck-turn-watchdog.test.ts +43 -0
  153. package/packages/remote-control-server/src/__tests__/ws-handler.test.ts +169 -0
  154. package/packages/remote-control-server/src/services/transport.ts +5 -1
  155. package/packages/remote-control-server/src/transport/ws-handler.ts +38 -3
  156. package/packages/remote-control-server/web/dist/assets/{AdminPanel-CpzAO2vZ.js → AdminPanel-CAK-wqCu.js} +1 -1
  157. package/packages/remote-control-server/web/dist/assets/{ArtifactView-CEyKbOJh.js → ArtifactView-DJxpXvlH.js} +1 -1
  158. package/{dist/rcs-web/assets/ArtifactsGallery-B_JcCYh1.js → packages/remote-control-server/web/dist/assets/ArtifactsGallery-CykyoUxk.js} +1 -1
  159. package/{dist/rcs-web/assets/Claim-CGxjGaui.js → packages/remote-control-server/web/dist/assets/Claim-DZQ8sfWt.js} +1 -1
  160. package/packages/remote-control-server/web/dist/assets/{Dashboard-DCq-h_y9.js → Dashboard-Cm9ZAh-6.js} +1 -1
  161. package/packages/remote-control-server/web/dist/assets/{Join-BM43XjA0.js → Join-D1X0Ji0b.js} +1 -1
  162. package/packages/remote-control-server/web/dist/assets/{Login-CPx4Dc28.js → Login-lDaHrIa-.js} +1 -1
  163. package/packages/remote-control-server/web/dist/assets/{Register-BV3xfUvd.js → Register-12ki3lPq.js} +1 -1
  164. package/packages/remote-control-server/web/dist/assets/{SessionDetail-DgMDo7Ge.js → SessionDetail-BZjIjZKu.js} +23 -23
  165. package/packages/remote-control-server/web/dist/assets/{SessionVisibilityBadge-CvqFRTea.js → SessionVisibilityBadge-BkZImPBJ.js} +1 -1
  166. package/packages/remote-control-server/web/dist/assets/{Setup-GfWdRpvh.js → Setup-Cpyfr8Pi.js} +1 -1
  167. package/packages/remote-control-server/web/dist/assets/{ShareLanding-BuEXTqqz.js → ShareLanding-Dh3_QdhD.js} +1 -1
  168. package/packages/remote-control-server/web/dist/assets/{TeamCreate-DalKoyLy.js → TeamCreate-CZC2EjYw.js} +1 -1
  169. package/packages/remote-control-server/web/dist/assets/{TeamDetail-DevkNiHQ.js → TeamDetail-umrDhcwG.js} +1 -1
  170. package/packages/remote-control-server/web/dist/assets/{TeamList-B1pHxRaK.js → TeamList-CI_ppYJz.js} +1 -1
  171. package/packages/remote-control-server/web/dist/assets/{TeamSettings-DWnEJMTx.js → TeamSettings-D_y3NFLr.js} +1 -1
  172. package/packages/remote-control-server/web/dist/assets/{UserSearchInput-DgktGnh2.js → UserSearchInput-BJTMnFdQ.js} +1 -1
  173. package/packages/remote-control-server/web/dist/assets/{UserSettings-DPhvsn9k.js → UserSettings-m2SsR0jt.js} +1 -1
  174. package/packages/remote-control-server/web/dist/assets/{arc-C7foUDWz.js → arc-B-w-om5W.js} +1 -1
  175. package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-BzsYecpv.js → architectureDiagram-3BPJPVTR-A0JqD49y.js} +1 -1
  176. package/{dist/rcs-web/assets/blockDiagram-GPEHLZMM-D4BSEcZT.js → packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-CRmWH6Kh.js} +1 -1
  177. package/{dist/rcs-web/assets/c4Diagram-AAUBKEIU-CIap7aYJ.js → packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-Dil5npJC.js} +1 -1
  178. package/packages/remote-control-server/web/dist/assets/channel-BAxtMvz9.js +1 -0
  179. package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-s9V4oCUf.js → chunk-2J33WTMH-B0U3olYO.js} +1 -1
  180. package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-CJrYwRaR.js → chunk-4BX2VUAB-D8eZOxCq.js} +1 -1
  181. package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-D8swZDnP.js → chunk-55IACEB6-BCg1yqKV.js} +1 -1
  182. package/{dist/rcs-web/assets/chunk-727SXJPM-vJ6LjIbB.js → packages/remote-control-server/web/dist/assets/chunk-727SXJPM-C9GSmRyu.js} +1 -1
  183. package/{dist/rcs-web/assets/chunk-AQP2D5EJ-COrMlHZr.js → packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-CDNB1DxJ.js} +1 -1
  184. package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-0lUT-961.js → chunk-FMBD7UC4-CUyVgVhv.js} +1 -1
  185. package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-BWqVDbg4.js → chunk-ND2GUHAM-DWUadZ9h.js} +1 -1
  186. package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-CfeMmsaw.js → chunk-QZHKN3VN-De-swXbY.js} +1 -1
  187. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DAE_PUq2.js +1 -0
  188. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-DAE_PUq2.js +1 -0
  189. package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-FipRU7Gt.js → code-block-IT6T5CEO-DHPrRtQH.js} +1 -1
  190. package/packages/remote-control-server/web/dist/assets/{copy-RtDWH7m7.js → copy-CFPy3H8V.js} +1 -1
  191. package/{dist/rcs-web/assets/cose-bilkent-S5V4N54A-wlwIwiSf.js → packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-CZjBoqHS.js} +1 -1
  192. package/packages/remote-control-server/web/dist/assets/{dagre-BM42HDAG-FlvB-WBQ.js → dagre-BM42HDAG-Cf5v7qFZ.js} +1 -1
  193. package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ-Dd5G25-Q.js → diagram-2AECGRRQ-C7UJVkwm.js} +1 -1
  194. package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-CnS79Wiq.js → diagram-5GNKFQAL-DyOsGtm_.js} +1 -1
  195. package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-oeffrVzV.js → diagram-KO2AKTUF-rj-dLm4C.js} +1 -1
  196. package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-Dc4rRllI.js → diagram-LMA3HP47-5IBISrVO.js} +1 -1
  197. package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-QYKwztsm.js → diagram-OG6HWLK6-CvKsIOGI.js} +1 -1
  198. package/packages/remote-control-server/web/dist/assets/{dialog-C6bSop75.js → dialog-D3djNDCB.js} +1 -1
  199. package/{dist/rcs-web/assets/erDiagram-TEJ5UH35-CFoDAbeH.js → packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-DN3O1WDD.js} +1 -1
  200. package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-zOHsjkHO.js → flowDiagram-I6XJVG4X-CXmRfzEy.js} +1 -1
  201. package/{dist/rcs-web/assets/ganttDiagram-6RSMTGT7-DmdYR8vQ.js → packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-6uA2-PAt.js} +1 -1
  202. package/{dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-ChNq0nxK.js → packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-DWYRvHtj.js} +1 -1
  203. package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-CTOfXwsH.js → infoDiagram-5YYISTIA-CJt4bepj.js} +1 -1
  204. package/packages/remote-control-server/web/dist/assets/{ishikawaDiagram-YF4QCWOH-AbFaqfWq.js → ishikawaDiagram-YF4QCWOH-DYHvIeSs.js} +1 -1
  205. package/packages/remote-control-server/web/dist/assets/{journeyDiagram-JHISSGLW-BZ5YDbY5.js → journeyDiagram-JHISSGLW-DWQeWDV-.js} +1 -1
  206. package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-2ujiDLTJ.js → kanban-definition-UN3LZRKU-D1vYCpGq.js} +1 -1
  207. package/packages/remote-control-server/web/dist/assets/{linear-hvc2NcTZ.js → linear-DEn8Cs7O.js} +1 -1
  208. package/packages/remote-control-server/web/dist/assets/{main-2KqxLOVo.js → main-COET8kmB.js} +3 -3
  209. package/{dist/rcs-web/assets/mermaid-VLURNSYL-CjE066pc.js → packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-DJIytlGH.js} +4 -4
  210. package/packages/remote-control-server/web/dist/assets/{mermaid.core-D0z5iBed.js → mermaid.core-DVQA7rXK.js} +5 -5
  211. package/{dist/rcs-web/assets/mindmap-definition-RKZ34NQL-DN_a_x4Q.js → packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-Dhv_wo7x.js} +1 -1
  212. package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-EaZYytph.js → pieDiagram-4H26LBE5-C86veflr.js} +1 -1
  213. package/packages/remote-control-server/web/dist/assets/{quadrantDiagram-W4KKPZXB-BbYaZQ_j.js → quadrantDiagram-W4KKPZXB-DJmcygzl.js} +1 -1
  214. package/packages/remote-control-server/web/dist/assets/{refresh-cw-2QNtciSF.js → refresh-cw-BRNwaL3w.js} +1 -1
  215. package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-sQpG_uMR.js → requirementDiagram-4Y6WPE33-PDkq_ITC.js} +1 -1
  216. package/packages/remote-control-server/web/dist/assets/{sankeyDiagram-5OEKKPKP-Dk-ywMbO.js → sankeyDiagram-5OEKKPKP-DvCuhECf.js} +1 -1
  217. package/packages/remote-control-server/web/dist/assets/{sequenceDiagram-3UESZ5HK-B8kXKWV0.js → sequenceDiagram-3UESZ5HK-Co2LWujo.js} +1 -1
  218. package/packages/remote-control-server/web/dist/assets/{stateDiagram-AJRCARHV-BIjc-tAY.js → stateDiagram-AJRCARHV-CDTXzmhr.js} +1 -1
  219. package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-BjJyk52d.js → stateDiagram-v2-BHNVJYJU-Sdqiqtes.js} +1 -1
  220. package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-9Myr5rlZ.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-Cudtpim6.js} +1 -1
  221. package/packages/remote-control-server/web/dist/assets/{vennDiagram-CIIHVFJN-B_0p3XFw.js → vennDiagram-CIIHVFJN-B_84pCPM.js} +1 -1
  222. package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-JKVEgrM5.js → wardleyDiagram-YWT4CUSO-B_tneRWc.js} +1 -1
  223. package/packages/remote-control-server/web/dist/assets/{xychartDiagram-2RQKCTM6-DUPPleBK.js → xychartDiagram-2RQKCTM6-CNdStpy2.js} +1 -1
  224. package/packages/remote-control-server/web/dist/index.html +1 -1
  225. package/dist/rcs-web/assets/channel-69qfoCOr.js +0 -1
  226. package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DihFTUAb.js +0 -1
  227. package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DihFTUAb.js +0 -1
  228. package/packages/remote-control-server/web/dist/assets/channel-69qfoCOr.js +0 -1
  229. package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DihFTUAb.js +0 -1
  230. package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-DihFTUAb.js +0 -1
@@ -0,0 +1,26 @@
1
+ // Re-render every bundled example from its JSON IR. Installed skills keep HTML
2
+ // beside the JSON examples; the development script passes the golden directory.
3
+
4
+ import { execFileSync } from 'node:child_process';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const skillRoot = path.resolve(__dirname, '..');
10
+ const outputRoot = path.resolve(process.argv[2] || path.join(skillRoot, 'examples'));
11
+
12
+ const TARGETS = [
13
+ ['workflow', 'agent-tool-call.workflow.json', 'workflow-agent-tool-call-rendered.html'],
14
+ ['sequence', 'cache-miss-request.sequence.json', 'sequence-cache-miss-request.html'],
15
+ ['dataflow', 'product-analytics.dataflow.json', 'dataflow-product-analytics.html'],
16
+ ['lifecycle', 'agent-run.lifecycle.json', 'lifecycle-agent-run.html'],
17
+ ['architecture', 'web-app.architecture.json', 'web-app-rendered.html'],
18
+ ];
19
+
20
+ for (const [mode, input, output] of TARGETS) {
21
+ execFileSync(process.execPath, [
22
+ path.join(skillRoot, `renderers/${mode}/render-${mode}.mjs`),
23
+ path.join(skillRoot, 'examples', input),
24
+ path.join(outputRoot, output),
25
+ ], { stdio: 'inherit' });
26
+ }
@@ -0,0 +1,182 @@
1
+ export const SKILL_ID = 'archify';
2
+ export const EXPECTED_REPOSITORY = 'https://github.com/tt-a1i/archify';
3
+ export const DEFAULT_MANIFEST_URL = 'https://tt-a1i.github.io/archify/skill-updates/archify/stable.json';
4
+
5
+ const CONTROL_OR_BIDI = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
6
+ const HEX_40 = /^[a-f0-9]{40}$/;
7
+ const HEX_64 = /^[a-f0-9]{64}$/;
8
+ const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
9
+ const UTC_SECONDS = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
10
+
11
+ export class UpdateContractError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = 'UpdateContractError';
15
+ }
16
+ }
17
+
18
+ function isPlainObject(value) {
19
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
20
+ }
21
+
22
+ function hasExactKeys(value, expected) {
23
+ return isPlainObject(value)
24
+ && Object.keys(value).sort().join('\0') === [...expected].sort().join('\0');
25
+ }
26
+
27
+ export function parseSemver(value) {
28
+ if (typeof value !== 'string' || value.length > 128) {
29
+ throw new UpdateContractError(`invalid SemVer: ${JSON.stringify(value)}`);
30
+ }
31
+ const match = SEMVER.exec(value);
32
+ if (!match) throw new UpdateContractError(`invalid SemVer: ${JSON.stringify(value)}`);
33
+ const prerelease = match[4]?.split('.') ?? null;
34
+ if (prerelease?.some((identifier) => /^\d+$/.test(identifier)
35
+ && identifier.length > 1 && identifier.startsWith('0'))) {
36
+ throw new UpdateContractError(`invalid SemVer: ${JSON.stringify(value)}`);
37
+ }
38
+ return {
39
+ core: match.slice(1, 4),
40
+ prerelease,
41
+ build: match[5]?.split('.') ?? null,
42
+ };
43
+ }
44
+
45
+ function compareNumericIdentifiers(left, right) {
46
+ if (left.length !== right.length) return left.length < right.length ? -1 : 1;
47
+ if (left === right) return 0;
48
+ return left < right ? -1 : 1;
49
+ }
50
+
51
+ function comparePrerelease(left, right) {
52
+ if (left === null && right === null) return 0;
53
+ if (left === null) return 1;
54
+ if (right === null) return -1;
55
+ const length = Math.max(left.length, right.length);
56
+ for (let index = 0; index < length; index += 1) {
57
+ if (left[index] === undefined) return -1;
58
+ if (right[index] === undefined) return 1;
59
+ if (left[index] === right[index]) continue;
60
+ const leftNumeric = /^\d+$/.test(left[index]);
61
+ const rightNumeric = /^\d+$/.test(right[index]);
62
+ if (leftNumeric && rightNumeric) return compareNumericIdentifiers(left[index], right[index]);
63
+ if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
64
+ return left[index] < right[index] ? -1 : 1;
65
+ }
66
+ return 0;
67
+ }
68
+
69
+ export function compareSemver(leftValue, rightValue) {
70
+ const left = parseSemver(leftValue);
71
+ const right = parseSemver(rightValue);
72
+ for (let index = 0; index < left.core.length; index += 1) {
73
+ const comparison = compareNumericIdentifiers(left.core[index], right.core[index]);
74
+ if (comparison !== 0) return comparison;
75
+ }
76
+ return comparePrerelease(left.prerelease, right.prerelease);
77
+ }
78
+
79
+ export function releaseChannelForVersion(value) {
80
+ return parseSemver(value).prerelease ? 'development' : 'stable';
81
+ }
82
+
83
+ export function isStableCoreVersion(value) {
84
+ try {
85
+ const parsed = parseSemver(value);
86
+ return parsed.prerelease === null && parsed.build === null;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+
92
+ export function validateCanonicalUtcTimestamp(value) {
93
+ if (typeof value !== 'string' || !UTC_SECONDS.test(value)) {
94
+ throw new UpdateContractError('publication time must use YYYY-MM-DDTHH:mm:ssZ');
95
+ }
96
+ const timestamp = Date.parse(value);
97
+ if (!Number.isFinite(timestamp)
98
+ || new Date(timestamp).toISOString().replace('.000Z', 'Z') !== value) {
99
+ throw new UpdateContractError('publication time is not a real UTC calendar instant');
100
+ }
101
+ return value;
102
+ }
103
+
104
+ export function validateLocalRelease(value) {
105
+ if (!hasExactKeys(value, [
106
+ 'schemaVersion', 'skillId', 'channel', 'version', 'source', 'updateManifestUrl',
107
+ ])
108
+ || value.schemaVersion !== 1
109
+ || value.skillId !== SKILL_ID
110
+ || !hasExactKeys(value.source, ['repository'])
111
+ || value.source.repository !== EXPECTED_REPOSITORY
112
+ || value.updateManifestUrl !== DEFAULT_MANIFEST_URL) {
113
+ throw new UpdateContractError('invalid local release identity');
114
+ }
115
+ const expectedChannel = releaseChannelForVersion(value.version);
116
+ if (value.channel !== expectedChannel) {
117
+ throw new UpdateContractError('local release channel does not match its version');
118
+ }
119
+ return {
120
+ schemaVersion: value.schemaVersion,
121
+ skillId: value.skillId,
122
+ channel: value.channel,
123
+ version: value.version,
124
+ source: { repository: value.source.repository },
125
+ updateManifestUrl: value.updateManifestUrl,
126
+ };
127
+ }
128
+
129
+ export function validateReleaseNotesUrl(value, version) {
130
+ if (!isStableCoreVersion(version)) {
131
+ throw new UpdateContractError('release notes require a stable core version');
132
+ }
133
+ const expected = `https://github.com/tt-a1i/archify/releases/tag/v${version}`;
134
+ if (value !== expected) {
135
+ throw new UpdateContractError('release notes URL is outside the exact trusted release path');
136
+ }
137
+ return value;
138
+ }
139
+
140
+ export function validateStableUpdateManifest(value) {
141
+ if (!hasExactKeys(value, [
142
+ 'schemaVersion', 'skillId', 'channel', 'version', 'publishedAt', 'source',
143
+ 'artifact', 'summary', 'releaseNotes', 'severity',
144
+ ])
145
+ || value.schemaVersion !== 1
146
+ || value.skillId !== SKILL_ID
147
+ || value.channel !== 'stable'
148
+ || !isStableCoreVersion(value.version)
149
+ || !hasExactKeys(value.source, ['repository', 'ref', 'treeSha'])
150
+ || value.source.repository !== EXPECTED_REPOSITORY
151
+ || value.source.ref !== `v${value.version}`
152
+ || !HEX_40.test(value.source.treeSha)
153
+ || !hasExactKeys(value.artifact, ['sha256'])
154
+ || !HEX_64.test(value.artifact.sha256)) {
155
+ throw new UpdateContractError('invalid immutable stable release identity');
156
+ }
157
+ validateCanonicalUtcTimestamp(value.publishedAt);
158
+ if (typeof value.summary !== 'string' || value.summary.length < 1 || value.summary.length > 160
159
+ || CONTROL_OR_BIDI.test(value.summary)) {
160
+ throw new UpdateContractError('invalid release summary');
161
+ }
162
+ validateReleaseNotesUrl(value.releaseNotes, value.version);
163
+ if (!['normal', 'security'].includes(value.severity)) {
164
+ throw new UpdateContractError('invalid update severity');
165
+ }
166
+ return {
167
+ schemaVersion: value.schemaVersion,
168
+ skillId: value.skillId,
169
+ channel: value.channel,
170
+ version: value.version,
171
+ publishedAt: value.publishedAt,
172
+ source: {
173
+ repository: value.source.repository,
174
+ ref: value.source.ref,
175
+ treeSha: value.source.treeSha,
176
+ },
177
+ artifact: { sha256: value.artifact.sha256 },
178
+ summary: value.summary,
179
+ releaseNotes: value.releaseNotes,
180
+ severity: value.severity,
181
+ };
182
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "skillId": "archify",
4
+ "channel": "development",
5
+ "version": "2.17.0-dev.1",
6
+ "source": {
7
+ "repository": "https://github.com/tt-a1i/archify"
8
+ },
9
+ "updateManifestUrl": "https://tt-a1i.github.io/archify/skill-updates/archify/stable.json"
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saluzi/saluzi-edu",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Saluzi CLI - interactive AI coding assistant in the terminal",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -419,6 +419,49 @@ describe('stuck-turn watchdog (lost turn-end result regression)', () => {
419
419
  expect(after).toBe(before)
420
420
  })
421
421
 
422
+ test('worker exit signal (synthetic error result) unlocks the session', async () => {
423
+ await driveTurn(app, sessionId)
424
+ expect(getSession(sessionId)?.status).toBe('running')
425
+
426
+ // The bridge worker's session-exit signal: the `--print` child died
427
+ // mid-turn (crash / timeout kill) and bridgeMain posts a synthetic
428
+ // result straight to the session-ingress events endpoint. The server
429
+ // must derive idle AND preserve the reason text for the Web UI.
430
+ const exitRes = await app.request(
431
+ `/v2/session_ingress/session/${sessionId}/events`,
432
+ {
433
+ method: 'POST',
434
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
435
+ body: JSON.stringify({
436
+ events: [
437
+ {
438
+ type: 'result',
439
+ subtype: 'error_during_execution',
440
+ is_error: true,
441
+ result: 'Worker process exited: OOM',
442
+ duration_ms: 1234,
443
+ num_turns: 0,
444
+ uuid: 'exit-result-1',
445
+ session_id: sessionId,
446
+ },
447
+ ],
448
+ }),
449
+ },
450
+ )
451
+ expect(exitRes.status).toBe(200)
452
+ expect(getSession(sessionId)?.status).toBe('idle')
453
+
454
+ // Reason text + is_error must survive normalizePayload so the web
455
+ // adapter can render the error card (not just silently unlock).
456
+ const exitEvent = getEventBus(sessionId)
457
+ .getEventsSince(0)
458
+ .find(e => e.type === 'result')
459
+ const payload = exitEvent?.payload as Record<string, unknown>
460
+ expect(payload.result).toBe('Worker process exited: OOM')
461
+ expect(payload.is_error).toBe(true)
462
+ expect(payload.subtype).toBe('error_during_execution')
463
+ })
464
+
422
465
  test('server-restart legacy: running session with an empty bus heals', async () => {
423
466
  // A session persisted as `running` whose bus is fresh (server restart)
424
467
  // has no turn signal at all — the sweep falls back to the session's
@@ -23,6 +23,7 @@ import {
23
23
  touchClientActivity,
24
24
  closeInactiveClient,
25
25
  } from '../transport/ws-handler'
26
+ import { publishSessionEvent } from '../services/transport'
26
27
 
27
28
  // Minimal WSContext mock
28
29
  function createMockWs(readyState = 1) {
@@ -1125,6 +1126,174 @@ describe('ws-handler', () => {
1125
1126
  })
1126
1127
  })
1127
1128
 
1129
+ // ─────────────────────────────────────────────────────────────────────────
1130
+ // Regression: permission approval lost during a WS gap → turn parked on
1131
+ // the permission wait forever (session stuck requires_action, card already
1132
+ // optimistically removed → total deadlock). Root cause is two-fold on the
1133
+ // server→worker direction (the worker→server direction is covered by the
1134
+ // bridge's verified-write retry):
1135
+ // 1. the live subscriber silently drops outbound events while
1136
+ // ws.readyState !== 1 (reconnect window), and
1137
+ // 2. on reconnect, NON_REPLAYABLE_EVENT_TYPES filtered
1138
+ // permission_response / control_response out of the history replay —
1139
+ // the approval was never re-delivered.
1140
+ // Outbound RESPONSES are replay-safe (the worker settles by request_id;
1141
+ // already-settled ids are logged and ignored) and must be replayed.
1142
+ // Outbound control_REQUESTS stay non-replayable (a replayed interrupt
1143
+ // aborts the post-reconnect turn).
1144
+ describe('approval replay across WS reconnect (lost-response regression)', () => {
1145
+ test('approval sent during the WS gap is re-delivered on reconnect', () => {
1146
+ const env = storeCreateEnvironment({ secret: 's' })
1147
+ const session = storeCreateSession({ environmentId: env.id })
1148
+ const bus = getEventBus(session.id)
1149
+
1150
+ // 1. Worker connects and asks for permission mid-turn.
1151
+ const ws1 = createMockWs()
1152
+ handleWebSocketOpen(ws1, session.id)
1153
+ ingestBridgeMessage(session.id, {
1154
+ type: 'control_request',
1155
+ request_id: 'perm-lost-1',
1156
+ request: {
1157
+ subtype: 'can_use_tool',
1158
+ tool_name: 'Bash',
1159
+ input: { command: 'echo hi' },
1160
+ tool_use_id: 'tu1',
1161
+ },
1162
+ })
1163
+ const { getSession } = require('../services/session')
1164
+ expect(getSession(session.id)?.status).toBe('requires_action')
1165
+
1166
+ // 2. The worker's WS drops (zombie recovery / network blip).
1167
+ handleWebSocketClose(ws1, session.id, 1006, 'network')
1168
+
1169
+ // 3. The remote user approves while no WS is live — the same publish
1170
+ // POST /web/sessions/:id/control performs. subscriberCount is 0:
1171
+ // the live path drops it.
1172
+ expect(bus.subscriberCount()).toBe(0)
1173
+ publishSessionEvent(
1174
+ session.id,
1175
+ 'permission_response',
1176
+ {
1177
+ type: 'permission_response',
1178
+ approved: true,
1179
+ request_id: 'perm-lost-1',
1180
+ },
1181
+ 'outbound',
1182
+ )
1183
+
1184
+ // 4. The worker reconnects (auto-reconnect, seconds later).
1185
+ const ws2 = createMockWs()
1186
+ handleWebSocketOpen(ws2, session.id)
1187
+
1188
+ // 5. The approval MUST be re-delivered — otherwise the turn stays
1189
+ // parked on the permission wait forever (the reported stuck).
1190
+ const frames = ws2
1191
+ .getSentData()
1192
+ .map((d: string) => JSON.parse(d))
1193
+ .filter((m: { type?: string }) => m.type === 'control_response')
1194
+ expect(frames).toHaveLength(1)
1195
+ expect(frames[0].response.request_id).toBe('perm-lost-1')
1196
+ expect(frames[0].response.response.behavior).toBe('allow')
1197
+
1198
+ handleWebSocketClose(ws2, session.id, 1000, 'done')
1199
+ })
1200
+
1201
+ test('denials (with feedback) replay identically', () => {
1202
+ const session = storeCreateSession({})
1203
+ const ws1 = createMockWs()
1204
+ handleWebSocketOpen(ws1, session.id)
1205
+ handleWebSocketClose(ws1, session.id, 1006, 'network')
1206
+
1207
+ publishSessionEvent(
1208
+ session.id,
1209
+ 'permission_response',
1210
+ {
1211
+ type: 'permission_response',
1212
+ approved: false,
1213
+ request_id: 'perm-deny-1',
1214
+ message: 'use the other file',
1215
+ },
1216
+ 'outbound',
1217
+ )
1218
+
1219
+ const ws2 = createMockWs()
1220
+ handleWebSocketOpen(ws2, session.id)
1221
+
1222
+ const frames = ws2
1223
+ .getSentData()
1224
+ .map((d: string) => JSON.parse(d))
1225
+ .filter((m: { type?: string }) => m.type === 'control_response')
1226
+ expect(frames).toHaveLength(1)
1227
+ expect(frames[0].response.response.behavior).toBe('deny')
1228
+ expect(frames[0].response.response.message).toBe('use the other file')
1229
+
1230
+ handleWebSocketClose(ws2, session.id, 1000, 'done')
1231
+ })
1232
+
1233
+ test('the worker\u2019s own inbound control_response echoes are NOT replayed', () => {
1234
+ const session = storeCreateSession({})
1235
+ ingestBridgeMessage(session.id, {
1236
+ type: 'control_response',
1237
+ response: {
1238
+ subtype: 'success',
1239
+ request_id: 'ctx-1',
1240
+ response: {},
1241
+ },
1242
+ })
1243
+
1244
+ const ws = createMockWs()
1245
+ handleWebSocketOpen(ws, session.id)
1246
+
1247
+ const frames = ws
1248
+ .getSentData()
1249
+ .map((d: string) => JSON.parse(d))
1250
+ .filter((m: { type?: string }) => m.type === 'control_response')
1251
+ expect(frames).toHaveLength(0)
1252
+
1253
+ handleWebSocketClose(ws, session.id, 1000, 'done')
1254
+ })
1255
+
1256
+ test('outbound control_request (interrupt / RPC) stays non-replayable', () => {
1257
+ const session = storeCreateSession({})
1258
+ const ws1 = createMockWs()
1259
+ handleWebSocketOpen(ws1, session.id)
1260
+ handleWebSocketClose(ws1, session.id, 1006, 'network')
1261
+
1262
+ // A user prompt and an interrupt both land during the gap.
1263
+ publishSessionEvent(
1264
+ session.id,
1265
+ 'user',
1266
+ { type: 'user', uuid: 'gap-user-1', content: 'hello' },
1267
+ 'outbound',
1268
+ )
1269
+ publishSessionEvent(
1270
+ session.id,
1271
+ 'interrupt',
1272
+ { action: 'interrupt' },
1273
+ 'outbound',
1274
+ )
1275
+
1276
+ const ws2 = createMockWs()
1277
+ handleWebSocketOpen(ws2, session.id)
1278
+
1279
+ const sent = ws2.getSentData().map((d: string) => JSON.parse(d))
1280
+ // Conversation replay still works…
1281
+ expect(
1282
+ sent.filter((m: { type?: string; uuid?: string }) => m.type === 'user'),
1283
+ ).toHaveLength(1)
1284
+ // …but a point-in-time interrupt must never resurrect on reconnect
1285
+ // (it would abort the post-reconnect turn).
1286
+ expect(
1287
+ sent.filter(
1288
+ (m: { type?: string; request?: { subtype?: string } }) =>
1289
+ m.type === 'control_request' && m.request?.subtype === 'interrupt',
1290
+ ),
1291
+ ).toHaveLength(0)
1292
+
1293
+ handleWebSocketClose(ws2, session.id, 1000, 'done')
1294
+ })
1295
+ })
1296
+
1128
1297
  describe('closeAllConnections', () => {
1129
1298
  test('closes all active connections', () => {
1130
1299
  const ws1 = createMockWs()
@@ -132,11 +132,15 @@ export function normalizePayload(
132
132
  }
133
133
 
134
134
  // Preserve result usage/cost so the web UI can render cumulative session
135
- // totals (mirrors the CLI StatusLine).
135
+ // totals (mirrors the CLI StatusLine). `result` text + `is_error` survive
136
+ // too — error-subtyped results (worker crash / timeout exit signal) must
137
+ // render their reason in the Web UI, not just flip the status to idle.
136
138
  if (type === 'result' || type === 'result_success') {
137
139
  if (p.usage && typeof p.usage === 'object') normalized.usage = p.usage
138
140
  if (typeof p.total_cost_usd === 'number')
139
141
  normalized.total_cost_usd = p.total_cost_usd
142
+ if (typeof p.result === 'string') normalized.result = p.result
143
+ if (typeof p.is_error === 'boolean') normalized.is_error = p.is_error
140
144
  }
141
145
 
142
146
  // Streaming deltas — the child emits type:'stream_event' (raw Anthropic
@@ -45,6 +45,35 @@ const NON_REPLAYABLE_EVENT_TYPES = new Set([
45
45
  'interrupt',
46
46
  ])
47
47
 
48
+ /**
49
+ * Exception to NON_REPLAYABLE_EVENT_TYPES: outbound control/permission
50
+ * RESPONSES (Web-UI approvals, denials, generic control answers) are
51
+ * replay-safe and MUST be re-delivered on reconnect.
52
+ *
53
+ * The live subscriber silently drops every outbound event published while
54
+ * ws.readyState !== 1 (the reconnect window). For conversation events the
55
+ * replay below covers that; for approval responses it used not to — they
56
+ * were in NON_REPLAYABLE_EVENT_TYPES, so an approval sent during the gap
57
+ * was lost forever. The worker's turn then stayed parked on the permission
58
+ * wait (no timeout on the pending handler), the session sat on
59
+ * requires_action with the card already optimistically removed → total
60
+ * deadlock (observed: `slz rcs one` stuck mid-task at a permission step).
61
+ *
62
+ * Replay safety: the worker settles responses by request_id — a response
63
+ * for an already-settled/unknown request is logged and ignored
64
+ * (useReplBridge handlePermissionResponse). Inbound (worker-authored)
65
+ * responses are NOT covered by this exception — they stay filtered.
66
+ * Outbound control_REQUESTS (interrupt, set_model, RPCs) stay
67
+ * non-replayable: a replayed interrupt would abort the post-reconnect
68
+ * turn.
69
+ */
70
+ function isReplayableOutboundResponse(event: SessionEvent): boolean {
71
+ if (event.direction !== 'outbound') return false
72
+ return (
73
+ event.type === 'control_response' || event.type === 'permission_response'
74
+ )
75
+ }
76
+
48
77
  // Server-side keepalive interval (configurable via RCS_WS_KEEPALIVE_INTERVAL).
49
78
  // Sends data frames to keep reverse proxies from closing idle connections.
50
79
  const SERVER_KEEPALIVE_INTERVAL_MS = (config.wsKeepaliveInterval || 20) * 1000
@@ -88,11 +117,15 @@ export function handleWebSocketOpen(ws: WSContext, sessionId: string) {
88
117
  // history — assistant replies are inbound events. Transient streaming
89
118
  // deltas are skipped (display-only, would flood the child's stdin parser),
90
119
  // and so is point-in-time control traffic (see NON_REPLAYABLE_EVENT_TYPES —
91
- // a replayed interrupt would abort the post-reconnect turn).
120
+ // a replayed interrupt would abort the post-reconnect turn). Outbound
121
+ // approval/permission RESPONSES are the exception — see
122
+ // isReplayableOutboundResponse.
92
123
  const missed = bus.getEventsSince(0)
93
124
  if (missed.length > 0) {
94
125
  const replayable = missed.filter(
95
- event => !NON_REPLAYABLE_EVENT_TYPES.has(event.type),
126
+ event =>
127
+ !NON_REPLAYABLE_EVENT_TYPES.has(event.type) ||
128
+ isReplayableOutboundResponse(event),
96
129
  )
97
130
  log(
98
131
  `[WS] Replaying ${replayable.length} of ${missed.length} retained event(s)`,
@@ -433,11 +466,13 @@ export function ingestBridgeMessage(
433
466
  payload = { response: msg.response }
434
467
  } else if (eventType === 'result' || eventType === 'result_success') {
435
468
  // Keep usage/cost so the web UI can render cumulative session totals
436
- // (mirrors the CLI StatusLine). Other result fields stay internal.
469
+ // (mirrors the CLI StatusLine), and result/is_error so error-subtyped
470
+ // results (worker crash / timeout exit signal) render their reason.
437
471
  payload = {
438
472
  subtype: msg.subtype,
439
473
  uuid: msg.uuid,
440
474
  result: msg.result,
475
+ ...(msg.is_error !== undefined ? { is_error: msg.is_error } : {}),
441
476
  ...(msg.total_cost_usd !== undefined
442
477
  ? { total_cost_usd: msg.total_cost_usd }
443
478
  : {}),
@@ -1 +1 @@
1
- import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{aC as x,aD as o,Y as m,aw as s,al as l,z as u}from"./main-2KqxLOVo.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){x();const[a,i]=d.useState([]),{myTeams:r,isLoading:c}=o(),n=d.useCallback(async()=>{try{const t=await m();i(t||[])}catch(t){console.error("Admin: failed to load sessions",t)}},[]);return d.useEffect(()=>{n()},[n]),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"mb-6 font-display text-2xl font-semibold text-text-primary",children:s("admin.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.teams")," (",r.length,")"]}),c?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("common.loading")}):r.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noTeams")}):e.jsx("div",{className:"space-y-2",children:r.map(t=>e.jsxs("a",{href:`/teams/${t.slug}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium text-text-primary",children:t.name}),e.jsx("span",{className:"ml-2 text-xs text-text-muted",children:t.slug})]}),e.jsx("span",{className:"text-xs text-text-muted",children:l(new Date(t.created_at).getTime()/1e3)})]},t.id))})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.sessions")," (",a.length,")"]}),a.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noSessions")}):e.jsx("div",{className:"space-y-2",children:a.map(t=>e.jsxs("a",{href:`/code/${t.id}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),e.jsx("span",{className:"rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-muted",children:t.source||"unknown"})]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"ml-4 flex items-center gap-3",children:[e.jsx(u,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:l(t.updated_at||t.created_at)})]})]},t.id))})]})]})})}export{j as AdminPanel};
1
+ import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{aC as x,aD as o,Y as m,aw as s,al as l,z as u}from"./main-COET8kmB.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){x();const[a,i]=d.useState([]),{myTeams:r,isLoading:c}=o(),n=d.useCallback(async()=>{try{const t=await m();i(t||[])}catch(t){console.error("Admin: failed to load sessions",t)}},[]);return d.useEffect(()=>{n()},[n]),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"mb-6 font-display text-2xl font-semibold text-text-primary",children:s("admin.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.teams")," (",r.length,")"]}),c?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("common.loading")}):r.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noTeams")}):e.jsx("div",{className:"space-y-2",children:r.map(t=>e.jsxs("a",{href:`/teams/${t.slug}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium text-text-primary",children:t.name}),e.jsx("span",{className:"ml-2 text-xs text-text-muted",children:t.slug})]}),e.jsx("span",{className:"text-xs text-text-muted",children:l(new Date(t.created_at).getTime()/1e3)})]},t.id))})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.sessions")," (",a.length,")"]}),a.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noSessions")}):e.jsx("div",{className:"space-y-2",children:a.map(t=>e.jsxs("a",{href:`/code/${t.id}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),e.jsx("span",{className:"rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-muted",children:t.source||"unknown"})]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"ml-4 flex items-center gap-3",children:[e.jsx(u,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:l(t.updated_at||t.created_at)})]})]},t.id))})]})]})})}export{j as AdminPanel};
@@ -1 +1 @@
1
- import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{aC as A,Z as j,aw as r,V as q,ah as R,P as U,G as F}from"./main-2KqxLOVo.js";import{S as O,E as G,C as K}from"./ArtifactsGallery-B_JcCYh1.js";import{R as P}from"./refresh-cw-2QNtciSF.js";import{C as V}from"./copy-RtDWH7m7.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./dialog-C6bSop75.js";let m=null;function J(n,c,e=0){b();const o=`/web/sessions/${n}/events`,l=new EventSource(o,{withCredentials:!0});m=l;let u=e;l.addEventListener("message",p=>{try{const x=JSON.parse(p.data);if(x.seqNum!==void 0&&x.seqNum<=u)return;x.seqNum!==void 0&&(u=x.seqNum),c(x)}catch{}}),l.addEventListener("error",()=>{console.warn("[SSE] error, readyState:",l.readyState),l.readyState===EventSource.CLOSED&&(l.close(),b())})}function b(){m&&(m.close(),m=null)}function M(n,c){const e=a.useRef(c);e.current=c;const o=a.useCallback(l=>{e.current(l)},[]);a.useEffect(()=>{if(n)return J(n,o),()=>{b()}},[n,o])}function I({artifactId:n,onBack:c}){A();const[e,o]=a.useState(null),[l,u]=a.useState(""),[p,x]=a.useState(!1),[S,f]=a.useState(0),[w,h]=a.useState(!1),[g,C]=a.useState(null),[E,k]=a.useState("template"),[d,y]=a.useState(!1);a.useEffect(()=>{let s=!1;return j(n).then(i=>{s||o(i)}).catch(i=>{s||u(i instanceof Error?i.message:r("artifacts.viewNotFound"))}),()=>{s=!0}},[n]);const v=a.useCallback(()=>{j(n).then(s=>o(s)).catch(()=>{})},[n]),_=a.useCallback(s=>{var i;s.type==="artifact_updated"&&((i=s.payload)!=null&&i.id&&s.payload.id!==n||(v(),f(D=>D+1),y(!0)))},[n,v]);M((e==null?void 0:e.session_id)??null,_),a.useEffect(()=>{if(!d)return;const s=setTimeout(()=>y(!1),2500);return()=>clearTimeout(s)},[d]);const N=a.useCallback(s=>{e&&(C(e),k(s),h(!0))},[e]),$=a.useCallback(s=>{h(!1),o(i=>i?{...i,...s}:s),f(i=>i+1)},[]),T=a.useCallback(async()=>{if(window.confirm(r("artifacts.delete")+" — "+n.slice(0,8)+"…?"))try{await q(n),c()}catch(s){alert(s instanceof Error?s.message:r("artifacts.deleteFailed"))}},[n,c]),L=a.useCallback(async()=>{if(!e)return;await R(`${window.location.origin}${e.url}`)&&(x(!0),setTimeout(()=>x(!1),1500))},[e]);return l?t.jsx("div",{className:"flex flex-1 items-center justify-center",children:t.jsxs("div",{className:"text-center",children:[t.jsx("p",{className:"text-status-error",children:r("artifacts.viewNotFound")}),t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:l}),t.jsx("button",{type:"button",onClick:c,className:"mt-4 rounded-md border border-border px-4 py-2 text-sm text-text-secondary hover:bg-surface-2",children:r("artifacts.backToGallery")})]})}):e?t.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2 border-b border-border bg-surface-1 px-4 py-2.5",children:[t.jsx("button",{type:"button",onClick:c,className:"text-sm text-text-muted hover:text-text-primary",children:r("artifacts.backToGallery")}),t.jsx("span",{className:"text-text-muted/40",children:"/"}),t.jsx("span",{className:"truncate font-medium text-text-primary",children:e.title||e.id.slice(0,12)}),t.jsx("span",{className:`rounded-full px-2 py-0.5 text-[11px] transition-colors ${d?"bg-status-active/15 text-status-active":"bg-surface-3 text-text-muted"}`,title:d?r("artifacts.view.liveUpdated"):void 0,children:d?`↻ v${e.version}`:`v${e.version}`}),e.session_id&&t.jsxs("a",{href:`/code/${e.session_id}`,className:"truncate font-mono text-[11px] text-text-muted hover:text-accent",title:e.session_id,children:[r("artifacts.session"),": ",e.session_id.slice(0,14),"…"]}),e.expires_at&&t.jsxs("span",{className:"text-[11px] text-text-muted",title:e.expires_at,children:[r("artifacts.expires"),": ",new Date(e.expires_at).toLocaleDateString()]}),t.jsxs("div",{className:"ml-auto flex items-center gap-1",children:[t.jsx("button",{type:"button",onClick:()=>f(s=>s+1),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("common.loading"),children:t.jsx(P,{className:"h-3.5 w-3.5"})}),t.jsx("button",{type:"button",onClick:()=>N("ai"),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.aiUpdate"),children:t.jsx(O,{className:"h-3.5 w-3.5"})}),e.can_manage&&t.jsx("button",{type:"button",onClick:()=>N("template"),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.edit"),children:t.jsx(U,{className:"h-3.5 w-3.5"})}),t.jsxs("button",{type:"button",onClick:L,className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:`${r("artifacts.copyLink")} · ${r("artifacts.linkNotice")}`,children:[t.jsx(V,{className:"h-3.5 w-3.5"}),p&&t.jsx("span",{className:"text-status-active",children:r("artifacts.copied")})]}),t.jsx("a",{href:e.url,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.openInNewTab"),children:t.jsx(G,{className:"h-3.5 w-3.5"})}),t.jsx("button",{type:"button",onClick:T,className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-status-error/10 hover:text-status-error",title:r("artifacts.delete"),children:t.jsx(F,{className:"h-3.5 w-3.5"})})]})]}),t.jsx("iframe",{src:`${e.url}${e.url.includes("?")?"&":"?"}_=${Date.now()}`,title:e.title||e.id,className:"min-h-0 w-full flex-1 border-0 bg-white",sandbox:"allow-scripts allow-popups allow-forms"},S),t.jsx(K,{open:w,onClose:()=>h(!1),onCreated:$,editArtifact:g,initialMode:E})]}):t.jsx("div",{className:"flex flex-1 items-center justify-center text-text-muted",children:r("common.loading")})}export{I as ArtifactView};
1
+ import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{aC as A,Z as j,aw as r,V as q,ah as R,P as U,G as F}from"./main-COET8kmB.js";import{S as O,E as G,C as K}from"./ArtifactsGallery-CykyoUxk.js";import{R as P}from"./refresh-cw-BRNwaL3w.js";import{C as V}from"./copy-CFPy3H8V.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";import"./dialog-D3djNDCB.js";let m=null;function J(n,c,e=0){b();const o=`/web/sessions/${n}/events`,l=new EventSource(o,{withCredentials:!0});m=l;let u=e;l.addEventListener("message",p=>{try{const x=JSON.parse(p.data);if(x.seqNum!==void 0&&x.seqNum<=u)return;x.seqNum!==void 0&&(u=x.seqNum),c(x)}catch{}}),l.addEventListener("error",()=>{console.warn("[SSE] error, readyState:",l.readyState),l.readyState===EventSource.CLOSED&&(l.close(),b())})}function b(){m&&(m.close(),m=null)}function M(n,c){const e=a.useRef(c);e.current=c;const o=a.useCallback(l=>{e.current(l)},[]);a.useEffect(()=>{if(n)return J(n,o),()=>{b()}},[n,o])}function I({artifactId:n,onBack:c}){A();const[e,o]=a.useState(null),[l,u]=a.useState(""),[p,x]=a.useState(!1),[S,f]=a.useState(0),[w,h]=a.useState(!1),[g,C]=a.useState(null),[E,k]=a.useState("template"),[d,y]=a.useState(!1);a.useEffect(()=>{let s=!1;return j(n).then(i=>{s||o(i)}).catch(i=>{s||u(i instanceof Error?i.message:r("artifacts.viewNotFound"))}),()=>{s=!0}},[n]);const v=a.useCallback(()=>{j(n).then(s=>o(s)).catch(()=>{})},[n]),_=a.useCallback(s=>{var i;s.type==="artifact_updated"&&((i=s.payload)!=null&&i.id&&s.payload.id!==n||(v(),f(D=>D+1),y(!0)))},[n,v]);M((e==null?void 0:e.session_id)??null,_),a.useEffect(()=>{if(!d)return;const s=setTimeout(()=>y(!1),2500);return()=>clearTimeout(s)},[d]);const N=a.useCallback(s=>{e&&(C(e),k(s),h(!0))},[e]),$=a.useCallback(s=>{h(!1),o(i=>i?{...i,...s}:s),f(i=>i+1)},[]),T=a.useCallback(async()=>{if(window.confirm(r("artifacts.delete")+" — "+n.slice(0,8)+"…?"))try{await q(n),c()}catch(s){alert(s instanceof Error?s.message:r("artifacts.deleteFailed"))}},[n,c]),L=a.useCallback(async()=>{if(!e)return;await R(`${window.location.origin}${e.url}`)&&(x(!0),setTimeout(()=>x(!1),1500))},[e]);return l?t.jsx("div",{className:"flex flex-1 items-center justify-center",children:t.jsxs("div",{className:"text-center",children:[t.jsx("p",{className:"text-status-error",children:r("artifacts.viewNotFound")}),t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:l}),t.jsx("button",{type:"button",onClick:c,className:"mt-4 rounded-md border border-border px-4 py-2 text-sm text-text-secondary hover:bg-surface-2",children:r("artifacts.backToGallery")})]})}):e?t.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2 border-b border-border bg-surface-1 px-4 py-2.5",children:[t.jsx("button",{type:"button",onClick:c,className:"text-sm text-text-muted hover:text-text-primary",children:r("artifacts.backToGallery")}),t.jsx("span",{className:"text-text-muted/40",children:"/"}),t.jsx("span",{className:"truncate font-medium text-text-primary",children:e.title||e.id.slice(0,12)}),t.jsx("span",{className:`rounded-full px-2 py-0.5 text-[11px] transition-colors ${d?"bg-status-active/15 text-status-active":"bg-surface-3 text-text-muted"}`,title:d?r("artifacts.view.liveUpdated"):void 0,children:d?`↻ v${e.version}`:`v${e.version}`}),e.session_id&&t.jsxs("a",{href:`/code/${e.session_id}`,className:"truncate font-mono text-[11px] text-text-muted hover:text-accent",title:e.session_id,children:[r("artifacts.session"),": ",e.session_id.slice(0,14),"…"]}),e.expires_at&&t.jsxs("span",{className:"text-[11px] text-text-muted",title:e.expires_at,children:[r("artifacts.expires"),": ",new Date(e.expires_at).toLocaleDateString()]}),t.jsxs("div",{className:"ml-auto flex items-center gap-1",children:[t.jsx("button",{type:"button",onClick:()=>f(s=>s+1),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("common.loading"),children:t.jsx(P,{className:"h-3.5 w-3.5"})}),t.jsx("button",{type:"button",onClick:()=>N("ai"),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.aiUpdate"),children:t.jsx(O,{className:"h-3.5 w-3.5"})}),e.can_manage&&t.jsx("button",{type:"button",onClick:()=>N("template"),className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.edit"),children:t.jsx(U,{className:"h-3.5 w-3.5"})}),t.jsxs("button",{type:"button",onClick:L,className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:`${r("artifacts.copyLink")} · ${r("artifacts.linkNotice")}`,children:[t.jsx(V,{className:"h-3.5 w-3.5"}),p&&t.jsx("span",{className:"text-status-active",children:r("artifacts.copied")})]}),t.jsx("a",{href:e.url,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-surface-2 hover:text-text-primary",title:r("artifacts.openInNewTab"),children:t.jsx(G,{className:"h-3.5 w-3.5"})}),t.jsx("button",{type:"button",onClick:T,className:"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-text-secondary hover:bg-status-error/10 hover:text-status-error",title:r("artifacts.delete"),children:t.jsx(F,{className:"h-3.5 w-3.5"})})]})]}),t.jsx("iframe",{src:`${e.url}${e.url.includes("?")?"&":"?"}_=${Date.now()}`,title:e.title||e.id,className:"min-h-0 w-full flex-1 border-0 bg-white",sandbox:"allow-scripts allow-popups allow-forms"},S),t.jsx(K,{open:w,onClose:()=>h(!1),onCreated:$,editArtifact:g,initialMode:E})]}):t.jsx("div",{className:"flex flex-1 items-center justify-center text-text-muted",children:r("common.loading")})}export{I as ArtifactView};
@@ -1,4 +1,4 @@
1
- var ht=Object.defineProperty;var ut=(t,e,r)=>e in t?ht(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var S=(t,e,r)=>ut(t,typeof e!="symbol"?e+"":e,r);import{e as k,j as o}from"./vendor-DE_-CLIE.js";import{ai as Re,am as ft,aC as Ve,aD as mt,_ as xt,aw as f,V as gt,ah as bt,F as kt,g as yt,P as wt,G as vt,q as He,Z as St,a3 as Rt,ar as Tt,a2 as $t,ab as jt,ac as Et,K as Nt,b as Ct}from"./main-2KqxLOVo.js";import{D as It,a as At,c as Lt,d as zt,b as _t}from"./dialog-C6bSop75.js";import{C as Dt}from"./copy-RtDWH7m7.js";/**
1
+ var ht=Object.defineProperty;var ut=(t,e,r)=>e in t?ht(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var S=(t,e,r)=>ut(t,typeof e!="symbol"?e+"":e,r);import{e as k,j as o}from"./vendor-DE_-CLIE.js";import{ai as Re,am as ft,aC as Ve,aD as mt,_ as xt,aw as f,V as gt,ah as bt,F as kt,g as yt,P as wt,G as vt,q as He,Z as St,a3 as Rt,ar as Tt,a2 as $t,ab as jt,ac as Et,K as Nt,b as Ct}from"./main-COET8kmB.js";import{D as It,a as At,c as Lt,d as zt,b as _t}from"./dialog-D3djNDCB.js";import{C as Dt}from"./copy-CFPy3H8V.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{I as u,Y as f}from"./main-2KqxLOVo.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";const v=2e3,N=3e4;function E(){const c=window.location.pathname.split("/"),i=c[c.length-1]||"",[s,n]=r.useState("idle"),[m,l]=r.useState(null),[a,d]=r.useState(null);return r.useEffect(()=>{if(!i||!i.startsWith("clm_")){l("Invalid claim token"),n("error");return}n("claiming"),u(i).then(t=>{d(t.environment_id),n("waiting")}).catch(t=>{l(t instanceof Error?t.message:"Claim failed"),n("error")})},[i]),r.useEffect(()=>{if(s!=="waiting"||!a)return;let t=!1;const x=Date.now(),o=setInterval(()=>{if(Date.now()-x>N){clearInterval(o),t||n("timeout");return}f().then(h=>{t||(h||[]).some(p=>p.environment_id===a)&&(clearInterval(o),window.location.href="/code/")}).catch(()=>{})},v);return()=>{t=!0,clearInterval(o)}},[s,a]),s==="claiming"?e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})}):s==="error"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsx("a",{href:"/code",className:"mt-4 inline-block text-accent hover:underline",children:"Back to dashboard"})]}):s==="waiting"||s==="timeout"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:"Environment claimed"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:"You are now the owner of this environment."})]}),e.jsxs("div",{className:"space-y-4",children:[a&&e.jsx("p",{className:"font-mono text-xs text-text-muted",children:a}),s==="waiting"?e.jsxs("p",{className:"text-sm text-text-muted",children:["Waiting for the worker to create a session",e.jsx("span",{className:"animate-pulse",children:"…"})]}):e.jsx("p",{className:"text-sm text-text-muted",children:"The worker has not created a session yet — it may be offline or stopped. The session will appear on the dashboard once the worker connects."}),e.jsx("a",{href:"/code",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 transition-colors",children:"Go to dashboard"})]})]}):e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})})}export{E as Claim};
1
+ import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{I as u,Y as f}from"./main-COET8kmB.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";const v=2e3,N=3e4;function E(){const c=window.location.pathname.split("/"),i=c[c.length-1]||"",[s,n]=r.useState("idle"),[m,l]=r.useState(null),[a,d]=r.useState(null);return r.useEffect(()=>{if(!i||!i.startsWith("clm_")){l("Invalid claim token"),n("error");return}n("claiming"),u(i).then(t=>{d(t.environment_id),n("waiting")}).catch(t=>{l(t instanceof Error?t.message:"Claim failed"),n("error")})},[i]),r.useEffect(()=>{if(s!=="waiting"||!a)return;let t=!1;const x=Date.now(),o=setInterval(()=>{if(Date.now()-x>N){clearInterval(o),t||n("timeout");return}f().then(h=>{t||(h||[]).some(p=>p.environment_id===a)&&(clearInterval(o),window.location.href="/code/")}).catch(()=>{})},v);return()=>{t=!0,clearInterval(o)}},[s,a]),s==="claiming"?e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})}):s==="error"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsx("a",{href:"/code",className:"mt-4 inline-block text-accent hover:underline",children:"Back to dashboard"})]}):s==="waiting"||s==="timeout"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:"Environment claimed"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:"You are now the owner of this environment."})]}),e.jsxs("div",{className:"space-y-4",children:[a&&e.jsx("p",{className:"font-mono text-xs text-text-muted",children:a}),s==="waiting"?e.jsxs("p",{className:"text-sm text-text-muted",children:["Waiting for the worker to create a session",e.jsx("span",{className:"animate-pulse",children:"…"})]}):e.jsx("p",{className:"text-sm text-text-muted",children:"The worker has not created a session yet — it may be offline or stopped. The session will appear on the dashboard once the worker connects."}),e.jsx("a",{href:"/code",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 transition-colors",children:"Go to dashboard"})]})]}):e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})})}export{E as Claim};
@@ -1,4 +1,4 @@
1
- import{j as e,e as n}from"./vendor-DE_-CLIE.js";import{ai as O,ag as S,aD as T,aB as L,z as F,aC as M,aw as a,al as R,r as $,t as A,e as W,s as q,d as I,ao as H,N as Q,aa as V,Y as z,$ as U,W as Y}from"./main-2KqxLOVo.js";import{g as E}from"./workerType-Bd-zteMi.js";import{S as Z}from"./SessionVisibilityBadge-CvqFRTea.js";import{D as G,a as J,c as K,d as X,b as ee}from"./dialog-C6bSop75.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
1
+ import{j as e,e as n}from"./vendor-DE_-CLIE.js";import{ai as O,ag as S,aD as T,aB as L,z as F,aC as M,aw as a,al as R,r as $,t as A,e as W,s as q,d as I,ao as H,N as Q,aa as V,Y as z,$ as U,W as Y}from"./main-COET8kmB.js";import{g as E}from"./workerType-Bd-zteMi.js";import{S as Z}from"./SessionVisibilityBadge-BkZImPBJ.js";import{D as G,a as J,c as K,d as X,b as ee}from"./dialog-D3djNDCB.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.