@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.
- package/dist/cli.js +59 -68
- package/dist/guide/guide-data.json +1 -1
- package/dist/rcs-web/assets/{AdminPanel-CpzAO2vZ.js → AdminPanel-CAK-wqCu.js} +1 -1
- package/dist/rcs-web/assets/{ArtifactView-CEyKbOJh.js → ArtifactView-DJxpXvlH.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/ArtifactsGallery-B_JcCYh1.js → dist/rcs-web/assets/ArtifactsGallery-CykyoUxk.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/Claim-CGxjGaui.js → dist/rcs-web/assets/Claim-DZQ8sfWt.js} +1 -1
- package/dist/rcs-web/assets/{Dashboard-DCq-h_y9.js → Dashboard-Cm9ZAh-6.js} +1 -1
- package/dist/rcs-web/assets/{Join-BM43XjA0.js → Join-D1X0Ji0b.js} +1 -1
- package/dist/rcs-web/assets/{Login-CPx4Dc28.js → Login-lDaHrIa-.js} +1 -1
- package/dist/rcs-web/assets/{Register-BV3xfUvd.js → Register-12ki3lPq.js} +1 -1
- package/dist/rcs-web/assets/{SessionDetail-DgMDo7Ge.js → SessionDetail-BZjIjZKu.js} +23 -23
- package/dist/rcs-web/assets/{SessionVisibilityBadge-CvqFRTea.js → SessionVisibilityBadge-BkZImPBJ.js} +1 -1
- package/dist/rcs-web/assets/{Setup-GfWdRpvh.js → Setup-Cpyfr8Pi.js} +1 -1
- package/dist/rcs-web/assets/{ShareLanding-BuEXTqqz.js → ShareLanding-Dh3_QdhD.js} +1 -1
- package/dist/rcs-web/assets/{TeamCreate-DalKoyLy.js → TeamCreate-CZC2EjYw.js} +1 -1
- package/dist/rcs-web/assets/{TeamDetail-DevkNiHQ.js → TeamDetail-umrDhcwG.js} +1 -1
- package/dist/rcs-web/assets/{TeamList-B1pHxRaK.js → TeamList-CI_ppYJz.js} +1 -1
- package/dist/rcs-web/assets/{TeamSettings-DWnEJMTx.js → TeamSettings-D_y3NFLr.js} +1 -1
- package/dist/rcs-web/assets/{UserSearchInput-DgktGnh2.js → UserSearchInput-BJTMnFdQ.js} +1 -1
- package/dist/rcs-web/assets/{UserSettings-DPhvsn9k.js → UserSettings-m2SsR0jt.js} +1 -1
- package/dist/rcs-web/assets/{arc-C7foUDWz.js → arc-B-w-om5W.js} +1 -1
- package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-BzsYecpv.js → architectureDiagram-3BPJPVTR-A0JqD49y.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-D4BSEcZT.js → dist/rcs-web/assets/blockDiagram-GPEHLZMM-CRmWH6Kh.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-CIap7aYJ.js → dist/rcs-web/assets/c4Diagram-AAUBKEIU-Dil5npJC.js} +1 -1
- package/dist/rcs-web/assets/channel-BAxtMvz9.js +1 -0
- package/dist/rcs-web/assets/{chunk-2J33WTMH-s9V4oCUf.js → chunk-2J33WTMH-B0U3olYO.js} +1 -1
- package/dist/rcs-web/assets/{chunk-4BX2VUAB-CJrYwRaR.js → chunk-4BX2VUAB-D8eZOxCq.js} +1 -1
- package/dist/rcs-web/assets/{chunk-55IACEB6-D8swZDnP.js → chunk-55IACEB6-BCg1yqKV.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/chunk-727SXJPM-vJ6LjIbB.js → dist/rcs-web/assets/chunk-727SXJPM-C9GSmRyu.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-COrMlHZr.js → dist/rcs-web/assets/chunk-AQP2D5EJ-CDNB1DxJ.js} +1 -1
- package/dist/rcs-web/assets/{chunk-FMBD7UC4-0lUT-961.js → chunk-FMBD7UC4-CUyVgVhv.js} +1 -1
- package/dist/rcs-web/assets/{chunk-ND2GUHAM-BWqVDbg4.js → chunk-ND2GUHAM-DWUadZ9h.js} +1 -1
- package/dist/rcs-web/assets/{chunk-QZHKN3VN-CfeMmsaw.js → chunk-QZHKN3VN-De-swXbY.js} +1 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DAE_PUq2.js +1 -0
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DAE_PUq2.js +1 -0
- package/dist/rcs-web/assets/{code-block-IT6T5CEO-FipRU7Gt.js → code-block-IT6T5CEO-DHPrRtQH.js} +1 -1
- package/dist/rcs-web/assets/{copy-RtDWH7m7.js → copy-CFPy3H8V.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-wlwIwiSf.js → dist/rcs-web/assets/cose-bilkent-S5V4N54A-CZjBoqHS.js} +1 -1
- package/dist/rcs-web/assets/{dagre-BM42HDAG-FlvB-WBQ.js → dagre-BM42HDAG-Cf5v7qFZ.js} +1 -1
- package/dist/rcs-web/assets/{diagram-2AECGRRQ-Dd5G25-Q.js → diagram-2AECGRRQ-C7UJVkwm.js} +1 -1
- package/dist/rcs-web/assets/{diagram-5GNKFQAL-CnS79Wiq.js → diagram-5GNKFQAL-DyOsGtm_.js} +1 -1
- package/dist/rcs-web/assets/{diagram-KO2AKTUF-oeffrVzV.js → diagram-KO2AKTUF-rj-dLm4C.js} +1 -1
- package/dist/rcs-web/assets/{diagram-LMA3HP47-Dc4rRllI.js → diagram-LMA3HP47-5IBISrVO.js} +1 -1
- package/dist/rcs-web/assets/{diagram-OG6HWLK6-QYKwztsm.js → diagram-OG6HWLK6-CvKsIOGI.js} +1 -1
- package/dist/rcs-web/assets/{dialog-C6bSop75.js → dialog-D3djNDCB.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-CFoDAbeH.js → dist/rcs-web/assets/erDiagram-TEJ5UH35-DN3O1WDD.js} +1 -1
- package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-zOHsjkHO.js → flowDiagram-I6XJVG4X-CXmRfzEy.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-DmdYR8vQ.js → dist/rcs-web/assets/ganttDiagram-6RSMTGT7-6uA2-PAt.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-ChNq0nxK.js → dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-DWYRvHtj.js} +1 -1
- package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-CTOfXwsH.js → infoDiagram-5YYISTIA-CJt4bepj.js} +1 -1
- package/dist/rcs-web/assets/{ishikawaDiagram-YF4QCWOH-AbFaqfWq.js → ishikawaDiagram-YF4QCWOH-DYHvIeSs.js} +1 -1
- package/dist/rcs-web/assets/{journeyDiagram-JHISSGLW-BZ5YDbY5.js → journeyDiagram-JHISSGLW-DWQeWDV-.js} +1 -1
- package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-2ujiDLTJ.js → kanban-definition-UN3LZRKU-D1vYCpGq.js} +1 -1
- package/dist/rcs-web/assets/{linear-hvc2NcTZ.js → linear-DEn8Cs7O.js} +1 -1
- package/dist/rcs-web/assets/{main-2KqxLOVo.js → main-COET8kmB.js} +3 -3
- package/{packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-CjE066pc.js → dist/rcs-web/assets/mermaid-VLURNSYL-DJIytlGH.js} +4 -4
- package/dist/rcs-web/assets/{mermaid.core-D0z5iBed.js → mermaid.core-DVQA7rXK.js} +5 -5
- 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
- package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-EaZYytph.js → pieDiagram-4H26LBE5-C86veflr.js} +1 -1
- package/dist/rcs-web/assets/{quadrantDiagram-W4KKPZXB-BbYaZQ_j.js → quadrantDiagram-W4KKPZXB-DJmcygzl.js} +1 -1
- package/dist/rcs-web/assets/{refresh-cw-2QNtciSF.js → refresh-cw-BRNwaL3w.js} +1 -1
- package/dist/rcs-web/assets/{requirementDiagram-4Y6WPE33-sQpG_uMR.js → requirementDiagram-4Y6WPE33-PDkq_ITC.js} +1 -1
- package/dist/rcs-web/assets/{sankeyDiagram-5OEKKPKP-Dk-ywMbO.js → sankeyDiagram-5OEKKPKP-DvCuhECf.js} +1 -1
- package/dist/rcs-web/assets/{sequenceDiagram-3UESZ5HK-B8kXKWV0.js → sequenceDiagram-3UESZ5HK-Co2LWujo.js} +1 -1
- package/dist/rcs-web/assets/{stateDiagram-AJRCARHV-BIjc-tAY.js → stateDiagram-AJRCARHV-CDTXzmhr.js} +1 -1
- package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-BjJyk52d.js → stateDiagram-v2-BHNVJYJU-Sdqiqtes.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-9Myr5rlZ.js → dist/rcs-web/assets/timeline-definition-PNZ67QCA-Cudtpim6.js} +1 -1
- package/dist/rcs-web/assets/{vennDiagram-CIIHVFJN-B_0p3XFw.js → vennDiagram-CIIHVFJN-B_84pCPM.js} +1 -1
- package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-JKVEgrM5.js → wardleyDiagram-YWT4CUSO-B_tneRWc.js} +1 -1
- package/dist/rcs-web/assets/{xychartDiagram-2RQKCTM6-DUPPleBK.js → xychartDiagram-2RQKCTM6-CNdStpy2.js} +1 -1
- package/dist/rcs-web/index.html +1 -1
- package/dist/vendor/archify/LICENSE +22 -0
- package/dist/vendor/archify/SKILL.md +137 -0
- package/dist/vendor/archify/THIRD_PARTY_NOTICES.md +69 -0
- package/dist/vendor/archify/assets/JetBrainsMono-OFL.txt +93 -0
- package/dist/vendor/archify/assets/template.html +14934 -0
- package/dist/vendor/archify/bin/archify.mjs +2687 -0
- package/dist/vendor/archify/bin/open-artifact.mjs +95 -0
- package/dist/vendor/archify/bin/preview.mjs +764 -0
- package/dist/vendor/archify/bin/visual-check.mjs +1012 -0
- package/dist/vendor/archify/brand-marks/README.md +31 -0
- package/dist/vendor/archify/brand-marks/catalog.json +131 -0
- package/dist/vendor/archify/delta/architecture-delta.mjs +1221 -0
- package/dist/vendor/archify/examples/agent-run.lifecycle.json +60 -0
- package/dist/vendor/archify/examples/agent-tool-call.workflow.json +94 -0
- package/dist/vendor/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/dist/vendor/archify/examples/brand-aware-delivery.architecture.json +47 -0
- package/dist/vendor/archify/examples/cache-miss-request.sequence.json +82 -0
- package/dist/vendor/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/dist/vendor/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/dist/vendor/archify/examples/dataflow-product-analytics.html +15045 -0
- package/dist/vendor/archify/examples/deployment-release.lifecycle.json +49 -0
- package/dist/vendor/archify/examples/event-stream.dataflow.json +57 -0
- package/dist/vendor/archify/examples/incident-response.workflow.json +64 -0
- package/dist/vendor/archify/examples/lifecycle-agent-run.html +14980 -0
- package/dist/vendor/archify/examples/product-analytics.dataflow.json +76 -0
- package/dist/vendor/archify/examples/production-deployment.architecture.json +71 -0
- package/dist/vendor/archify/examples/release-delivery.workflow.json +62 -0
- package/dist/vendor/archify/examples/sequence-cache-miss-request.html +15060 -0
- package/dist/vendor/archify/examples/web-app-rendered.html +15009 -0
- package/dist/vendor/archify/examples/web-app.architecture.json +46 -0
- package/dist/vendor/archify/examples/workflow-agent-tool-call-rendered.html +15051 -0
- package/dist/vendor/archify/migrations/workflow-v2.mjs +279 -0
- package/dist/vendor/archify/package.json +17 -0
- package/dist/vendor/archify/recipes/scenarios.mjs +391 -0
- package/dist/vendor/archify/references/authoring-contract.md +243 -0
- package/dist/vendor/archify/references/brand-marks.md +65 -0
- package/dist/vendor/archify/references/delivery-contract.md +120 -0
- package/dist/vendor/archify/references/viewer-runtime.md +45 -0
- package/dist/vendor/archify/renderers/architecture/grid.mjs +62 -0
- package/dist/vendor/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/dist/vendor/archify/renderers/dataflow/README.md +104 -0
- package/dist/vendor/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/dist/vendor/archify/renderers/lifecycle/README.md +115 -0
- package/dist/vendor/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/dist/vendor/archify/renderers/sequence/README.md +114 -0
- package/dist/vendor/archify/renderers/sequence/render-sequence.mjs +464 -0
- package/dist/vendor/archify/renderers/shared/brand-marks.mjs +563 -0
- package/dist/vendor/archify/renderers/shared/cli.mjs +218 -0
- package/dist/vendor/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/dist/vendor/archify/renderers/shared/diagnostics.mjs +127 -0
- package/dist/vendor/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/dist/vendor/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
- package/dist/vendor/archify/renderers/shared/generated-validators.mjs +13 -0
- package/dist/vendor/archify/renderers/shared/geometry.mjs +1423 -0
- package/dist/vendor/archify/renderers/shared/i18n.mjs +595 -0
- package/dist/vendor/archify/renderers/shared/layout-report.mjs +40 -0
- package/dist/vendor/archify/renderers/shared/legend.mjs +217 -0
- package/dist/vendor/archify/renderers/shared/output-path.mjs +340 -0
- package/dist/vendor/archify/renderers/shared/repository-evidence.mjs +238 -0
- package/dist/vendor/archify/renderers/shared/repository-location.mjs +58 -0
- package/dist/vendor/archify/renderers/shared/text-fit.mjs +49 -0
- package/dist/vendor/archify/renderers/shared/utils.mjs +232 -0
- package/dist/vendor/archify/renderers/shared/validator.mjs +86 -0
- package/dist/vendor/archify/renderers/workflow/README.md +223 -0
- package/dist/vendor/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/dist/vendor/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/dist/vendor/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/dist/vendor/archify/schemas/README.md +211 -0
- package/dist/vendor/archify/schemas/architecture.schema.json +178 -0
- package/dist/vendor/archify/schemas/common.schema.json +115 -0
- package/dist/vendor/archify/schemas/dataflow.schema.json +243 -0
- package/dist/vendor/archify/schemas/lifecycle.schema.json +266 -0
- package/dist/vendor/archify/schemas/sequence.schema.json +223 -0
- package/dist/vendor/archify/schemas/workflow.schema.json +428 -0
- package/dist/vendor/archify/scripts/check-render-output.mjs +836 -0
- package/dist/vendor/archify/scripts/check-update.mjs +1667 -0
- package/dist/vendor/archify/scripts/render-examples.mjs +26 -0
- package/dist/vendor/archify/scripts/update-contract.mjs +182 -0
- package/dist/vendor/archify/skill-release.json +10 -0
- package/package.json +1 -1
- package/packages/remote-control-server/src/__tests__/stuck-turn-watchdog.test.ts +43 -0
- package/packages/remote-control-server/src/__tests__/ws-handler.test.ts +169 -0
- package/packages/remote-control-server/src/services/transport.ts +5 -1
- package/packages/remote-control-server/src/transport/ws-handler.ts +38 -3
- package/packages/remote-control-server/web/dist/assets/{AdminPanel-CpzAO2vZ.js → AdminPanel-CAK-wqCu.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ArtifactView-CEyKbOJh.js → ArtifactView-DJxpXvlH.js} +1 -1
- package/{dist/rcs-web/assets/ArtifactsGallery-B_JcCYh1.js → packages/remote-control-server/web/dist/assets/ArtifactsGallery-CykyoUxk.js} +1 -1
- package/{dist/rcs-web/assets/Claim-CGxjGaui.js → packages/remote-control-server/web/dist/assets/Claim-DZQ8sfWt.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Dashboard-DCq-h_y9.js → Dashboard-Cm9ZAh-6.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Join-BM43XjA0.js → Join-D1X0Ji0b.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Login-CPx4Dc28.js → Login-lDaHrIa-.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Register-BV3xfUvd.js → Register-12ki3lPq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{SessionDetail-DgMDo7Ge.js → SessionDetail-BZjIjZKu.js} +23 -23
- package/packages/remote-control-server/web/dist/assets/{SessionVisibilityBadge-CvqFRTea.js → SessionVisibilityBadge-BkZImPBJ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Setup-GfWdRpvh.js → Setup-Cpyfr8Pi.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ShareLanding-BuEXTqqz.js → ShareLanding-Dh3_QdhD.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamCreate-DalKoyLy.js → TeamCreate-CZC2EjYw.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamDetail-DevkNiHQ.js → TeamDetail-umrDhcwG.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamList-B1pHxRaK.js → TeamList-CI_ppYJz.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamSettings-DWnEJMTx.js → TeamSettings-D_y3NFLr.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{UserSearchInput-DgktGnh2.js → UserSearchInput-BJTMnFdQ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{UserSettings-DPhvsn9k.js → UserSettings-m2SsR0jt.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{arc-C7foUDWz.js → arc-B-w-om5W.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-BzsYecpv.js → architectureDiagram-3BPJPVTR-A0JqD49y.js} +1 -1
- package/{dist/rcs-web/assets/blockDiagram-GPEHLZMM-D4BSEcZT.js → packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-CRmWH6Kh.js} +1 -1
- package/{dist/rcs-web/assets/c4Diagram-AAUBKEIU-CIap7aYJ.js → packages/remote-control-server/web/dist/assets/c4Diagram-AAUBKEIU-Dil5npJC.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/channel-BAxtMvz9.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-s9V4oCUf.js → chunk-2J33WTMH-B0U3olYO.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-CJrYwRaR.js → chunk-4BX2VUAB-D8eZOxCq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-D8swZDnP.js → chunk-55IACEB6-BCg1yqKV.js} +1 -1
- package/{dist/rcs-web/assets/chunk-727SXJPM-vJ6LjIbB.js → packages/remote-control-server/web/dist/assets/chunk-727SXJPM-C9GSmRyu.js} +1 -1
- package/{dist/rcs-web/assets/chunk-AQP2D5EJ-COrMlHZr.js → packages/remote-control-server/web/dist/assets/chunk-AQP2D5EJ-CDNB1DxJ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-0lUT-961.js → chunk-FMBD7UC4-CUyVgVhv.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-BWqVDbg4.js → chunk-ND2GUHAM-DWUadZ9h.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-CfeMmsaw.js → chunk-QZHKN3VN-De-swXbY.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DAE_PUq2.js +1 -0
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-DAE_PUq2.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-FipRU7Gt.js → code-block-IT6T5CEO-DHPrRtQH.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{copy-RtDWH7m7.js → copy-CFPy3H8V.js} +1 -1
- package/{dist/rcs-web/assets/cose-bilkent-S5V4N54A-wlwIwiSf.js → packages/remote-control-server/web/dist/assets/cose-bilkent-S5V4N54A-CZjBoqHS.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{dagre-BM42HDAG-FlvB-WBQ.js → dagre-BM42HDAG-Cf5v7qFZ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ-Dd5G25-Q.js → diagram-2AECGRRQ-C7UJVkwm.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-CnS79Wiq.js → diagram-5GNKFQAL-DyOsGtm_.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-oeffrVzV.js → diagram-KO2AKTUF-rj-dLm4C.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-Dc4rRllI.js → diagram-LMA3HP47-5IBISrVO.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-QYKwztsm.js → diagram-OG6HWLK6-CvKsIOGI.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{dialog-C6bSop75.js → dialog-D3djNDCB.js} +1 -1
- package/{dist/rcs-web/assets/erDiagram-TEJ5UH35-CFoDAbeH.js → packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-DN3O1WDD.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-zOHsjkHO.js → flowDiagram-I6XJVG4X-CXmRfzEy.js} +1 -1
- package/{dist/rcs-web/assets/ganttDiagram-6RSMTGT7-DmdYR8vQ.js → packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-6uA2-PAt.js} +1 -1
- package/{dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-ChNq0nxK.js → packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-DWYRvHtj.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-CTOfXwsH.js → infoDiagram-5YYISTIA-CJt4bepj.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ishikawaDiagram-YF4QCWOH-AbFaqfWq.js → ishikawaDiagram-YF4QCWOH-DYHvIeSs.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{journeyDiagram-JHISSGLW-BZ5YDbY5.js → journeyDiagram-JHISSGLW-DWQeWDV-.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-2ujiDLTJ.js → kanban-definition-UN3LZRKU-D1vYCpGq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{linear-hvc2NcTZ.js → linear-DEn8Cs7O.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{main-2KqxLOVo.js → main-COET8kmB.js} +3 -3
- package/{dist/rcs-web/assets/mermaid-VLURNSYL-CjE066pc.js → packages/remote-control-server/web/dist/assets/mermaid-VLURNSYL-DJIytlGH.js} +4 -4
- package/packages/remote-control-server/web/dist/assets/{mermaid.core-D0z5iBed.js → mermaid.core-DVQA7rXK.js} +5 -5
- 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
- package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-EaZYytph.js → pieDiagram-4H26LBE5-C86veflr.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{quadrantDiagram-W4KKPZXB-BbYaZQ_j.js → quadrantDiagram-W4KKPZXB-DJmcygzl.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{refresh-cw-2QNtciSF.js → refresh-cw-BRNwaL3w.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{requirementDiagram-4Y6WPE33-sQpG_uMR.js → requirementDiagram-4Y6WPE33-PDkq_ITC.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{sankeyDiagram-5OEKKPKP-Dk-ywMbO.js → sankeyDiagram-5OEKKPKP-DvCuhECf.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{sequenceDiagram-3UESZ5HK-B8kXKWV0.js → sequenceDiagram-3UESZ5HK-Co2LWujo.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{stateDiagram-AJRCARHV-BIjc-tAY.js → stateDiagram-AJRCARHV-CDTXzmhr.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-BjJyk52d.js → stateDiagram-v2-BHNVJYJU-Sdqiqtes.js} +1 -1
- package/{dist/rcs-web/assets/timeline-definition-PNZ67QCA-9Myr5rlZ.js → packages/remote-control-server/web/dist/assets/timeline-definition-PNZ67QCA-Cudtpim6.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{vennDiagram-CIIHVFJN-B_0p3XFw.js → vennDiagram-CIIHVFJN-B_84pCPM.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-JKVEgrM5.js → wardleyDiagram-YWT4CUSO-B_tneRWc.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{xychartDiagram-2RQKCTM6-DUPPleBK.js → xychartDiagram-2RQKCTM6-CNdStpy2.js} +1 -1
- package/packages/remote-control-server/web/dist/index.html +1 -1
- package/dist/rcs-web/assets/channel-69qfoCOr.js +0 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-DihFTUAb.js +0 -1
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-DihFTUAb.js +0 -1
- package/packages/remote-control-server/web/dist/assets/channel-69qfoCOr.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-DihFTUAb.js +0 -1
- 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
|
@@ -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 =>
|
|
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)
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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.
|