agentworkshop 0.8.1 → 0.8.3
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/.output/.AgentWorkShop/aml-python/train-example.py +92 -92
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{BCLUwdP52.js → 39W1CH-l2.js} +1 -1
- package/.output/public/_nuxt/7xbYPfY6.js +1 -0
- package/.output/public/_nuxt/{BfvuWqSa.js → ATAvN55g.js} +1 -1
- package/.output/public/_nuxt/{B2NbzUau2.js → B3eCVqcT2.js} +1 -1
- package/.output/public/_nuxt/{DuUc4bbY2.js → B9qIhT7k2.js} +1 -1
- package/.output/public/_nuxt/{BkEokGX5.js → BE9oKpOt.js} +1 -1
- package/.output/public/_nuxt/{D_59BNP1.js → Bbk1XCCM.js} +3 -3
- package/.output/public/_nuxt/{Dz9C2pTa.js → CMzExk8F.js} +1 -1
- package/.output/public/_nuxt/{dHwWyr6b.js → CT4bi_Y4.js} +1 -1
- package/.output/public/_nuxt/{26OL4Ao82.js → CeCSjB9O2.js} +1 -1
- package/.output/public/_nuxt/{Dyxf2xZw.js → Cot5VNae.js} +1 -1
- package/.output/public/_nuxt/{BVg2R2VB2.js → Crf8_Ad02.js} +1 -1
- package/.output/public/_nuxt/{rDvMijKA.js → D9tNM-1a.js} +2 -2
- package/.output/public/_nuxt/{YAA98rWJ.js → DAug2CPf.js} +7 -7
- package/.output/public/_nuxt/{CQSxS_Ek.js → DbhTN7-T.js} +1 -1
- package/.output/public/_nuxt/DgGzwjAr2.js +2 -0
- package/.output/public/_nuxt/DkRozlDP2.js +1 -0
- package/.output/public/_nuxt/{DGu_fna7.js → DoChWkff.js} +1 -1
- package/.output/public/_nuxt/{Byiiiwc72.js → DxH5focQ2.js} +1 -1
- package/.output/public/_nuxt/Dyr3LPGL.js +1 -0
- package/.output/public/_nuxt/{CC2Pv8VL2.js → MC_i34H42.js} +1 -1
- package/.output/public/_nuxt/OmpTerminalPanel.DMWgGwDs.css +1 -0
- package/.output/public/_nuxt/PluginSlot.BqBzLD4T.css +1 -0
- package/.output/public/_nuxt/TownView.Cn8SPG7S.css +1 -0
- package/.output/public/_nuxt/{CmuGMxDP.js → TugRY_4O.js} +1 -1
- package/.output/public/_nuxt/{BPUQZ9Lq2.js → WybiLTow2.js} +1 -1
- package/.output/public/_nuxt/{BaYDgyaR.js → Zn0BZpf0.js} +3 -3
- package/.output/public/_nuxt/{_id_.BQRWK7J2.css → _id_.Be5JaH-P.css} +1 -1
- package/.output/public/_nuxt/{_wsId_.DCnKQQdY.css → _wsId_.p_vAYtTp.css} +1 -1
- package/.output/public/_nuxt/{agents.D-JPovTZ.css → agents.CRomddYR.css} +1 -1
- package/.output/public/_nuxt/aml.DgOMpDpv.css +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/fd0033e4-1eaa-42f8-9a04-3132717a703b.json +1 -0
- package/.output/public/_nuxt/{default.BEXGWZFQ.css → default.CpAx70gC.css} +1 -1
- package/.output/public/_nuxt/{logs.BkJPbR_K.css → logs.DcSvz6vi.css} +1 -1
- package/.output/public/_nuxt/{monitor.D3yEqqrv.css → monitor.OoNTwfMJ.css} +1 -1
- package/.output/public/_nuxt/{ontology.B_3Wn907.css → ontology.JqJ6PjV1.css} +1 -1
- package/.output/public/_nuxt/{operations.-l6u44Ar.css → operations.C48ggFa5.css} +1 -1
- package/.output/public/_nuxt/{pages.Cdpm_B-G.css → pages.Dpa28tJW.css} +1 -1
- package/.output/public/_nuxt/permissions.CrV-4t-6.css +1 -0
- package/.output/public/_nuxt/{BfeXib9G.js → rcdmiszh2.js} +1 -1
- package/.output/public/_nuxt/schedules.DYWOjGHm.css +1 -0
- package/.output/public/_nuxt/{teams.CLQaXno5.css → teams.DEJoJ4QV.css} +1 -1
- package/.output/public/_nuxt/{tokens.BDSUWF-L.css → tokens.DKZWCP5v.css} +1 -1
- package/.output/public/_nuxt/tools.DP-nsTli.css +1 -0
- package/.output/public/_nuxt/wK6Pp4Zc2.js +2 -0
- package/.output/public/_nuxt/{workshop.BBiFhXuM.css → workshop.PT1xhP8C.css} +1 -1
- package/.output/public/favicon.svg +14 -14
- package/.output/public/robots.txt +3 -3
- package/.output/server/chunks/_/LeftOutlined.mjs.map +1 -1
- package/.output/server/chunks/_/RightOutlined.mjs.map +1 -1
- package/.output/server/chunks/_/SearchOutlined.mjs +1230 -1261
- package/.output/server/chunks/_/SearchOutlined.mjs.map +1 -1
- package/.output/server/chunks/_/error-500.mjs.map +1 -1
- package/.output/server/chunks/_/nitro.mjs +3308 -3389
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs +704 -0
- package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs.map +1 -0
- package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs +77 -0
- package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs.map +1 -0
- package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs +889 -0
- package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs.map +1 -0
- package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs +131 -0
- package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs.map +1 -0
- package/.output/server/chunks/build/TownView-CUbzOT_M.mjs +5960 -0
- package/.output/server/chunks/build/TownView-CUbzOT_M.mjs.map +1 -0
- package/.output/server/chunks/build/_id_-BHWZiRQZ.mjs +373 -0
- package/.output/server/chunks/build/_id_-BHWZiRQZ.mjs.map +1 -0
- package/.output/server/chunks/build/_id_-JaGx0yBE.mjs +1922 -0
- package/.output/server/chunks/build/_id_-JaGx0yBE.mjs.map +1 -0
- package/.output/server/chunks/build/_wsId_-C4DKkEqv.mjs +13707 -0
- package/.output/server/chunks/build/_wsId_-C4DKkEqv.mjs.map +1 -0
- package/.output/server/chunks/build/agents-DRod4lTC.mjs +1047 -0
- package/.output/server/chunks/build/agents-DRod4lTC.mjs.map +1 -0
- package/.output/server/chunks/build/alert-CNGhs--Y.mjs +260 -0
- package/.output/server/chunks/build/alert-CNGhs--Y.mjs.map +1 -0
- package/.output/server/chunks/build/aml-B3Umz4DR.mjs +729 -0
- package/.output/server/chunks/build/aml-B3Umz4DR.mjs.map +1 -0
- package/.output/server/chunks/build/analysis-tNpFLtMt.mjs +502 -0
- package/.output/server/chunks/build/analysis-tNpFLtMt.mjs.map +1 -0
- package/.output/server/chunks/build/{api-B4Om0mEc.mjs → api-D-zkgkj-.mjs} +8 -10
- package/.output/server/chunks/build/api-D-zkgkj-.mjs.map +1 -0
- package/.output/server/chunks/build/{api-BsAgXWxi.mjs → api-D3gy2e2q.mjs} +22 -24
- package/.output/server/chunks/build/api-D3gy2e2q.mjs.map +1 -0
- package/.output/server/chunks/build/{api-BEW_ebY_.mjs → api-bn4OKkl_.mjs} +17 -19
- package/.output/server/chunks/build/api-bn4OKkl_.mjs.map +1 -0
- package/.output/server/chunks/build/api-error-CnW_xiNI.mjs +46 -0
- package/.output/server/chunks/build/api-error-CnW_xiNI.mjs.map +1 -0
- package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs +70 -0
- package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs.map +1 -0
- package/.output/server/chunks/build/board-B2oYXGBy.mjs +172 -0
- package/.output/server/chunks/build/board-B2oYXGBy.mjs.map +1 -0
- package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +81 -94
- package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -1
- package/.output/server/chunks/build/card-BECE6y_G.mjs +922 -0
- package/.output/server/chunks/build/card-BECE6y_G.mjs.map +1 -0
- package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs +950 -0
- package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs.map +1 -0
- package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs +113 -112
- package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs.map +1 -1
- package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs +429 -0
- package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs.map +1 -0
- package/.output/server/chunks/build/client-only-S7k53PIm.mjs +42 -0
- package/.output/server/chunks/build/client-only-S7k53PIm.mjs.map +1 -0
- package/.output/server/chunks/build/constants-HPHJvjne.mjs +65 -75
- package/.output/server/chunks/build/constants-HPHJvjne.mjs.map +1 -1
- package/.output/server/chunks/build/core-CRlsQhzd.mjs +292 -0
- package/.output/server/chunks/build/core-CRlsQhzd.mjs.map +1 -0
- package/.output/server/chunks/build/daq-DHsYtWC-.mjs +1210 -0
- package/.output/server/chunks/build/daq-DHsYtWC-.mjs.map +1 -0
- package/.output/server/chunks/build/data-Cl4wRZO6.mjs +459 -0
- package/.output/server/chunks/build/data-Cl4wRZO6.mjs.map +1 -0
- package/.output/server/chunks/build/dcw-DnjOM6p1.mjs +467 -0
- package/.output/server/chunks/build/dcw-DnjOM6p1.mjs.map +1 -0
- package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs +3 -15
- package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs.map +1 -1
- package/.output/server/chunks/build/default-DDRKP2Mb.mjs +2246 -0
- package/.output/server/chunks/build/default-DDRKP2Mb.mjs.map +1 -0
- package/.output/server/chunks/build/descriptions-B3uhDesi.mjs +401 -0
- package/.output/server/chunks/build/descriptions-B3uhDesi.mjs.map +1 -0
- package/.output/server/chunks/build/drawer-DwXxapMg.mjs +822 -0
- package/.output/server/chunks/build/drawer-DwXxapMg.mjs.map +1 -0
- package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs +12 -0
- package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs.map +1 -0
- package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs +530 -0
- package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs.map +1 -0
- package/.output/server/chunks/build/{es-Bxu10NJ2.mjs → es-DXSEkmAm.mjs} +1 -2
- package/.output/server/chunks/build/es-DXSEkmAm.mjs.map +1 -0
- package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs +2082 -0
- package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs.map +1 -0
- package/.output/server/chunks/build/form-Cw2Ex9w5.mjs +3543 -0
- package/.output/server/chunks/build/form-Cw2Ex9w5.mjs.map +1 -0
- package/.output/server/chunks/build/hasIn-RYRGomyg.mjs +192 -0
- package/.output/server/chunks/build/hasIn-RYRGomyg.mjs.map +1 -0
- package/.output/server/chunks/build/hitl-B4cHRlkC.mjs +120 -0
- package/.output/server/chunks/build/hitl-B4cHRlkC.mjs.map +1 -0
- package/.output/server/chunks/build/input-CJgB-RL6.mjs +1705 -0
- package/.output/server/chunks/build/input-CJgB-RL6.mjs.map +1 -0
- package/.output/server/chunks/build/input-number-CQKL42p_.mjs +1027 -0
- package/.output/server/chunks/build/input-number-CQKL42p_.mjs.map +1 -0
- package/.output/server/chunks/build/interval-DiAUqODq.mjs +8 -0
- package/.output/server/chunks/build/interval-DiAUqODq.mjs.map +1 -0
- package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs +6 -0
- package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs.map +1 -0
- package/.output/server/chunks/build/logs-C4vKFkHQ.mjs +381 -0
- package/.output/server/chunks/build/logs-C4vKFkHQ.mjs.map +1 -0
- package/.output/server/chunks/build/menu-xO8ocVtL.mjs +1833 -0
- package/.output/server/chunks/build/menu-xO8ocVtL.mjs.map +1 -0
- package/.output/server/chunks/build/monitor-BNrG6v3b.mjs +2216 -0
- package/.output/server/chunks/build/monitor-BNrG6v3b.mjs.map +1 -0
- package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs +0 -2
- package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs.map +1 -1
- package/.output/server/chunks/build/ontology-B_0Vm6j-.mjs +1416 -0
- package/.output/server/chunks/build/ontology-B_0Vm6j-.mjs.map +1 -0
- package/.output/server/chunks/build/operations-D8D6-Jm-.mjs +278 -0
- package/.output/server/chunks/build/operations-D8D6-Jm-.mjs.map +1 -0
- package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs +202 -0
- package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs.map +1 -0
- package/.output/server/chunks/build/pages-Dac4icQC.mjs +439 -0
- package/.output/server/chunks/build/pages-Dac4icQC.mjs.map +1 -0
- package/.output/server/chunks/build/pagination-BTzq7dD5.mjs +1330 -0
- package/.output/server/chunks/build/pagination-BTzq7dD5.mjs.map +1 -0
- package/.output/server/chunks/build/permissions-qmimwB0M.mjs +649 -0
- package/.output/server/chunks/build/permissions-qmimwB0M.mjs.map +1 -0
- package/.output/server/chunks/build/plugins-Dh_goy-k.mjs +269 -0
- package/.output/server/chunks/build/plugins-Dh_goy-k.mjs.map +1 -0
- package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs +333 -0
- package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs.map +1 -0
- package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs +77 -0
- package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs.map +1 -0
- package/.output/server/chunks/build/schedules-C2_x38gj.mjs +7039 -0
- package/.output/server/chunks/build/schedules-C2_x38gj.mjs.map +1 -0
- package/.output/server/chunks/build/segmented-29uEKZ3D.mjs +332 -0
- package/.output/server/chunks/build/segmented-29uEKZ3D.mjs.map +1 -0
- package/.output/server/chunks/build/select-CJb2XrQf.mjs +3734 -0
- package/.output/server/chunks/build/select-CJb2XrQf.mjs.map +1 -0
- package/.output/server/chunks/build/settings-Cz2Plds0.mjs +944 -0
- package/.output/server/chunks/build/settings-Cz2Plds0.mjs.map +1 -0
- package/.output/server/chunks/build/space-BByD-mFE.mjs +107 -0
- package/.output/server/chunks/build/space-BByD-mFE.mjs.map +1 -0
- package/.output/server/chunks/build/spin-XhbgGeLP.mjs +313 -0
- package/.output/server/chunks/build/spin-XhbgGeLP.mjs.map +1 -0
- package/.output/server/chunks/build/studio-CwYXl00G.mjs +329 -0
- package/.output/server/chunks/build/studio-CwYXl00G.mjs.map +1 -0
- package/.output/server/chunks/build/switch-DWcwVFxW.mjs +374 -0
- package/.output/server/chunks/build/switch-DWcwVFxW.mjs.map +1 -0
- package/.output/server/chunks/build/table-Zhuo7Fq-.mjs +7249 -0
- package/.output/server/chunks/build/table-Zhuo7Fq-.mjs.map +1 -0
- package/.output/server/chunks/build/tabs-BCwBXjNt.mjs +1838 -0
- package/.output/server/chunks/build/tabs-BCwBXjNt.mjs.map +1 -0
- package/.output/server/chunks/build/tag-CRW-anwy.mjs +1010 -0
- package/.output/server/chunks/build/tag-CRW-anwy.mjs.map +1 -0
- package/.output/server/chunks/build/teams-CwhFdcYn.mjs +1160 -0
- package/.output/server/chunks/build/teams-CwhFdcYn.mjs.map +1 -0
- package/.output/server/chunks/build/tokens-C5ODO1HA.mjs +992 -0
- package/.output/server/chunks/build/tokens-C5ODO1HA.mjs.map +1 -0
- package/.output/server/chunks/build/tools-C0YKragH.mjs +487 -0
- package/.output/server/chunks/build/tools-C0YKragH.mjs.map +1 -0
- package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs +888 -0
- package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs.map +1 -0
- package/.output/server/chunks/build/town-BV-hbwb5.mjs +16 -29
- package/.output/server/chunks/build/town-BV-hbwb5.mjs.map +1 -1
- package/.output/server/chunks/build/town-LkDwWnKA.mjs +117 -0
- package/.output/server/chunks/build/town-LkDwWnKA.mjs.map +1 -0
- package/.output/server/chunks/build/types-D6J7slEa.mjs.map +1 -1
- package/.output/server/chunks/build/types-DWqIeMRP.mjs +28 -29
- package/.output/server/chunks/build/types-DWqIeMRP.mjs.map +1 -1
- package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs +120 -0
- package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs.map +1 -0
- package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs +71 -0
- package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs.map +1 -0
- package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs +16 -23
- package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs.map +1 -1
- package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs +112 -0
- package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs.map +1 -0
- package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs +140 -0
- package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs +88 -0
- package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs +79 -0
- package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs +188 -0
- package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs +86 -0
- package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs +32 -37
- package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs.map +1 -1
- package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs +251 -0
- package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs +90 -0
- package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs +80 -0
- package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs.map +1 -0
- package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs +126 -0
- package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs.map +1 -0
- package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs +120 -0
- package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqAddNode-CRorxgOY.mjs +141 -0
- package/.output/server/chunks/build/useDaqAddNode-CRorxgOY.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqDetailBinding-Ck-YUW9J.mjs +72 -0
- package/.output/server/chunks/build/useDaqDetailBinding-Ck-YUW9J.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqDetailFrames-CLMoreaz.mjs +78 -0
- package/.output/server/chunks/build/useDaqDetailFrames-CLMoreaz.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqDetailHistory-BVNQXwC_.mjs +166 -0
- package/.output/server/chunks/build/useDaqDetailHistory-BVNQXwC_.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqDetailNode-BC0e9OfX.mjs +103 -0
- package/.output/server/chunks/build/useDaqDetailNode-BC0e9OfX.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqDetailParams-D173iwFg.mjs +157 -0
- package/.output/server/chunks/build/useDaqDetailParams-D173iwFg.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqFilters-CC-o_21d.mjs +224 -0
- package/.output/server/chunks/build/useDaqFilters-CC-o_21d.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs +43 -44
- package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs.map +1 -1
- package/.output/server/chunks/build/useDaqOptimizations-4vK2w1yn.mjs +132 -0
- package/.output/server/chunks/build/useDaqOptimizations-4vK2w1yn.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqStream-BHKpSJFd.mjs +385 -0
- package/.output/server/chunks/build/useDaqStream-BHKpSJFd.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqTemplates-CsXSc7yI.mjs +181 -0
- package/.output/server/chunks/build/useDaqTemplates-CsXSc7yI.mjs.map +1 -0
- package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs +312 -310
- package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs.map +1 -1
- package/.output/server/chunks/build/useDashboardData-DuKjuJTz.mjs +139 -0
- package/.output/server/chunks/build/useDashboardData-DuKjuJTz.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwAddNode-C5DcxsHF.mjs +217 -0
- package/.output/server/chunks/build/useDcwAddNode-C5DcxsHF.mjs.map +1 -0
- package/.output/server/chunks/build/{useDcwCards-SaiImIYQ.mjs → useDcwCards-0bAVo6uB.mjs} +20 -23
- package/.output/server/chunks/build/useDcwCards-0bAVo6uB.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwDetailScope-BNFOlt2v.mjs +184 -0
- package/.output/server/chunks/build/useDcwDetailScope-BNFOlt2v.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwDetailTemplates-DSH-o0tE.mjs +143 -0
- package/.output/server/chunks/build/useDcwDetailTemplates-DSH-o0tE.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwFilter-W61BFUcT.mjs +65 -0
- package/.output/server/chunks/build/useDcwFilter-W61BFUcT.mjs.map +1 -0
- package/.output/server/chunks/build/{useDcwLedger-0ie-0WTc.mjs → useDcwLedger-DsColLdc.mjs} +29 -35
- package/.output/server/chunks/build/useDcwLedger-DsColLdc.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwLineMutations-Cx4Ir7g3.mjs +133 -0
- package/.output/server/chunks/build/useDcwLineMutations-Cx4Ir7g3.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwLineRun-DQ0vB08z.mjs +100 -0
- package/.output/server/chunks/build/useDcwLineRun-DQ0vB08z.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwParamApprovals-CYspRuDk.mjs +119 -0
- package/.output/server/chunks/build/useDcwParamApprovals-CYspRuDk.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwProducts-CTbm_5S_.mjs +88 -0
- package/.output/server/chunks/build/useDcwProducts-CTbm_5S_.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwQuery-E0yjZs7G.mjs +93 -0
- package/.output/server/chunks/build/useDcwQuery-E0yjZs7G.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwQuickActions-BvT5VFOY.mjs +84 -0
- package/.output/server/chunks/build/useDcwQuickActions-BvT5VFOY.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwRecipes-zngShyk0.mjs +263 -0
- package/.output/server/chunks/build/useDcwRecipes-zngShyk0.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwStream-82IdjJKk.mjs +455 -0
- package/.output/server/chunks/build/useDcwStream-82IdjJKk.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwTemplates-CpHrcnvJ.mjs +87 -0
- package/.output/server/chunks/build/useDcwTemplates-CpHrcnvJ.mjs.map +1 -0
- package/.output/server/chunks/build/useDcwWrites-BlOhljp9.mjs +136 -0
- package/.output/server/chunks/build/useDcwWrites-BlOhljp9.mjs.map +1 -0
- package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs +118 -0
- package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs.map +1 -0
- package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs +104 -0
- package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs.map +1 -0
- package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs +52 -0
- package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs.map +1 -0
- package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs +30 -33
- package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs.map +1 -1
- package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs +80 -0
- package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs.map +1 -0
- package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs +136 -0
- package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs.map +1 -0
- package/.output/server/chunks/build/useLogsScope-BRyy550Y.mjs +75 -0
- package/.output/server/chunks/build/useLogsScope-BRyy550Y.mjs.map +1 -0
- package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs +155 -166
- package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs.map +1 -1
- package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs +128 -0
- package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs.map +1 -0
- package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs +77 -0
- package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs.map +1 -0
- package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs +20 -27
- package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs.map +1 -1
- package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs +182 -0
- package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs.map +1 -0
- package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs +139 -0
- package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs.map +1 -0
- package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs +146 -0
- package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs.map +1 -0
- package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs +23 -39
- package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs.map +1 -1
- package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs +71 -0
- package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs.map +1 -0
- package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs +78 -0
- package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs.map +1 -0
- package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs +91 -0
- package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs.map +1 -0
- package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs +76 -0
- package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs.map +1 -0
- package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs +31 -38
- package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs.map +1 -1
- package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs +99 -0
- package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs.map +1 -0
- package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs +124 -0
- package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs.map +1 -0
- package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs +21 -28
- package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs.map +1 -1
- package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs +106 -0
- package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs.map +1 -0
- package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs +81 -0
- package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs.map +1 -0
- package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs +108 -0
- package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs.map +1 -0
- package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs +86 -0
- package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs.map +1 -0
- package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs +16 -17
- package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs.map +1 -1
- package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs +131 -0
- package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs +128 -0
- package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs +118 -0
- package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs +1577 -0
- package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs.map +1 -0
- package/.output/server/chunks/build/{useWorkspaceAuth-Dlvj9csD.mjs → useWorkspaceAuth-TahC9EC7.mjs} +4 -16
- package/.output/server/chunks/build/useWorkspaceAuth-TahC9EC7.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs +94 -0
- package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs +30 -33
- package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs.map +1 -1
- package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs +150 -0
- package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs.map +1 -0
- package/.output/server/chunks/build/users-pVCK50z-.mjs +566 -0
- package/.output/server/chunks/build/users-pVCK50z-.mjs.map +1 -0
- package/.output/server/chunks/build/workshop-DAgsBgG4.mjs +499 -0
- package/.output/server/chunks/build/workshop-DAgsBgG4.mjs.map +1 -0
- package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs +111 -121
- package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs.map +1 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +4 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
- package/.output/server/chunks/routes/renderer.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs.map +1 -1
- package/.output/server/chunks/virtual/entry.mjs +9357 -10721
- package/.output/server/chunks/virtual/entry.mjs.map +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs.map +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +2 -2
- package/README.md +3 -3
- package/app/components/AwLogo.vue +75 -75
- package/app/components/aml/AmlDatasetFormModal.vue +279 -279
- package/app/components/aml/AmlDatasetTable.vue +319 -319
- package/app/components/aml/AmlExperimentsTable.vue +142 -142
- package/app/components/aml/AmlInfraBanner.vue +23 -23
- package/app/components/aml/AmlJobsTable.vue +248 -248
- package/app/components/aml/AmlOverviewBar.vue +62 -62
- package/app/components/aml/AmlPageHeader.vue +47 -47
- package/app/components/aml/AmlPredictConsole.vue +201 -201
- package/app/components/app-header/HitlBell.vue +423 -423
- package/app/components/daq/DaqAddNodeModal.vue +209 -209
- package/app/components/daq/DaqAlarmBar.vue +46 -46
- package/app/components/daq/DaqControlCard.vue +159 -159
- package/app/components/daq/DaqInfraBanner.vue +31 -31
- package/app/components/daq/DaqLineBanner.vue +47 -47
- package/app/components/daq/DaqNodePanel.vue +396 -396
- package/app/components/daq/DaqOptPanel.vue +197 -197
- package/app/components/daq/DaqTemplateModal.vue +246 -246
- package/app/components/dashboard/DashboardGaugeBand.vue +78 -78
- package/app/components/dashboard/DashboardHero.vue +209 -209
- package/app/components/dashboard/DashboardLineStatePanel.vue +78 -78
- package/app/components/dashboard/DashboardNodeStatePanel.vue +46 -46
- package/app/components/dashboard/DashboardPipelinePanel.vue +46 -46
- package/app/components/dashboard/DashboardTrendPanel.vue +83 -83
- package/app/components/dashboard/DashboardWritePanel.vue +52 -52
- package/app/components/dcw/DcwCreateLineModal.vue +105 -105
- package/app/components/dcw/DcwDeleteLineModal.vue +73 -73
- package/app/components/dcw/DcwDetailTemplateModal.vue +238 -238
- package/app/components/dcw/DcwLedgerCard.vue +160 -160
- package/app/components/dcw/DcwMesArtifacts.vue +140 -140
- package/app/components/dcw/DcwProductCreateModal.vue +113 -113
- package/app/components/dcw/DcwRecipeDispatchHistoryModal.vue +244 -244
- package/app/components/dcw/DcwRecipeEditModal.vue +399 -399
- package/app/components/dcw/DcwRecipeHistoryModal.vue +165 -165
- package/app/components/dcw/DcwRunDataModal.vue +191 -191
- package/app/components/dcw/DcwTemplateModal.vue +227 -227
- package/app/components/dcw/DcwWriteHistoryCard.vue +96 -96
- package/app/components/dcw/ExpConfirmCard.vue +103 -103
- package/app/components/dcw/RecipeDispatchApprovalCard.vue +330 -330
- package/app/components/logs/LogsPageHead.vue +71 -71
- package/app/components/monitor/MonitorAgentTable.vue +143 -143
- package/app/components/monitor/MonitorChannelTable.vue +80 -80
- package/app/components/monitor/MonitorLoginGate.vue +24 -24
- package/app/components/monitor/MonitorPageHead.vue +92 -92
- package/app/components/monitor/MonitorProcessTable.vue +159 -159
- package/app/components/ontology/OntologyGraph.vue +356 -356
- package/app/components/operations/OperationsFilterCard.vue +164 -164
- package/app/components/operations/OperationsPageHead.vue +47 -47
- package/app/components/tokens/TokenCreateModal.vue +42 -42
- package/app/components/tokens/TokenOnceModal.vue +164 -164
- package/app/components/tokens/TokenRenameModal.vue +40 -40
- package/app/components/tokens/TokensPageHead.vue +76 -76
- package/app/components/workshop/A2aRpcDebugger.vue +237 -237
- package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
- package/app/components/workshop/AgentLanesView.vue +278 -278
- package/app/components/workshop/ArtifactCard.vue +120 -120
- package/app/components/workshop/AssetLibrary.vue +452 -452
- package/app/components/workshop/ChatMemberPanel.vue +556 -556
- package/app/components/workshop/CommandPalette.vue +270 -270
- package/app/components/workshop/Composer.vue +540 -540
- package/app/components/workshop/DaqTemplateIcon.vue +33 -33
- package/app/components/workshop/DeviceTwinPanel.vue +167 -167
- package/app/components/workshop/FileSelectorModal.vue +188 -188
- package/app/components/workshop/InspectorPanel.vue +301 -301
- package/app/components/workshop/PluginSlot.vue +120 -120
- package/app/components/workshop/TranscriptTimeline.vue +223 -223
- package/app/components/workshop/agents/AgentTemplateEditModal.vue +139 -139
- package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
- package/app/components/workshop/blocks/ClusterError.vue +85 -85
- package/app/components/workshop/blocks/ClusterLife.vue +87 -87
- package/app/components/workshop/blocks/ClusterMember.vue +95 -95
- package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
- package/app/components/workshop/blocks/ClusterOther.vue +67 -67
- package/app/components/workshop/blocks/ClusterStatus.vue +149 -149
- package/app/components/workshop/blocks/ClusterTool.vue +176 -176
- package/app/components/workshop/blocks/EventBlockAvatar.vue +114 -114
- package/app/components/workshop/blocks/EventBlockHead.vue +232 -232
- package/app/components/workshop/composer/ComposerToolbar.vue +278 -278
- package/app/components/workshop/composer/MentionMenu.vue +135 -135
- package/app/components/workshop/composer/ReplyChip.vue +65 -65
- package/app/components/workshop/composer/StatusChip.vue +171 -171
- package/app/components/workshop/console/Dock.vue +71 -71
- package/app/components/workshop/console/LeftPane.vue +84 -84
- package/app/components/workshop/device-twin/DeviceTwinCard.vue +265 -265
- package/app/components/workshop/device-twin/DeviceTwinDcwSection.vue +203 -203
- package/app/components/workshop/lanes/AddMemberModal.vue +270 -270
- package/app/components/workshop/lanes/EditMemberModal.vue +106 -106
- package/app/components/workshop/lanes/LanesToolbar.vue +97 -97
- package/app/components/workshop/session-list/ChannelSettingsModal.vue +3 -3
- package/app/components/workshop/session-list/MountChannelModal.vue +124 -124
- package/app/components/workshop/session-list/SaveTemplateModal.vue +93 -93
- package/app/components/workshop/task-board/Card.vue +172 -172
- package/app/components/workshop/task-board/Column.vue +151 -151
- package/app/components/workshop/task-board/List.vue +157 -157
- package/app/components/workshop/task-board/StatusMenu.vue +88 -88
- package/app/components/workshop/teams/TeamAddMemberModal.vue +53 -53
- package/app/components/workshop/teams/TeamCreateModal.vue +94 -94
- package/app/components/workshop/teams/TeamDeployModal.vue +40 -40
- package/app/components/workshop/teams/TeamPluginModal.vue +119 -119
- package/app/components/workshop/terminal/OmpTerminalPanel.vue +270 -270
- package/app/components/workshop/terminal/TerminalHitlCard.vue +170 -170
- package/app/components/workshop/town/TownScene.ts +466 -466
- package/app/components/workshop/town/TownView.vue +561 -561
- package/app/components/workshop/town/components/AutoModeConfirmModal.vue +94 -94
- package/app/components/workshop/town/components/TownAgentBindings.vue +405 -405
- package/app/components/workshop/town/components/TownAgentInspector.vue +554 -554
- package/app/components/workshop/town/components/TownAlarmList.vue +147 -147
- package/app/components/workshop/town/components/TownBoundaryPanel.vue +350 -350
- package/app/components/workshop/town/components/TownCalloutLayer.vue +147 -147
- package/app/components/workshop/town/components/TownChannelDock.vue +116 -116
- package/app/components/workshop/town/components/TownControlDock.vue +405 -405
- package/app/components/workshop/town/components/TownDaqNodeInspector.vue +345 -345
- package/app/components/workshop/town/components/TownDaqTree.vue +366 -366
- package/app/components/workshop/town/components/TownDcwBindSection.vue +473 -473
- package/app/components/workshop/town/components/TownDcwNodeInspector.vue +185 -185
- package/app/components/workshop/town/components/TownDcwTree.vue +280 -280
- package/app/components/workshop/town/components/TownDeviceBindings.vue +394 -394
- package/app/components/workshop/town/components/TownDeviceTransform.vue +248 -248
- package/app/components/workshop/town/components/TownEventList.vue +120 -120
- package/app/components/workshop/town/components/TownHealthBody.vue +100 -100
- package/app/components/workshop/town/components/TownKpiStrip.vue +207 -207
- package/app/components/workshop/town/components/TownLeftRail.vue +308 -308
- package/app/components/workshop/town/components/TownLoadingMask.vue +61 -61
- package/app/components/workshop/town/components/TownNavMap.vue +154 -154
- package/app/components/workshop/town/components/TownRightRail.vue +543 -543
- package/app/components/workshop/town/components/TownStage.vue +281 -281
- package/app/components/workshop/town/components/TownStageTop.vue +238 -238
- package/app/components/workshop/town/components/TownStatusBar.vue +108 -108
- package/app/components/workshop/town/components/TownTopNav.vue +367 -367
- package/app/components/workshop/town/components/TownTrendDock.vue +178 -178
- package/app/components/workshop/town/scene/town-scene-agents.ts +254 -254
- package/app/components/workshop/town/scene/town-scene-behavior.ts +194 -194
- package/app/components/workshop/town/scene/town-scene-bubbles.ts +96 -96
- package/app/components/workshop/town/scene/town-scene-core.ts +158 -158
- package/app/components/workshop/town/scene/town-scene-models.ts +109 -109
- package/app/components/workshop/town/scene/town-scene-visuals.ts +279 -279
- package/app/components/workshop/town/scene/town-scene3d-agents.ts +308 -308
- package/app/components/workshop/town/scene/town-scene3d-blocks.ts +297 -297
- package/app/components/workshop/town/scene/town-scene3d-bubbles.ts +281 -281
- package/app/components/workshop/town/scene/town-scene3d-camera.ts +282 -282
- package/app/components/workshop/town/scene/town-scene3d-devices.ts +433 -433
- package/app/components/workshop/town/scene/town-scene3d-editing.ts +490 -490
- package/app/components/workshop/town/scene/town-scene3d-events.ts +173 -173
- package/app/components/workshop/town/scene/town-scene3d-factory.ts +412 -412
- package/app/components/workshop/town/scene/town-scene3d-hud.ts +110 -110
- package/app/components/workshop/town/scene/town-scene3d-lifecycle.ts +144 -144
- package/app/components/workshop/town/scene/town-scene3d-links.ts +141 -141
- package/app/components/workshop/town/scene/town-scene3d-loop.ts +286 -286
- package/app/components/workshop/town/scene/town-scene3d-models.ts +154 -154
- package/app/components/workshop/town/scene/town-scene3d-nodes.ts +562 -562
- package/app/components/workshop/town/scene/town-scene3d-ranges.ts +273 -273
- package/app/components/workshop/town/scene/town-scene3d-renderer.ts +320 -320
- package/app/components/workshop/town/scene/town-scene3d-selection.ts +257 -257
- package/app/components/workshop/town/scene/town-scene3d-types.ts +264 -264
- package/app/components/workshop/transcript/TranscriptBlockList.vue +68 -68
- package/app/components/workshop/transcript/TranscriptEarlierPager.vue +81 -81
- package/app/components/workshop/transcript/TranscriptFilterBar.vue +126 -126
- package/app/components/workshop/workbench/CreateWorkspaceModal.vue +36 -36
- package/app/components/workshop/workbench/WorkspaceEmpty.vue +56 -56
- package/app/composables/useResponsive.ts +88 -88
- package/app/composables/workshop/device-twin-types.ts +29 -29
- package/app/composables/workshop/event-blocks/attention.ts +58 -58
- package/app/composables/workshop/event-blocks/classify.ts +44 -44
- package/app/composables/workshop/event-blocks/clusterer.ts +231 -231
- package/app/composables/workshop/event-blocks/fold-stream.ts +45 -45
- package/app/composables/workshop/event-blocks/markdown.ts +81 -81
- package/app/composables/workshop/event-blocks/mentions.ts +49 -49
- package/app/composables/workshop/event-blocks/text-utils.ts +100 -100
- package/app/composables/workshop/event-blocks/types.ts +40 -40
- package/app/composables/workshop/town/town-relay-props.ts +231 -231
- package/app/composables/workshop/town/town-view-types.ts +145 -145
- package/app/composables/workshop/town/useTownAgentBindings.ts +182 -182
- package/app/composables/workshop/town/useTownAgentChat.ts +203 -203
- package/app/composables/workshop/town/useTownAlarms.ts +36 -36
- package/app/composables/workshop/town/useTownCallouts.ts +174 -174
- package/app/composables/workshop/town/useTownChannels.ts +220 -220
- package/app/composables/workshop/town/useTownHealth.ts +66 -66
- package/app/composables/workshop/town/useTownHudTickers.ts +77 -77
- package/app/composables/workshop/town/useTownLayout.ts +277 -277
- package/app/composables/workshop/town/useTownNavMap.ts +301 -301
- package/app/composables/workshop/town/useTownNodeBindings.ts +345 -345
- package/app/composables/workshop/town/useTownPanelDrag.ts +91 -91
- package/app/composables/workshop/town/useTownRailData.ts +421 -421
- package/app/composables/workshop/town/useTownSceneControl.ts +92 -92
- package/app/composables/workshop/town/useTownSceneInput.ts +275 -275
- package/app/composables/workshop/town/useTownSceneRuntime.ts +390 -390
- package/app/composables/workshop/town/useTownSheets.ts +41 -41
- package/app/composables/workshop/town/useTownTrends.ts +93 -93
- package/app/composables/workshop/useChannelList.ts +88 -88
- package/app/composables/workshop/useChannelTerminals.ts +65 -65
- package/app/composables/workshop/useComposerMentions.ts +130 -130
- package/app/composables/workshop/useDcwStream.ts +374 -374
- package/app/composables/workshop/useDeviceTwinDcwWrite.ts +77 -77
- package/app/composables/workshop/useDeviceTwinPanel.ts +56 -56
- package/app/composables/workshop/useEscClose.ts +44 -44
- package/app/composables/workshop/useEventBlockView.ts +159 -159
- package/app/composables/workshop/useEventBlocks.ts +33 -33
- package/app/composables/workshop/useHitlAnswer.ts +184 -184
- package/app/composables/workshop/useLaneWidths.ts +27 -27
- package/app/composables/workshop/useOmpTerminalSession.ts +424 -424
- package/app/composables/workshop/usePluginAdmin.ts +152 -152
- package/app/composables/workshop/usePluginPanels.ts +72 -72
- package/app/composables/workshop/useRuntimeConfigDraft.ts +118 -118
- package/app/composables/workshop/useSettingsGroups.ts +243 -243
- package/app/composables/workshop/useTaskBoardColumns.ts +47 -47
- package/app/composables/workshop/useTerminalRenderer.ts +308 -308
- package/app/composables/workshop/useTranscriptEnterStage.ts +48 -48
- package/app/composables/workshop/useTranscriptHistory.ts +52 -52
- package/app/composables/workshop/useTranscriptScroll.ts +113 -113
- package/app/composables/workshop/useVisibleInterval.ts +42 -42
- package/app/composables/workshop/useWorkshopWs.ts +265 -265
- package/app/config/index.ts +1 -1
- package/app/middleware/locale-cookie.global.ts +22 -22
- package/app/pages/aml/api.ts +6 -6
- package/app/pages/aml/composables/useAmlDatasets.ts +38 -38
- package/app/pages/aml/composables/useAmlEntities.ts +57 -57
- package/app/pages/aml/composables/useAmlEnv.ts +191 -191
- package/app/pages/aml/composables/useAmlExperiments.ts +45 -45
- package/app/pages/aml/composables/useAmlFormat.ts +44 -44
- package/app/pages/aml/composables/useAmlJobs.ts +131 -131
- package/app/pages/aml/composables/useAmlModels.ts +56 -56
- package/app/pages/aml/composables/useAmlNotes.ts +47 -47
- package/app/pages/aml/composables/useAmlPredict.ts +93 -93
- package/app/pages/aml/constants.ts +63 -63
- package/app/pages/aml/index.vue +236 -236
- package/app/pages/composables/useDashboardCharts.ts +192 -192
- package/app/pages/composables/useDashboardData.ts +144 -144
- package/app/pages/daq/composables/useDaqAddNode.ts +126 -126
- package/app/pages/daq/composables/useDaqDetailBinding.ts +29 -29
- package/app/pages/daq/composables/useDaqDetailFrames.ts +42 -42
- package/app/pages/daq/composables/useDaqDetailNode.ts +53 -53
- package/app/pages/daq/composables/useDaqDetailParams.ts +138 -138
- package/app/pages/daq/composables/useDaqFilters.ts +187 -187
- package/app/pages/daq/composables/useDaqNodeWindow.ts +86 -86
- package/app/pages/daq/composables/useDaqOptimizations.ts +99 -99
- package/app/pages/daq/composables/useDaqTemplates.ts +152 -152
- package/app/pages/daq/index.vue +260 -260
- package/app/pages/dcw/composables/useDcwCards.ts +27 -27
- package/app/pages/dcw/composables/useDcwDetailScope.ts +145 -145
- package/app/pages/dcw/composables/useDcwDetailTemplates.ts +94 -94
- package/app/pages/dcw/composables/useDcwFilter.ts +29 -29
- package/app/pages/dcw/composables/useDcwLedger.ts +34 -34
- package/app/pages/dcw/composables/useDcwLineMutations.ts +115 -115
- package/app/pages/dcw/composables/useDcwLineRun.ts +60 -60
- package/app/pages/dcw/composables/useDcwProducts.ts +54 -54
- package/app/pages/dcw/composables/useDcwQuery.ts +68 -68
- package/app/pages/dcw/composables/useDcwQuickActions.ts +47 -47
- package/app/pages/dcw/composables/useDcwRecipes.ts +256 -256
- package/app/pages/dcw/composables/useDcwTemplates.ts +50 -50
- package/app/pages/dcw/index.vue +195 -195
- package/app/pages/dcw/types.ts +9 -9
- package/app/pages/index.vue +126 -126
- package/app/pages/logs/composables/useLogsFormat.ts +43 -43
- package/app/pages/logs/composables/useLogsScope.ts +39 -39
- package/app/pages/monitor/types.ts +61 -61
- package/app/pages/operations.vue +61 -61
- package/app/pages/permissions/index.vue +369 -369
- package/app/pages/tokens/composables/useTokenClipboard.ts +33 -33
- package/app/pages/tokens/composables/useTokenCreate.ts +93 -93
- package/app/pages/tokens/composables/useTokenRename.ts +54 -54
- package/app/pages/tokens/composables/useTokenReveal.ts +84 -84
- package/app/pages/tokens/composables/useTokensList.ts +60 -60
- package/app/pages/tokens.vue +111 -111
- package/app/pages/tools/index.vue +98 -98
- package/app/pages/workshop/agents.vue +130 -130
- package/app/pages/workshop/composables/useAgentHarnessOptions.ts +59 -59
- package/app/pages/workshop/composables/useAgentTemplateActions.ts +42 -42
- package/app/pages/workshop/composables/useAgentTemplateDialogState.ts +24 -24
- package/app/pages/workshop/composables/useAgentTemplateForm.ts +88 -88
- package/app/pages/workshop/composables/useAgentTemplatesCatalog.ts +92 -92
- package/app/pages/workshop/composables/useTeamActions.ts +44 -44
- package/app/pages/workshop/composables/useTeamAddMemberDialog.ts +49 -49
- package/app/pages/workshop/composables/useTeamCreateDialog.ts +67 -67
- package/app/pages/workshop/composables/useTeamDeployDialog.ts +49 -49
- package/app/pages/workshop/composables/useTeamDialogState.ts +46 -46
- package/app/pages/workshop/composables/useTeamPluginDialog.ts +72 -72
- package/app/pages/workshop/composables/useTeamsCatalog.ts +100 -100
- package/app/pages/workshop/composables/useWorkbenchWorkspaces.ts +123 -123
- package/app/pages/workshop/composables/useWorkspaceAuth.ts +31 -31
- package/app/pages/workshop/composables/useWorkspaceChannels.ts +62 -62
- package/app/pages/workshop/composables/useWorkspaceShell.ts +136 -136
- package/app/pages/workshop/schedules.vue +553 -553
- package/app/pages/workshop/w/[wsId].vue +221 -221
- package/app/plugins/aw-plugins.client.ts +213 -213
- package/app/plugins/esc-close.client.ts +31 -31
- package/app/stores/workshop/hitl.ts +183 -183
- package/app/stores/workshop/narrow-fetch.ts +23 -23
- package/app/utils/api-error.ts +75 -75
- package/app/utils/builtin-catalog.ts +104 -104
- package/app/utils/chart-trend.ts +97 -97
- package/app/utils/dcw-driver-badge.ts +16 -16
- package/app/utils/dcw-recipe-form.ts +26 -26
- package/cli/commands/tui.mjs +28 -28
- package/cli/commands/update.mjs +124 -124
- package/cli/core/child-lifecycle.mjs +136 -136
- package/cli/core/meta.mjs +38 -38
- package/cli/core/post-build.mjs +96 -96
- package/config.yml +1 -1
- package/docs/cli.en.md +2 -2
- package/docs/cli.md +2 -2
- package/docs/mcp.en.md +27 -27
- package/docs/multi-harness-architecture.md +248 -248
- package/docs/plugins.en.md +1 -1
- package/docs/plugins.md +1 -1
- package/docs/sdk.en.md +1 -1
- package/docs/sdk.md +1 -1
- package/docs/tui.md +43 -43
- package/i18n/dicts/_en.json +1551 -1551
- package/i18n/dicts/_en2.json +300 -300
- package/i18n/dicts/_en4.json +114 -114
- package/i18n/dicts/agentLanesView.json +61 -61
- package/i18n/dicts/appHeader.json +17 -17
- package/i18n/dicts/channelSessionList.json +51 -51
- package/i18n/dicts/chat.json +79 -79
- package/i18n/dicts/clusterTool.json +4 -4
- package/i18n/dicts/composer.json +38 -38
- package/i18n/dicts/ctpl.json +37 -37
- package/i18n/dicts/dcwDetail.json +219 -219
- package/i18n/dicts/lineOps.json +14 -14
- package/i18n/dicts/multiChannelView.json +13 -13
- package/i18n/dicts/notifications.json +13 -13
- package/i18n/dicts/taskInspectorDrawer.json +25 -25
- package/i18n/dicts/teamPlugins.json +10 -10
- package/i18n/dicts/townView.json +209 -209
- package/mcp/discovery.mjs +227 -227
- package/package.json +1 -1
- package/public/favicon.svg +14 -14
- package/public/robots.txt +3 -3
- package/scripts/_audit/audit-harness-adapters.md +664 -664
- package/scripts/_audit/aw-mcp-live-e2e.mjs +293 -293
- package/scripts/_audit/bump-version.mjs +51 -51
- package/scripts/_audit/detached-instance.mjs +112 -112
- package/scripts/_audit/detached-start.mjs +103 -103
- package/scripts/_audit/eda-ui-fix-acceptance.mjs +212 -212
- package/scripts/_audit/guard-upstream-liveness.mjs +104 -104
- package/scripts/_audit/http-api-authz-audit.md +657 -657
- package/scripts/_audit/kb-team-mock-e2e.mjs +146 -146
- package/scripts/_audit/kb-team-omp-e2e.mjs +229 -229
- package/scripts/_audit/run.mjs +21 -21
- package/scripts/_audit/runtime-audit.md +716 -716
- package/scripts/_audit/skills-guided-e2e.mjs +316 -316
- package/scripts/_audit/stability-soak.mjs +252 -252
- package/scripts/_audit/stubs/nuxt-imports.mjs +67 -67
- package/scripts/_audit/ts-register-hook.mjs +12 -12
- package/scripts/_audit/ts-resolve-hook.mjs +96 -96
- package/scripts/_aw-packaged-start.cjs +22 -22
- package/scripts/_aw0746-stage12.mjs +94 -94
- package/scripts/_aw0746-stage34.mjs +136 -136
- package/scripts/_aw0746-stage6b-train-sweep.mjs +145 -145
- package/scripts/_aw0746-stage6c-jobsmoke.mjs +69 -69
- package/scripts/_dbg-configroot-audit.mjs +86 -86
- package/scripts/_dbg-daq-intervals-func.mjs +115 -115
- package/scripts/_dbg-perms-e2e.mjs +142 -142
- package/scripts/_dbg-protocol-matrix.mjs +462 -462
- package/scripts/_dbg-render-regression.mjs +193 -193
- package/scripts/_dbg-schedule-e2e.mjs +262 -262
- package/scripts/_e2e-ui-functional.mjs +371 -371
- package/scripts/_i18n-en-cjk-scan.mjs +28 -28
- package/scripts/_i18n-en-verify.mjs +107 -107
- package/scripts/_i18n-extra-checks.mjs +53 -53
- package/scripts/_i18n-scan-hardcoded.mjs +180 -180
- package/scripts/_lib-aml-python-run.mjs +17 -17
- package/scripts/_lint-reflow.mjs +105 -105
- package/scripts/_loop-biax-campaign.mjs +130 -130
- package/scripts/_plc-sim-detached.cjs +22 -22
- package/scripts/_probe-daq-omp-task.mjs +100 -100
- package/scripts/_probe-daq-scope-default.mjs +123 -123
- package/scripts/_probe-model-channel-link.cjs +25 -25
- package/scripts/_probe-recipe-switch.mjs +92 -92
- package/scripts/_provision-injection-line.mjs +39 -39
- package/scripts/_run-matrix.ps1 +53 -53
- package/scripts/_sweep-button-contrast.mjs +87 -87
- package/scripts/acceptance-aml-hybrid-e2e.ts +396 -396
- package/scripts/acceptance-aml-hybrid-live.mjs +93 -93
- package/scripts/acceptance-aml-model-identity.ts +137 -137
- package/scripts/agent-daq-isolation-e2e.mjs +91 -91
- package/scripts/api-contract-smoke.mjs +126 -126
- package/scripts/ask-hitl-e2e.mjs +96 -96
- package/scripts/aw-expose.mjs +159 -159
- package/scripts/channel-interaction-smoke.mjs +80 -80
- package/scripts/data-studio-ui-e2e.mjs +163 -163
- package/scripts/demo-group-chat-all-real.ts +279 -279
- package/scripts/demo-group-chat-omp-cases.ts +210 -210
- package/scripts/demo-group-chat-omp.ts +184 -184
- package/scripts/demo-group-chat-order.ts +197 -197
- package/scripts/dev-modbus-simulator.mjs +55 -55
- package/scripts/docs-shots.mjs +36 -36
- package/scripts/e2e-agentteam-chat.mjs +473 -473
- package/scripts/e2e-agentteam-real-triage.mjs +421 -421
- package/scripts/e2e-aml-decoupled.mjs +162 -162
- package/scripts/e2e-aw-tui-global.mjs +277 -277
- package/scripts/e2e-closedloop/cleanup.mjs +27 -27
- package/scripts/e2e-closedloop/lib.mjs +109 -109
- package/scripts/e2e-closedloop/main.mjs +59 -59
- package/scripts/e2e-closedloop/scenarios-accounts.mjs +210 -210
- package/scripts/e2e-closedloop/scenarios-authz.mjs +196 -196
- package/scripts/e2e-closedloop/scenarios-daq-dcw.mjs +222 -222
- package/scripts/e2e-closedloop/scenarios-plugins.mjs +169 -169
- package/scripts/e2e-closedloop/state.mjs +10 -10
- package/scripts/e2e-config-groups.mjs +238 -238
- package/scripts/e2e-crash-cycle.mjs +108 -108
- package/scripts/e2e-full-closedloop.mjs +16 -16
- package/scripts/e2e-hil-multi-user.mjs +307 -307
- package/scripts/e2e-hil-restart.mjs +339 -339
- package/scripts/e2e-idd-results-ui.mjs +175 -0
- package/scripts/e2e-idd-results.mjs +48 -16
- package/scripts/e2e-injection-recipe-closedloop.mjs +203 -203
- package/scripts/e2e-line-governance.mjs +352 -352
- package/scripts/e2e-ontology.mjs +393 -393
- package/scripts/e2e-plc-plugin-closedloop.mjs +549 -549
- package/scripts/e2e-timezone-settings.mjs +57 -57
- package/scripts/full-stack-shots.mjs +145 -145
- package/scripts/full-tool-injection-harness-e2e.mjs +214 -214
- package/scripts/hitl-reject-e2e.mjs +131 -131
- package/scripts/line-log-smoke.mjs +260 -260
- package/scripts/live-aml-mockomp.mjs +304 -304
- package/scripts/live-aml-optloop-resume.mjs +322 -322
- package/scripts/live-aml-optloop.mjs +588 -588
- package/scripts/live-aml-stage9.mjs +169 -169
- package/scripts/live-aml-two-goals.mjs +315 -315
- package/scripts/live-optloop-two-modes.mjs +857 -857
- package/scripts/mes-agent-integration-e2e.mjs +361 -361
- package/scripts/ops-plugins-e2e.mjs +85 -85
- package/scripts/proof-omp-real.ts +189 -189
- package/scripts/scenario-suite-setup.mjs +337 -337
- package/scripts/scenario-suite-stability.mjs +144 -144
- package/scripts/smoke-optimization-verify.ts +72 -72
- package/scripts/team-coordination-e2e.mjs +96 -96
- package/scripts/test-agentteam-task-chat-flow.ts +420 -420
- package/scripts/test-agentteam-workflow.ts +472 -472
- package/scripts/test-aw-skills.mjs +102 -102
- package/scripts/test-cli-exit.mjs +343 -343
- package/scripts/test-daq-frame-race.mjs +358 -358
- package/scripts/test-data-root.mjs +208 -208
- package/scripts/test-events-index.mjs +176 -176
- package/scripts/test-group-chat-hardening.ts +265 -265
- package/scripts/test-group-chat-unit/lib.ts +186 -186
- package/scripts/test-group-chat-unit/main.ts +45 -45
- package/scripts/test-group-chat-unit/section-a-migration.ts +75 -75
- package/scripts/test-group-chat-unit/section-b-permission-matrix.ts +88 -88
- package/scripts/test-group-chat-unit/section-c-member-lifecycle.ts +64 -64
- package/scripts/test-group-chat-unit/section-d-mention-resolution.ts +36 -36
- package/scripts/test-group-chat-unit/section-e-chat-facts.ts +97 -97
- package/scripts/test-group-chat-unit/section-f-user-notifications.ts +52 -52
- package/scripts/test-group-chat-unit/section-g-member-projection.ts +44 -44
- package/scripts/test-group-chat-unit/section-h-outbox-consistency.ts +30 -30
- package/scripts/test-group-chat-unit/section-i-read-idempotency.ts +24 -24
- package/scripts/test-group-chat-unit/section-j-permission-scope.ts +150 -150
- package/scripts/test-group-chat-unit.ts +35 -35
- package/scripts/test-hitl-decision.ts +526 -526
- package/scripts/test-hitl-legacy-channel-auth.ts +143 -143
- package/scripts/test-hitl-registry.ts +112 -112
- package/scripts/test-log-flooding.mjs +160 -160
- package/scripts/test-lru.mjs +101 -101
- package/scripts/test-memory-month-query.mjs +70 -70
- package/scripts/test-plugin-hardening.mjs +90 -90
- package/scripts/test-plugin-lifecycle.mjs +173 -173
- package/scripts/test-rollback-index.mjs +137 -137
- package/scripts/test-schedule-runtime.ts +309 -309
- package/scripts/test-scheduler-loop/scenarios-supervise.ts +25 -25
- package/scripts/test-sdk-surface.mjs +158 -158
- package/scripts/test-serial-bridge.mjs +418 -418
- package/scripts/test-tui-commands.mjs +148 -148
- package/scripts/test-tui-reducers.mjs +72 -72
- package/scripts/three-system-e2e/lib.mjs +79 -79
- package/scripts/three-system-e2e/main.mjs +40 -40
- package/scripts/three-system-e2e/phases/phase-0-user-token.mjs +42 -42
- package/scripts/three-system-e2e/phases/phase-0a2-line-autoselect.mjs +35 -35
- package/scripts/three-system-e2e/phases/phase-0b-fixture-grants.mjs +39 -39
- package/scripts/three-system-e2e/phases/phase-0c-plugin-outbound-auth.mjs +95 -95
- package/scripts/three-system-e2e/phases/stage-1-health.mjs +47 -47
- package/scripts/three-system-e2e/phases/stage-2-5-team-plugins.mjs +84 -84
- package/scripts/three-system-e2e/phases/stage-2-teams-tools-hitl.mjs +184 -184
- package/scripts/three-system-e2e/phases/stage-3-diag.mjs +73 -73
- package/scripts/three-system-e2e/phases/stage-4-plugin-toggle.mjs +53 -53
- package/scripts/three-system-e2e/state.mjs +87 -87
- package/scripts/three-system-e2e.mjs +40 -40
- package/scripts/tool-face-batch-identity-e2e.mjs +222 -222
- package/scripts/tsconfig.json +14 -14
- package/scripts/tui-smoke.mjs +100 -100
- package/scripts/typecheck.mjs +75 -75
- package/scripts/ui/admin-shots.mjs +46 -46
- package/scripts/ui/bump-microfont.mjs +39 -39
- package/scripts/ui/linkcheck2.mjs +37 -37
- package/scripts/ui/live-render-check.mjs +72 -72
- package/scripts/ui/md-lint.mjs +80 -80
- package/scripts/ui/perf-audit.mjs +132 -132
- package/scripts/ui/readme-assets.mjs +30 -30
- package/scripts/ui/readme-shots.mjs +42 -42
- package/scripts/ui/record-demo.mjs +557 -557
- package/scripts/ui/record.mjs +225 -225
- package/scripts/ui/seed-admin.mjs +68 -68
- package/scripts/ui/seed-demo.mjs +83 -83
- package/scripts/ui/seed-industrial-demo.mjs +171 -171
- package/scripts/ui/shot-hero.mjs +25 -25
- package/scripts/ui/shots.mjs +75 -75
- package/scripts/ui/sim-ui-shot.mjs +16 -16
- package/scripts/ui/smoke-refactor.mjs +258 -258
- package/scripts/ui/verify-nav.mjs +51 -51
- package/scripts/ui/verify-responsive.mjs +285 -285
- package/sdk/client.d.mts +110 -110
- package/sdk/examples/line-sentinel/index.mjs +105 -105
- package/sdk/examples/ops-notifier/index.mjs +34 -34
- package/sdk/examples/sample-insight/index.mjs +39 -39
- package/server/api/plugins/[name]/[...path].ts +5 -1
- package/server/api/plugins/client/[name].get.ts +18 -18
- package/server/api/plugins/i18n.get.ts +12 -12
- package/server/api/plugins/manifest.get.ts +10 -10
- package/server/api/system/backup/list.get.ts +32 -32
- package/server/api/system/backup/run.post.ts +21 -21
- package/server/api/system/config-groups/[id].delete.ts +21 -21
- package/server/api/system/config-groups/[id].patch.ts +26 -26
- package/server/api/system/config-groups/index.get.ts +21 -21
- package/server/api/system/config-groups/index.post.ts +33 -33
- package/server/api/system/timezone.get.ts +20 -20
- package/server/api/users/tokens/[id]/token.get.ts +11 -11
- package/server/api/workshop/[...path].ts +13 -13
- package/server/api/workshop/agent-tools/approvals/index.get.ts +43 -43
- package/server/api/workshop/agent-tools/bindings/[id].delete.ts +26 -26
- package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -45
- package/server/api/workshop/agent-tools/bindings/index.get.ts +41 -41
- package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -42
- package/server/api/workshop/aml/datasets/[id]/preview.get.ts +68 -68
- package/server/api/workshop/aml/datasets/[id].delete.ts +39 -39
- package/server/api/workshop/aml/datasets/[id].get.ts +53 -53
- package/server/api/workshop/aml/datasets/[id].patch.ts +30 -30
- package/server/api/workshop/aml/datasets/index.get.ts +20 -20
- package/server/api/workshop/aml/datasets/index.post.ts +27 -27
- package/server/api/workshop/aml/entities/index.get.ts +13 -13
- package/server/api/workshop/aml/entities/prune.post.ts +28 -28
- package/server/api/workshop/aml/env/index.get.ts +13 -13
- package/server/api/workshop/aml/env/recheck.post.ts +14 -14
- package/server/api/workshop/aml/env/uv.post.ts +21 -21
- package/server/api/workshop/aml/env/venv.post.ts +24 -24
- package/server/api/workshop/aml/experiments/index.get.ts +35 -35
- package/server/api/workshop/aml/index.get.ts +37 -37
- package/server/api/workshop/aml/jobs/[id]/cancel.post.ts +21 -21
- package/server/api/workshop/aml/jobs/[id]/logs.get.ts +23 -23
- package/server/api/workshop/aml/jobs/[id]/retry.post.ts +20 -20
- package/server/api/workshop/aml/jobs/[id].delete.ts +44 -44
- package/server/api/workshop/aml/jobs/[id].get.ts +23 -23
- package/server/api/workshop/aml/jobs/index.get.ts +26 -26
- package/server/api/workshop/aml/models/[id]/predict.post.ts +24 -24
- package/server/api/workshop/aml/models/[id]/promote.post.ts +30 -30
- package/server/api/workshop/aml/models/index.get.ts +48 -48
- package/server/api/workshop/aml/training-plans/[id]/train.post.ts +18 -18
- package/server/api/workshop/aml/training-plans/[id].delete.ts +18 -18
- package/server/api/workshop/aml/training-plans/[id].patch.ts +30 -30
- package/server/api/workshop/aml/training-plans/index.get.ts +9 -9
- package/server/api/workshop/aml/training-plans/index.post.ts +43 -43
- package/server/api/workshop/approvals/[id]/decide.post.ts +30 -30
- package/server/api/workshop/approvals/index.get.ts +22 -22
- package/server/api/workshop/audit.get.ts +43 -43
- package/server/api/workshop/channels/[id]/chat/messages/[messageId]/read.post.ts +22 -22
- package/server/api/workshop/channels/[id]/chat/messages/index.get.ts +29 -29
- package/server/api/workshop/channels/[id]/chat/messages/index.post.ts +51 -51
- package/server/api/workshop/channels/[id]/chat/permissions.get.ts +35 -35
- package/server/api/workshop/channels/[id]/index.patch.ts +64 -64
- package/server/api/workshop/channels/[id]/members/[userId]/approve.post.ts +20 -20
- package/server/api/workshop/channels/[id]/members/[userId].delete.ts +21 -21
- package/server/api/workshop/channels/[id]/members/index.get.ts +23 -23
- package/server/api/workshop/channels/[id]/members/leave.post.ts +20 -20
- package/server/api/workshop/channels/[id]/twin-profile.get.ts +45 -45
- package/server/api/workshop/channels/[id]/twin-profile.patch.ts +72 -72
- package/server/api/workshop/daq/[id]/test.post.ts +1 -1
- package/server/api/workshop/daq/alarms.get.ts +16 -16
- package/server/api/workshop/dcw/[id]/write.post.ts +4 -4
- package/server/api/workshop/dcw/[id].delete.ts +41 -41
- package/server/api/workshop/dcw/[id].patch.ts +40 -40
- package/server/api/workshop/dcw/mes-test-read.post.ts +24 -24
- package/server/api/workshop/dcw/params/[id]/read.post.ts +17 -17
- package/server/api/workshop/dcw/params/[id]/write.post.ts +21 -21
- package/server/api/workshop/dcw/params/[id].delete.ts +19 -19
- package/server/api/workshop/dcw/params/[id].patch.ts +23 -23
- package/server/api/workshop/dcw/params/index.get.ts +27 -27
- package/server/api/workshop/dcw/params/index.post.ts +25 -25
- package/server/api/workshop/dcw/products/[id].delete.ts +16 -16
- package/server/api/workshop/dcw/products/[id].patch.ts +17 -17
- package/server/api/workshop/dcw/recipes/[id]/index.patch.ts +22 -22
- package/server/api/workshop/dcw/recipes/[id]/versions.get.ts +14 -14
- package/server/api/workshop/dcw/recipes/[id].delete.ts +25 -25
- package/server/api/workshop/dcw/recipes/index.get.ts +12 -12
- package/server/api/workshop/dcw/runs/[id]/close.post.ts +15 -15
- package/server/api/workshop/dcw/templates/[key].delete.ts +14 -14
- package/server/api/workshop/dcw/templates/[key].patch.ts +16 -16
- package/server/api/workshop/dcw/templates/index.post.ts +15 -15
- package/server/api/workshop/dcw/test-driver.post.ts +16 -16
- package/server/api/workshop/device-twins/[id].delete.ts +25 -25
- package/server/api/workshop/eda/runs/[id]/labels.patch.ts +25 -25
- package/server/api/workshop/exp/confirmations/[id]/decide.post.ts +41 -41
- package/server/api/workshop/exp/confirmations/index.get.ts +25 -25
- package/server/api/workshop/harnesses/[id]/providers.get.ts +16 -16
- package/server/api/workshop/hitl/respond.post.ts +94 -94
- package/server/api/workshop/notifications/index.get.ts +60 -60
- package/server/api/workshop/notifications/read.post.ts +31 -31
- package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -24
- package/server/api/workshop/plugins/[name]/disable.post.ts +21 -21
- package/server/api/workshop/plugins/[name]/enable.post.ts +21 -21
- package/server/api/workshop/plugins/[name]/index.get.ts +14 -14
- package/server/api/workshop/schedules/[id]/run.post.ts +15 -15
- package/server/api/workshop/schedules/[id]/runs.get.ts +15 -15
- package/server/api/workshop/schedules/[id].delete.ts +14 -14
- package/server/api/workshop/schedules/[id].get.ts +13 -13
- package/server/api/workshop/schedules/[id].patch.ts +29 -29
- package/server/api/workshop/schedules/index.get.ts +12 -12
- package/server/api/workshop/schedules/index.post.ts +32 -32
- package/server/api/workshop/tasks/[id]/reassign.post.ts +32 -32
- package/server/api/workshop/tasks/[id]/update.post.ts +35 -35
- package/server/api/workshop/teams/[id]/plugins/index.get.ts +36 -36
- package/server/api/workshop/teams/[id]/plugins/index.put.ts +42 -42
- package/server/api/workshop/ws/audience.ts +56 -56
- package/server/api/workshop/ws/db-buffer.ts +68 -68
- package/server/api/workshop/ws/event-mapping.ts +47 -47
- package/server/api/workshop/ws/handlers.ts +132 -132
- package/server/api/workshop/ws/hub.ts +133 -133
- package/server/api/workshop/ws/index.ts +23 -23
- package/server/api/workshop/ws/notification-uplink.ts +77 -77
- package/server/api/workshop/ws/shared.ts +94 -94
- package/server/api/workshop/ws/streams.ts +146 -146
- package/server/middleware/00-security-headers.ts +38 -38
- package/server/middleware/01-rate-guard.ts +101 -101
- package/server/plugins/aml-twin-worker.ts +32 -32
- package/server/plugins/dev-stability-guard.ts +42 -42
- package/server/plugins-builtin/diag-bridge/client.mjs +32 -12
- package/server/plugins-builtin/diag-bridge/host/constants.mjs +25 -25
- package/server/plugins-builtin/diag-bridge/host/exports.mjs +104 -104
- package/server/plugins-builtin/diag-bridge/host/helpers.mjs +39 -9
- package/server/plugins-builtin/diag-bridge/host/index.mjs +15 -15
- package/server/plugins-builtin/diag-bridge/host/intents.mjs +62 -62
- package/server/plugins-builtin/diag-bridge/host/plugin.mjs +60 -26
- package/server/plugins-builtin/diag-bridge/host/snapshot.mjs +93 -93
- package/server/plugins-builtin/diag-bridge/index.mjs +9 -9
- package/server/plugins-builtin/serial-bridge/client.mjs +211 -211
- package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -409
- package/server/plugins-builtin/serial-bridge/i18n.json +62 -62
- package/server/plugins-builtin/serial-bridge/index.mjs +247 -247
- package/server/plugins-builtin/serial-bridge/lib.mjs +208 -208
- package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -168
- package/server/services/system-config/contracts.ts +29 -29
- package/server/services/system-config/dispose.ts +19 -19
- package/server/services/system-config/facade.ts +26 -26
- package/server/services/system-config/groups.ts +108 -108
- package/server/services/system-config/index.ts +21 -21
- package/server/services/system-config/init.ts +26 -26
- package/server/services/system-config/mutate.ts +103 -103
- package/server/services/system-config/plugins.ts +104 -104
- package/server/services/system-config/snapshot.ts +59 -59
- package/server/services/system-config/state.ts +79 -79
- package/server/services/system-config/types.ts +58 -58
- package/server/services/workshop/agents/adapters/omp-rpc-client/api.ts +111 -111
- package/server/services/workshop/agents/adapters/omp-rpc-client/contracts.ts +22 -22
- package/server/services/workshop/agents/adapters/omp-rpc-client/facade.ts +7 -7
- package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +0 -18
- package/server/services/workshop/agents/adapters/omp-rpc-client/helpers.ts +38 -38
- package/server/services/workshop/agents/adapters/omp-rpc-client/index.ts +25 -25
- package/server/services/workshop/agents/adapters/omp-rpc-client/start.ts +70 -70
- package/server/services/workshop/agents/adapters/omp-rpc-client/state.ts +65 -65
- package/server/services/workshop/agents/adapters/omp-rpc-client/stdout.ts +92 -92
- package/server/services/workshop/agents/adapters/omp-rpc-client/usage.ts +47 -47
- package/server/services/workshop/agents/agent-badge.ts +38 -38
- package/server/services/workshop/agents/binding-authz.ts +60 -60
- package/server/services/workshop/agents/binding-mode.ts +51 -51
- package/server/services/workshop/agents/codex-agent/client.ts +170 -170
- package/server/services/workshop/agents/codex-agent/core.ts +119 -119
- package/server/services/workshop/agents/codex-agent/facade.ts +8 -8
- package/server/services/workshop/agents/codex-agent/helpers.ts +13 -13
- package/server/services/workshop/agents/codex-agent/hitl.ts +138 -138
- package/server/services/workshop/agents/codex-agent/index.ts +14 -14
- package/server/services/workshop/agents/codex-agent/turn.ts +367 -367
- package/server/services/workshop/agents/codex-agent/types.ts +42 -42
- package/server/services/workshop/agents/harness-process.ts +3 -3
- package/server/services/workshop/agents/harness-terminal/api.ts +197 -197
- package/server/services/workshop/agents/harness-terminal/index.ts +17 -17
- package/server/services/workshop/agents/harness-terminal/io.ts +120 -120
- package/server/services/workshop/agents/harness-terminal/park.ts +55 -55
- package/server/services/workshop/agents/harness-terminal/sanitize.ts +98 -98
- package/server/services/workshop/agents/harness-terminal/session.ts +124 -124
- package/server/services/workshop/agents/harness-terminal/shared.ts +74 -74
- package/server/services/workshop/agents/hitl-capabilities.ts +312 -312
- package/server/services/workshop/agents/hitl-decision/answers.ts +32 -32
- package/server/services/workshop/agents/hitl-decision/decide.ts +268 -268
- package/server/services/workshop/agents/hitl-decision/payload.ts +45 -45
- package/server/services/workshop/agents/hitl-decision/shared.ts +108 -108
- package/server/services/workshop/agents/hitl-decision/visibility.ts +94 -94
- package/server/services/workshop/agents/host-tool-bridge/tools/progress.ts +84 -84
- package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -104
- package/server/services/workshop/agents/host-tool-bridge/tools/team.ts +70 -70
- package/server/services/workshop/agents/industrial/aml-activity.ts +131 -131
- package/server/services/workshop/agents/industrial/audit-query.ts +66 -66
- package/server/services/workshop/agents/industrial/daq-tools.ts +352 -352
- package/server/services/workshop/agents/industrial/exp-tools.ts +104 -104
- package/server/services/workshop/agents/industrial/ops-tools.ts +16 -54
- package/server/services/workshop/agents/industrial/param-tools.ts +69 -69
- package/server/services/workshop/agents/industrial/recipe-gate.ts +6 -19
- package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
- package/server/services/workshop/agents/node-bindings.repo.ts +207 -207
- package/server/services/workshop/agents/node-delegation.ts +159 -159
- package/server/services/workshop/agents/omp-agent/core.ts +146 -146
- package/server/services/workshop/agents/omp-agent/facade.ts +8 -8
- package/server/services/workshop/agents/omp-agent/helpers.ts +37 -37
- package/server/services/workshop/agents/omp-agent/index.ts +16 -16
- package/server/services/workshop/agents/omp-agent/tools-steer.ts +1 -18
- package/server/services/workshop/agents/omp-agent/types.ts +45 -45
- package/server/services/workshop/agents/opencode-agent/core.ts +77 -77
- package/server/services/workshop/agents/opencode-agent/facade.ts +8 -8
- package/server/services/workshop/agents/opencode-agent/helpers.ts +29 -29
- package/server/services/workshop/agents/opencode-agent/hitl.ts +113 -113
- package/server/services/workshop/agents/opencode-agent/index.ts +16 -16
- package/server/services/workshop/agents/opencode-agent/lifecycle.ts +44 -44
- package/server/services/workshop/agents/opencode-agent/server.ts +244 -244
- package/server/services/workshop/agents/opencode-agent/turn.ts +278 -278
- package/server/services/workshop/agents/opencode-agent/types.ts +54 -54
- package/server/services/workshop/agents/tool-classes.ts +44 -44
- package/server/services/workshop/aml/clean.ts +120 -120
- package/server/services/workshop/aml/entity.ts +367 -367
- package/server/services/workshop/aml/job-orchestrator/broadcast.ts +37 -37
- package/server/services/workshop/aml/job-orchestrator/control.ts +94 -94
- package/server/services/workshop/aml/job-orchestrator/failure.ts +96 -96
- package/server/services/workshop/aml/job-orchestrator/index.ts +22 -22
- package/server/services/workshop/aml/job-orchestrator/process.ts +101 -101
- package/server/services/workshop/aml/job-orchestrator/shared.ts +53 -53
- package/server/services/workshop/aml/job-orchestrator/status.ts +20 -20
- package/server/services/workshop/aml/job-orchestrator/tick.ts +37 -37
- package/server/services/workshop/aml/python/train-example.py +92 -92
- package/server/services/workshop/aml/runtime.ts +137 -137
- package/server/services/workshop/aml/stats.ts +140 -140
- package/server/services/workshop/aml/twin/calibration-worker.ts +150 -150
- package/server/services/workshop/aml/twin/model-backed-provider.ts +332 -332
- package/server/services/workshop/aml/twin/physics-spec-draft.ts +185 -185
- package/server/services/workshop/aml/twin/prompt-composer.ts +143 -143
- package/server/services/workshop/aml/twin/training-plans.ts +260 -260
- package/server/services/workshop/aml/twin/write-guard.ts +19 -19
- package/server/services/workshop/assets/character-asset.repo.ts +1 -1
- package/server/services/workshop/assets/device-twin.repo.ts +1 -1
- package/server/services/workshop/daq/bus/index.ts +5 -12
- package/server/services/workshop/daq/daq-controller/contracts.ts +39 -39
- package/server/services/workshop/daq/daq-controller/facade.ts +28 -28
- package/server/services/workshop/daq/daq-controller/frames.ts +137 -137
- package/server/services/workshop/daq/daq-controller/helpers.ts +52 -52
- package/server/services/workshop/daq/daq-controller/index.ts +22 -22
- package/server/services/workshop/daq/daq-controller/runtime-control.ts +72 -72
- package/server/services/workshop/daq/daq-controller/sweep-alarms.ts +176 -176
- package/server/services/workshop/daq/daq-controller/tsdb-twin.ts +138 -138
- package/server/services/workshop/daq/drivers/http.ts +95 -95
- package/server/services/workshop/daq/drivers/mock.ts +130 -130
- package/server/services/workshop/daq/drivers/modbus-rtu.ts +67 -67
- package/server/services/workshop/daq/drivers/modbus-tcp.ts +307 -307
- package/server/services/workshop/daq/drivers/opcua.ts +227 -227
- package/server/services/workshop/daq/drivers/s7-stub.ts +29 -29
- package/server/services/workshop/daq/host-bindings.ts +71 -71
- package/server/services/workshop/daq/host-ports.ts +65 -65
- package/server/services/workshop/db/aml-team-seeds.ts +118 -118
- package/server/services/workshop/db/backup-registry.ts +33 -33
- package/server/services/workshop/db/channel-member.repo.ts +122 -122
- package/server/services/workshop/db/channel.repo.ts +203 -203
- package/server/services/workshop/db/chat-message.repo.ts +233 -233
- package/server/services/workshop/db/database/index.ts +18 -18
- package/server/services/workshop/db/database/json.ts +14 -14
- package/server/services/workshop/db/database/open.ts +97 -97
- package/server/services/workshop/db/database/seed-data.ts +60 -60
- package/server/services/workshop/db/hitl-request.repo.ts +221 -221
- package/server/services/workshop/db/notification.repo.ts +199 -199
- package/server/services/workshop/db/readonly.ts +30 -30
- package/server/services/workshop/db/scheduled-task.repo.ts +235 -235
- package/server/services/workshop/db/transaction.ts +72 -72
- package/server/services/workshop/dcw/dcw-controller/contracts.ts +16 -16
- package/server/services/workshop/dcw/dcw-controller/control.ts +78 -78
- package/server/services/workshop/dcw/dcw-controller/facade.ts +19 -19
- package/server/services/workshop/dcw/dcw-controller/index.ts +22 -22
- package/server/services/workshop/dcw/dcw-controller/params.ts +97 -97
- package/server/services/workshop/dcw/dcw-controller/products.ts +103 -103
- package/server/services/workshop/dcw/dcw-controller/write-audit.ts +49 -49
- package/server/services/workshop/dcw/dcw-templates.ts +136 -136
- package/server/services/workshop/dcw/param-conversion.ts +78 -78
- package/server/services/workshop/dcw/param-map.repo.ts +349 -349
- package/server/services/workshop/dcw/plugin-bridge.ts +45 -45
- package/server/services/workshop/dcw/recipe-rollback-manager/contracts.ts +26 -26
- package/server/services/workshop/dcw/recipe-rollback-manager/facade.ts +13 -13
- package/server/services/workshop/dcw/recipe-rollback-manager/helpers.ts +30 -30
- package/server/services/workshop/dcw/recipe-rollback-manager/index.ts +17 -17
- package/server/services/workshop/dcw/recipe-rollback-manager/internal.ts +33 -33
- package/server/services/workshop/dcw/recipe-rollback-manager/judge.ts +52 -52
- package/server/services/workshop/dcw/recipe-rollback-manager/lock.ts +137 -137
- package/server/services/workshop/dcw/recipe-rollback-manager/rollback.ts +190 -190
- package/server/services/workshop/dcw/recipe-rollback-manager/state.ts +21 -21
- package/server/services/workshop/dcw/recipe-rollback-manager/sweep.ts +77 -77
- package/server/services/workshop/dcw/recipe-rollback-manager/types.ts +3 -3
- package/server/services/workshop/dcw/recipe-rollback-manager/views.ts +214 -214
- package/server/services/workshop/exp/exp-collector.ts +275 -275
- package/server/services/workshop/exp/exp-state.repo.ts +339 -339
- package/server/services/workshop/mes/mes-controller.ts +1155 -1155
- package/server/services/workshop/mes/mes-hook.ts +567 -567
- package/server/services/workshop/ontology/subgraph.core.ts +300 -300
- package/server/services/workshop/ontology/subgraph.service.ts +113 -113
- package/server/services/workshop/plugins/host/api.mjs +90 -90
- package/server/services/workshop/plugins/host/config.mjs +135 -135
- package/server/services/workshop/plugins/host/index.mjs +23 -23
- package/server/services/workshop/plugins/host/init.mjs +109 -109
- package/server/services/workshop/plugins/host/load.mjs +321 -321
- package/server/services/workshop/plugins/host/reload.mjs +94 -94
- package/server/services/workshop/plugins/host/rollback.mjs +72 -72
- package/server/services/workshop/plugins/host/state.mjs +54 -54
- package/server/services/workshop/plugins/host/toggle.mjs +64 -64
- package/server/services/workshop/plugins/host.mjs +9 -9
- package/server/services/workshop/runtime/agent-runtime/facade.ts +7 -7
- package/server/services/workshop/runtime/agent-runtime/helpers.ts +18 -18
- package/server/services/workshop/runtime/agent-runtime/index.ts +19 -19
- package/server/services/workshop/runtime/agent-runtime/lifecycle.ts +137 -137
- package/server/services/workshop/runtime/chat-mention.ts +164 -164
- package/server/services/workshop/runtime/chat-projection.ts +246 -246
- package/server/services/workshop/runtime/manager/admin-agents.ts +268 -268
- package/server/services/workshop/runtime/manager/bus.ts +182 -182
- package/server/services/workshop/runtime/manager/channel-template-constants.ts +20 -20
- package/server/services/workshop/runtime/manager/chat-reply.ts +181 -181
- package/server/services/workshop/runtime/manager/chat.ts +384 -384
- package/server/services/workshop/runtime/manager/facade.ts +24 -24
- package/server/services/workshop/runtime/manager/helpers.ts +119 -119
- package/server/services/workshop/runtime/manager/index.ts +42 -42
- package/server/services/workshop/runtime/manager/internal.ts +73 -73
- package/server/services/workshop/runtime/manager/notifications.ts +108 -108
- package/server/services/workshop/runtime/manager/teams.ts +148 -148
- package/server/services/workshop/runtime/memory/contracts.ts +18 -18
- package/server/services/workshop/runtime/memory/facade.ts +10 -10
- package/server/services/workshop/runtime/memory/helpers.ts +196 -196
- package/server/services/workshop/runtime/memory/index.ts +27 -27
- package/server/services/workshop/runtime/memory/score.ts +33 -33
- package/server/services/workshop/runtime/memory/state.ts +40 -40
- package/server/services/workshop/runtime/monitor.ts +3 -3
- package/server/services/workshop/runtime/platform-notice.ts +113 -113
- package/server/services/workshop/runtime/schedule-runtime.ts +347 -347
- package/server/services/workshop/runtime/scheduler-loop/contracts.ts +29 -29
- package/server/services/workshop/runtime/scheduler-loop/facade.ts +7 -7
- package/server/services/workshop/runtime/scheduler-loop/helpers.ts +14 -14
- package/server/services/workshop/runtime/scheduler-loop/index.ts +16 -16
- package/server/services/workshop/runtime/task-engine/facade.ts +7 -7
- package/server/services/workshop/runtime/task-engine/index.ts +15 -15
- package/server/services/workshop/runtime/task-engine/types.ts +3 -3
- package/server/services/workshop/runtime/user-notification-hub.ts +192 -192
- package/server/types/pg.d.ts +49 -49
- package/server/utils/approval-gate.ts +67 -67
- package/server/utils/mojibake-guard.ts +29 -29
- package/server/utils/stability-severity.ts +77 -77
- package/shared/config/groups.mjs +241 -241
- package/shared/dcw-protocol/catalog.ts +232 -232
- package/shared/dcw-protocol/closed-loop.ts +137 -137
- package/shared/lru.mjs +97 -97
- package/tui/README.md +74 -74
- package/tui/aw-tui.mjs +445 -445
- package/tui/commands/index.mjs +287 -287
- package/tui/components/chat-log.mjs +42 -42
- package/tui/components/monitor-pane.mjs +39 -39
- package/tui/components/root.mjs +53 -53
- package/tui/components/status-bar.mjs +33 -33
- package/tui/lib/api.mjs +82 -82
- package/tui/lib/pickers.mjs +121 -121
- package/tui/lib/reducers.mjs +218 -218
- package/tui/lib/state.mjs +86 -86
- package/tui/lib/virtual-terminal.mjs +48 -48
- package/tui/lib/ws.mjs +125 -125
- package/tui/theme.mjs +38 -38
- package/.output/.AgentWorkShop/aml-python/__pycache__/aml_eval.cpython-312.pyc +0 -0
- package/.output/.AgentWorkShop/aml-python/__pycache__/amlkit.cpython-312.pyc +0 -0
- package/.output/.AgentWorkShop/aml-python/__pycache__/train-example.cpython-312.pyc +0 -0
- package/.output/.AgentWorkShop/aml-python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
- package/.output/public/_nuxt/BRYBzVMJ.js +0 -1
- package/.output/public/_nuxt/BW2uTUx52.js +0 -2
- package/.output/public/_nuxt/BtZKe9ZV.js +0 -1
- package/.output/public/_nuxt/CfFUK6932.js +0 -2
- package/.output/public/_nuxt/DhW7cFOa.js +0 -1
- package/.output/public/_nuxt/OmpTerminalPanel.ComMDrA8.css +0 -1
- package/.output/public/_nuxt/PluginSlot.CGH0vb95.css +0 -1
- package/.output/public/_nuxt/TownView.CC3t-Dte.css +0 -1
- package/.output/public/_nuxt/aml.PalMp-5n.css +0 -1
- package/.output/public/_nuxt/builds/meta/fa0af8b5-3929-428d-a6de-3b5cc6b8248f.json +0 -1
- package/.output/public/_nuxt/permissions.DxuOOIqQ.css +0 -1
- package/.output/public/_nuxt/schedules.BXNJ9q_I.css +0 -1
- package/.output/public/_nuxt/tools.BwXFAb-X.css +0 -1
- package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs +0 -716
- package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs.map +0 -1
- package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs +0 -72
- package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs.map +0 -1
- package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs +0 -942
- package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs.map +0 -1
- package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs +0 -141
- package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs.map +0 -1
- package/.output/server/chunks/build/TownView-BWMDbosY.mjs +0 -6489
- package/.output/server/chunks/build/TownView-BWMDbosY.mjs.map +0 -1
- package/.output/server/chunks/build/_id_-BK-t8nRG.mjs +0 -392
- package/.output/server/chunks/build/_id_-BK-t8nRG.mjs.map +0 -1
- package/.output/server/chunks/build/_id_-CZPlPDm4.mjs +0 -2045
- package/.output/server/chunks/build/_id_-CZPlPDm4.mjs.map +0 -1
- package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs +0 -14297
- package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs.map +0 -1
- package/.output/server/chunks/build/agents-CpNLdI8E.mjs +0 -1078
- package/.output/server/chunks/build/agents-CpNLdI8E.mjs.map +0 -1
- package/.output/server/chunks/build/alert-D0ivtTGy.mjs +0 -263
- package/.output/server/chunks/build/alert-D0ivtTGy.mjs.map +0 -1
- package/.output/server/chunks/build/aml-DRAFRcGU.mjs +0 -814
- package/.output/server/chunks/build/aml-DRAFRcGU.mjs.map +0 -1
- package/.output/server/chunks/build/analysis-p-dBkjoK.mjs +0 -533
- package/.output/server/chunks/build/analysis-p-dBkjoK.mjs.map +0 -1
- package/.output/server/chunks/build/api-B4Om0mEc.mjs.map +0 -1
- package/.output/server/chunks/build/api-BEW_ebY_.mjs.map +0 -1
- package/.output/server/chunks/build/api-BsAgXWxi.mjs.map +0 -1
- package/.output/server/chunks/build/api-error-BwAQLw44.mjs +0 -47
- package/.output/server/chunks/build/api-error-BwAQLw44.mjs.map +0 -1
- package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs +0 -81
- package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs.map +0 -1
- package/.output/server/chunks/build/board-Dl2Ar22r.mjs +0 -178
- package/.output/server/chunks/build/board-Dl2Ar22r.mjs.map +0 -1
- package/.output/server/chunks/build/card-Cqk0Ur-L.mjs +0 -953
- package/.output/server/chunks/build/card-Cqk0Ur-L.mjs.map +0 -1
- package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs +0 -942
- package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs.map +0 -1
- package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs +0 -439
- package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs.map +0 -1
- package/.output/server/chunks/build/client-only-qNA2OVV_.mjs +0 -43
- package/.output/server/chunks/build/client-only-qNA2OVV_.mjs.map +0 -1
- package/.output/server/chunks/build/core-CgTOPS4t.mjs +0 -294
- package/.output/server/chunks/build/core-CgTOPS4t.mjs.map +0 -1
- package/.output/server/chunks/build/daq-CdxcfY_G.mjs +0 -1266
- package/.output/server/chunks/build/daq-CdxcfY_G.mjs.map +0 -1
- package/.output/server/chunks/build/data-D8uX1dnm.mjs +0 -481
- package/.output/server/chunks/build/data-D8uX1dnm.mjs.map +0 -1
- package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +0 -505
- package/.output/server/chunks/build/dcw-BlDQtS4q.mjs.map +0 -1
- package/.output/server/chunks/build/default-CNWS6NUw.mjs +0 -2353
- package/.output/server/chunks/build/default-CNWS6NUw.mjs.map +0 -1
- package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs +0 -406
- package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs.map +0 -1
- package/.output/server/chunks/build/drawer-Caji0PLs.mjs +0 -834
- package/.output/server/chunks/build/drawer-Caji0PLs.mjs.map +0 -1
- package/.output/server/chunks/build/dropdown-BNwTVGde.mjs +0 -14
- package/.output/server/chunks/build/dropdown-BNwTVGde.mjs.map +0 -1
- package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs +0 -540
- package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs.map +0 -1
- package/.output/server/chunks/build/es-Bxu10NJ2.mjs.map +0 -1
- package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs +0 -2448
- package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs.map +0 -1
- package/.output/server/chunks/build/form-D_UpWPN4.mjs +0 -4712
- package/.output/server/chunks/build/form-D_UpWPN4.mjs.map +0 -1
- package/.output/server/chunks/build/hasIn-DBdElbjM.mjs +0 -553
- package/.output/server/chunks/build/hasIn-DBdElbjM.mjs.map +0 -1
- package/.output/server/chunks/build/hitl-Bd30yr1J.mjs +0 -132
- package/.output/server/chunks/build/hitl-Bd30yr1J.mjs.map +0 -1
- package/.output/server/chunks/build/input-GtPuSEgt.mjs +0 -2181
- package/.output/server/chunks/build/input-GtPuSEgt.mjs.map +0 -1
- package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +0 -1120
- package/.output/server/chunks/build/input-number-BNlNDK7H.mjs.map +0 -1
- package/.output/server/chunks/build/interval-DvHBIIZh.mjs +0 -9
- package/.output/server/chunks/build/interval-DvHBIIZh.mjs.map +0 -1
- package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs +0 -7
- package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs.map +0 -1
- package/.output/server/chunks/build/logs-pRb-TMWa.mjs +0 -427
- package/.output/server/chunks/build/logs-pRb-TMWa.mjs.map +0 -1
- package/.output/server/chunks/build/menu-BXt-X0dt.mjs +0 -1952
- package/.output/server/chunks/build/menu-BXt-X0dt.mjs.map +0 -1
- package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs +0 -2253
- package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs.map +0 -1
- package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs +0 -1406
- package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +0 -1
- package/.output/server/chunks/build/operations-SMQrRAcr.mjs +0 -311
- package/.output/server/chunks/build/operations-SMQrRAcr.mjs.map +0 -1
- package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +0 -202
- package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +0 -1
- package/.output/server/chunks/build/pages-AFRP4-EL.mjs +0 -542
- package/.output/server/chunks/build/pages-AFRP4-EL.mjs.map +0 -1
- package/.output/server/chunks/build/pagination-DTAconUo.mjs +0 -1346
- package/.output/server/chunks/build/pagination-DTAconUo.mjs.map +0 -1
- package/.output/server/chunks/build/permissions-DgXQZSyx.mjs +0 -637
- package/.output/server/chunks/build/permissions-DgXQZSyx.mjs.map +0 -1
- package/.output/server/chunks/build/plugins-LRjaSEZy.mjs +0 -272
- package/.output/server/chunks/build/plugins-LRjaSEZy.mjs.map +0 -1
- package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs +0 -340
- package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs.map +0 -1
- package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs +0 -78
- package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs.map +0 -1
- package/.output/server/chunks/build/schedules-dSnr8url.mjs +0 -7172
- package/.output/server/chunks/build/schedules-dSnr8url.mjs.map +0 -1
- package/.output/server/chunks/build/segmented-D3HWtHPw.mjs +0 -341
- package/.output/server/chunks/build/segmented-D3HWtHPw.mjs.map +0 -1
- package/.output/server/chunks/build/select-B3Dsb9yq.mjs +0 -3923
- package/.output/server/chunks/build/select-B3Dsb9yq.mjs.map +0 -1
- package/.output/server/chunks/build/settings-BrIhnS2Z.mjs +0 -1014
- package/.output/server/chunks/build/settings-BrIhnS2Z.mjs.map +0 -1
- package/.output/server/chunks/build/space-Dwu2Skt8.mjs +0 -110
- package/.output/server/chunks/build/space-Dwu2Skt8.mjs.map +0 -1
- package/.output/server/chunks/build/spin-C2cuvGth.mjs +0 -357
- package/.output/server/chunks/build/spin-C2cuvGth.mjs.map +0 -1
- package/.output/server/chunks/build/studio-cdoNCfyy.mjs +0 -332
- package/.output/server/chunks/build/studio-cdoNCfyy.mjs.map +0 -1
- package/.output/server/chunks/build/switch-CyR-H6Fb.mjs +0 -377
- package/.output/server/chunks/build/switch-CyR-H6Fb.mjs.map +0 -1
- package/.output/server/chunks/build/table-CmVD-cA9.mjs +0 -7546
- package/.output/server/chunks/build/table-CmVD-cA9.mjs.map +0 -1
- package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs +0 -1924
- package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs.map +0 -1
- package/.output/server/chunks/build/tag-y0sn-xv9.mjs +0 -1156
- package/.output/server/chunks/build/tag-y0sn-xv9.mjs.map +0 -1
- package/.output/server/chunks/build/teams-B1d32eHK.mjs +0 -1203
- package/.output/server/chunks/build/teams-B1d32eHK.mjs.map +0 -1
- package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs +0 -1062
- package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs.map +0 -1
- package/.output/server/chunks/build/tools-s_9U1Djj.mjs +0 -487
- package/.output/server/chunks/build/tools-s_9U1Djj.mjs.map +0 -1
- package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs +0 -920
- package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs.map +0 -1
- package/.output/server/chunks/build/town-B5aoiG98.mjs +0 -133
- package/.output/server/chunks/build/town-B5aoiG98.mjs.map +0 -1
- package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs +0 -124
- package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs.map +0 -1
- package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs +0 -77
- package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs.map +0 -1
- package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs +0 -117
- package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs.map +0 -1
- package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs +0 -133
- package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs +0 -92
- package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs +0 -86
- package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs +0 -194
- package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs +0 -89
- package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs +0 -267
- package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs +0 -93
- package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs +0 -86
- package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs.map +0 -1
- package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs +0 -130
- package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs.map +0 -1
- package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs +0 -129
- package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +0 -142
- package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs +0 -70
- package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs +0 -79
- package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs +0 -176
- package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +0 -99
- package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +0 -159
- package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +0 -222
- package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs +0 -136
- package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +0 -395
- package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs.map +0 -1
- package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +0 -187
- package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs.map +0 -1
- package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs +0 -153
- package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +0 -219
- package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwCards-SaiImIYQ.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs +0 -184
- package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs +0 -148
- package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs +0 -71
- package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwLedger-0ie-0WTc.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs +0 -137
- package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs +0 -104
- package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs +0 -121
- package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs +0 -93
- package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs +0 -98
- package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs +0 -88
- package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs +0 -258
- package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +0 -452
- package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs +0 -91
- package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs.map +0 -1
- package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs +0 -140
- package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs.map +0 -1
- package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs +0 -128
- package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs.map +0 -1
- package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs +0 -107
- package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs.map +0 -1
- package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs +0 -55
- package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs.map +0 -1
- package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs +0 -88
- package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs.map +0 -1
- package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs +0 -150
- package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs.map +0 -1
- package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs +0 -83
- package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs.map +0 -1
- package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs +0 -135
- package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs.map +0 -1
- package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs +0 -91
- package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs.map +0 -1
- package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs +0 -195
- package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs.map +0 -1
- package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs +0 -149
- package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs.map +0 -1
- package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs +0 -156
- package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs +0 -79
- package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs +0 -84
- package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs +0 -97
- package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs +0 -80
- package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs +0 -103
- package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs.map +0 -1
- package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs +0 -123
- package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs.map +0 -1
- package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs +0 -115
- package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs.map +0 -1
- package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs +0 -87
- package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs.map +0 -1
- package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs +0 -118
- package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs.map +0 -1
- package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs +0 -92
- package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs +0 -141
- package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs +0 -138
- package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs +0 -119
- package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs +0 -1659
- package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkspaceAuth-Dlvj9csD.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs +0 -92
- package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs +0 -168
- package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs.map +0 -1
- package/.output/server/chunks/build/users-DjiVC_tS.mjs +0 -569
- package/.output/server/chunks/build/users-DjiVC_tS.mjs.map +0 -1
- package/.output/server/chunks/build/workshop-1gKeDASV.mjs +0 -546
- package/.output/server/chunks/build/workshop-1gKeDASV.mjs.map +0 -1
- package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.json +0 -1
- package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/1459e6269990a5d229b9228c8b2f62ffaa7d350068380ae8b875fee0db45cca6.source +0 -180
- package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/c2991e909c70c5c12b90a407c7adcf63384c51668a2b334e6e047fa675c268fe.source +0 -305
- package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/e09129039d1e27e3fac24becc9bdafd2d1a7c8049bff24173df007be865f0165.source +0 -264
- package/app/.mimosa/hook-status/sess_05189059-e42d-4188-8911-4f7baabe009b-28ef7c75ea.json +0 -14
- package/scripts/e2e-direct-rest-simulator-paper.mjs +0 -624
- package/scripts/e2e-pi-simulator-paper.mjs +0 -2316
- package/scripts/e2e-registered-harness-simulator-paper.mjs +0 -1926
- package/scripts/e2e-simulator-optimizer-paper.mjs +0 -264
- package/scripts/fixtures/omp-paper-harness.mjs +0 -163
- package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.json +0 -1
- package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/942d2679b87b96c612b4f2a425c3ccc5b6f3234f0cf589a8441602f866fbe277.source +0 -41
- package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/dd617a82339d2c61e49e28e416aabeb2fc100fb3cb1beca18d02dfb833214af6.source +0 -51
- package/server/.mimosa/hook-status/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2-e67b6b91bf.json +0 -14
- package/server/services/workshop/.mimosa/hook-state/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f.json +0 -1
- package/server/services/workshop/.mimosa/hook-status/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f-e6b75bbfe6.json +0 -14
- package/server/services/workshop/agents/omp-agent/supervision-history.ts +0 -38
- package/server/services/workshop/aml/python/__pycache__/aml_eval.cpython-312.pyc +0 -0
- package/server/services/workshop/aml/python/__pycache__/amlkit.cpython-312.pyc +0 -0
- package/server/services/workshop/aml/python/__pycache__/train-example.cpython-312.pyc +0 -0
- package/server/services/workshop/aml/python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
- package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.json +0 -1
- package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.mvjqkcs6-68688-fb7131a89c.baseline/190a6772a4e43801737b4ba6072eb9d53d3099b5d8a9e6f57bc5e8592a26a6c4.source +0 -274
- package/server/services/workshop/optimization/python/.mimosa/hook-status/session_187ec97f45d4bd02369bbe94da527cf1-01ed7f04fa.json +0 -14
- package/server/services/workshop/optimization/python/__pycache__/problems.cpython-312.pyc +0 -0
- /package/.output/public/_nuxt/{9j2J4k4w.js → 9j2J4k4w2.js} +0 -0
- /package/.output/public/_nuxt/{BY3Lbz3h2.js → BY3Lbz3h.js} +0 -0
- /package/.output/public/_nuxt/{Iub61dX92.js → Iub61dX9.js} +0 -0
- /package/.output/public/_nuxt/{Q-JpBT032.js → Q-JpBT03.js} +0 -0
- /package/.output/public/_nuxt/{dVw8IHY62.js → dVw8IHY6.js} +0 -0
- /package/.output/public/_nuxt/{k9b520K-.js → k9b520K-2.js} +0 -0
|
@@ -1,2316 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Bounded integration evidence for AgentWorkShop's registered `pi` harness.
|
|
4
|
-
* Pi receives a deterministic OpenAI-compatible model response from a local
|
|
5
|
-
* loopback fixture; the actual Pi CLI, Pi extension, AgentWorkShop bridge,
|
|
6
|
-
* protected approval API, simulator, device readback, and run-tagged sampling
|
|
7
|
-
* remain in the execution path. No external model or provider is used.
|
|
8
|
-
*/
|
|
9
|
-
import { spawn, spawnSync } from 'node:child_process'
|
|
10
|
-
import { createHash, randomBytes } from 'node:crypto'
|
|
11
|
-
import { chmodSync, closeSync, copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, symlinkSync, writeFileSync } from 'node:fs'
|
|
12
|
-
import { createServer } from 'node:net'
|
|
13
|
-
import { createServer as createHttpServer } from 'node:http'
|
|
14
|
-
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
|
15
|
-
import { fileURLToPath } from 'node:url'
|
|
16
|
-
import { setTimeout as delay } from 'node:timers/promises'
|
|
17
|
-
import { resolveRunMode } from '../shared/config/home.mjs'
|
|
18
|
-
|
|
19
|
-
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
20
|
-
const AW_PORT = 3997
|
|
21
|
-
const SIM_PORT = 4020
|
|
22
|
-
const MODEL_API_PORT = 4021
|
|
23
|
-
const MQTT_PORT = 18840
|
|
24
|
-
const OFFLINE_TSDB_PORT = 45321
|
|
25
|
-
const OFFLINE_OBJECTSTORE_PORT = 45322
|
|
26
|
-
const OFFLINE_APP_MQTT_QUEUE_PORT = 45323
|
|
27
|
-
const FORBIDDEN_PORT = 4010
|
|
28
|
-
const APP_BASE = `http://127.0.0.1:${AW_PORT}`
|
|
29
|
-
const SIM_BASE = `http://127.0.0.1:${SIM_PORT}`
|
|
30
|
-
const SIM_SOURCE = resolve(REPO, 'plc-node-simulator')
|
|
31
|
-
const VERSION = JSON.parse(readFileSync(join(REPO, 'package.json'), 'utf8')).version
|
|
32
|
-
const TAG = `pi${Date.now().toString(36)}`
|
|
33
|
-
mkdirSync(join(REPO, '.omc'), { recursive: true })
|
|
34
|
-
const ROOT = mkdtempSync(join(REPO, '.omc', 'registered-pi-paper-'))
|
|
35
|
-
const HOME = join(ROOT, 'aw-home')
|
|
36
|
-
const EVIDENCE_PATH = join(ROOT, 'evidence.json')
|
|
37
|
-
const PI_AGENT_DIR = join(HOME, 'pi-agent')
|
|
38
|
-
const OUTPUT_BASE = join(REPO, 'docs', 'audit', 'evidence', '2026-10-25-current-cross-scene')
|
|
39
|
-
const OUTPUT_DIR = join(OUTPUT_BASE, `r23-pi-registered-harness-${new Date().toISOString().replace(/[-:.]/g, '').replace('T', '-').slice(0, 15)}-${randomBytes(3).toString('hex')}`)
|
|
40
|
-
const PI_MODELS_PATH = join(PI_AGENT_DIR, 'models.json')
|
|
41
|
-
const SIM_ROOT = join(ROOT, 'simulator')
|
|
42
|
-
const SIM_LOG = join(ROOT, 'simulator.log')
|
|
43
|
-
const APP_LOG = join(ROOT, 'agentworkshop.log')
|
|
44
|
-
const EMPTY_DOTENV = join(HOME, 'empty.env')
|
|
45
|
-
const ISOLATED_PROMPTS_DIR = join(HOME, 'prompts')
|
|
46
|
-
const NUXT_CLI = join(REPO, 'node_modules', 'nuxt', 'bin', 'nuxt.mjs')
|
|
47
|
-
const RAG_BRIDGE_DISABLED_BASE_URL = 'http://paper-harness-outbound-disabled.invalid'
|
|
48
|
-
const SIM_LOG_FD = openSync(SIM_LOG, 'a')
|
|
49
|
-
const APP_LOG_FD = openSync(APP_LOG, 'a')
|
|
50
|
-
const HARNESS_MODE = 'pi-local-fixture'
|
|
51
|
-
const PI_PROVIDER = 'agentworkshop-local'
|
|
52
|
-
const PI_MODEL = 'aw-deterministic-paper-fixture'
|
|
53
|
-
const PI_COMMAND = join(dirname(process.execPath), 'pi.cmd')
|
|
54
|
-
const PI_CLI_PACKAGE_PATH = join(dirname(process.execPath), 'node_modules', '@mariozechner', 'pi-coding-agent', 'package.json')
|
|
55
|
-
const PI_APPROVAL_TIMEOUT_MS = 180_000
|
|
56
|
-
const PI_TASK_COMPLETION_TIMEOUT_MS = 180_000
|
|
57
|
-
const PI_PROMPT_TIMEOUT_MS = 180_000
|
|
58
|
-
// Keep the shared evidence helpers usable while this runner selects only the
|
|
59
|
-
// local Pi fixture mode; no OMP CLI or external model is invoked.
|
|
60
|
-
const REAL_OMP_PROVIDER = PI_PROVIDER
|
|
61
|
-
const REAL_OMP_MODEL = PI_MODEL
|
|
62
|
-
const REAL_OMP_TRIALS_PER_SCENE = 1
|
|
63
|
-
const REAL_OMP_APPROVAL_TIMEOUT_MS = PI_APPROVAL_TIMEOUT_MS
|
|
64
|
-
const REAL_OMP_TASK_COMPLETION_TIMEOUT_MS = PI_TASK_COMPLETION_TIMEOUT_MS
|
|
65
|
-
const PI_API_TRACE_PATH = join(ROOT, 'pi-model-api-trace.json')
|
|
66
|
-
const piApiTrace = []
|
|
67
|
-
let piFixtureTarget = null
|
|
68
|
-
let piApiServer
|
|
69
|
-
|
|
70
|
-
const evidence = {
|
|
71
|
-
schemaVersion: 1,
|
|
72
|
-
experiment: {
|
|
73
|
-
id: TAG,
|
|
74
|
-
projectVersion: VERSION,
|
|
75
|
-
campaign: 'Pi registered-harness local-fixture cross-scene E2E',
|
|
76
|
-
harnessMode: HARNESS_MODE,
|
|
77
|
-
provider: PI_PROVIDER,
|
|
78
|
-
model: PI_MODEL,
|
|
79
|
-
trialsPerScene: 1,
|
|
80
|
-
runOutcomes: [],
|
|
81
|
-
modelFixture: 'deterministic local OpenAI-compatible streaming API; fixture scripts one recipe_trial call and one complete_task call per scene; no LLM or external provider',
|
|
82
|
-
startedAt: new Date().toISOString(),
|
|
83
|
-
postTrialSnapshotDelaySeconds: 20,
|
|
84
|
-
scenes: [],
|
|
85
|
-
},
|
|
86
|
-
isolation: {
|
|
87
|
-
result: 'pending',
|
|
88
|
-
awHome: 'fresh isolated AW_HOME',
|
|
89
|
-
appBase: APP_BASE,
|
|
90
|
-
simulatorBase: SIM_BASE,
|
|
91
|
-
simulatorMqttLoopbackPort: MQTT_PORT,
|
|
92
|
-
appMqttQueueOfflineProbePort: OFFLINE_APP_MQTT_QUEUE_PORT,
|
|
93
|
-
explicitLoopbackOnly: true,
|
|
94
|
-
externalLlmDisabled: true,
|
|
95
|
-
modelApiBase: `http://127.0.0.1:${MODEL_API_PORT}/v1`,
|
|
96
|
-
forbiddenServicePortExcluded: true,
|
|
97
|
-
checks: [],
|
|
98
|
-
},
|
|
99
|
-
checks: [],
|
|
100
|
-
status: 'running',
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let appProcess
|
|
104
|
-
let simProcess
|
|
105
|
-
let currentStage = 'preflight'
|
|
106
|
-
let currentScene
|
|
107
|
-
let authToken
|
|
108
|
-
let syntheticAdminId
|
|
109
|
-
let isolatedPluginNames = []
|
|
110
|
-
let expectedPluginNames = []
|
|
111
|
-
const allowedEnabledPluginNames = ['rag-bridge']
|
|
112
|
-
let projectPluginTreeAtPrepare
|
|
113
|
-
let projectPromptTreeAtPrepare
|
|
114
|
-
let promptTreeAtPrepare
|
|
115
|
-
const generatedSessionPassword = randomBytes(32).toString('hex')
|
|
116
|
-
const children = new Set()
|
|
117
|
-
const allocatedDevicePorts = []
|
|
118
|
-
const CHILD_OS_ENV_KEYS = process.platform === 'win32'
|
|
119
|
-
? ['PATH', 'PATHEXT', 'SystemRoot', 'WINDIR', 'TEMP', 'TMP', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'HOMEDRIVE', 'HOMEPATH', 'ProgramData']
|
|
120
|
-
: ['PATH', 'HOME', 'TMPDIR', 'TMP', 'TEMP', 'LANG', 'LC_ALL']
|
|
121
|
-
const CHILD_EXTRA_ENV_KEYS = new Set(['SIM_PORT', 'MQTT_BROKER_PORT'])
|
|
122
|
-
const RELEASE_CHECK_SUFFIXES = ['-process-stopped', '-port-released']
|
|
123
|
-
|
|
124
|
-
function check(id, pass, detail = {}) {
|
|
125
|
-
evidence.checks.push({ id, status: pass ? 'pass' : 'fail', detail })
|
|
126
|
-
if (!pass) throw new Error(`check failed: ${id}`)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function noteIsolation(id, pass, detail = {}) {
|
|
130
|
-
evidence.isolation.checks.push({ id, status: pass ? 'pass' : 'fail', detail })
|
|
131
|
-
if (!pass) throw new Error(`isolation preflight failed: ${id}`)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function safeText(value, limit = 500) {
|
|
135
|
-
let text = String(value ?? '')
|
|
136
|
-
if (authToken) text = text.split(authToken).join('[REDACTED]')
|
|
137
|
-
text = text.replace(/\but-[a-f\d]{32}\b/gi, '[REDACTED_TOKEN]')
|
|
138
|
-
text = text.replace(/\bBearer\s+[^\s,;]+/gi, 'Bearer [REDACTED]')
|
|
139
|
-
text = text.replace(/\b(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|secret)\s*[:=]\s*["']?[^\s,"'}]+/gi, '[REDACTED_CREDENTIAL]')
|
|
140
|
-
text = text.replace(/\bsk-[A-Za-z0-9_-]{16,}\b/g, '[REDACTED_CREDENTIAL]')
|
|
141
|
-
return text.slice(0, limit)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function compactError(error) {
|
|
145
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
146
|
-
return { name: error instanceof Error ? error.name : 'Error', message: safeText(message) }
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async function readRequestJson(req) {
|
|
150
|
-
const chunks = []
|
|
151
|
-
let bytes = 0
|
|
152
|
-
for await (const chunk of req) {
|
|
153
|
-
bytes += chunk.length
|
|
154
|
-
if (bytes > 2_000_000) throw new Error('model fixture rejected request larger than 2 MB')
|
|
155
|
-
chunks.push(chunk)
|
|
156
|
-
}
|
|
157
|
-
return JSON.parse(Buffer.concat(chunks).toString('utf8'))
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function sendSse(res, chunks) {
|
|
161
|
-
res.writeHead(200, {
|
|
162
|
-
'content-type': 'text/event-stream; charset=utf-8',
|
|
163
|
-
'cache-control': 'no-cache, no-transform',
|
|
164
|
-
connection: 'keep-alive',
|
|
165
|
-
})
|
|
166
|
-
for (const chunk of chunks) res.write(`data: ${JSON.stringify(chunk)}\n\n`)
|
|
167
|
-
res.write('data: [DONE]\n\n')
|
|
168
|
-
res.end()
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function chatChunk(id, delta, finishReason = null, usage) {
|
|
172
|
-
return {
|
|
173
|
-
id,
|
|
174
|
-
object: 'chat.completion.chunk',
|
|
175
|
-
created: Math.floor(Date.now() / 1000),
|
|
176
|
-
model: PI_MODEL,
|
|
177
|
-
choices: [{ index: 0, delta, finish_reason: finishReason }],
|
|
178
|
-
...(usage ? { usage } : {}),
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async function startPiModelFixture() {
|
|
183
|
-
piApiServer = createHttpServer(async (req, res) => {
|
|
184
|
-
if (req.method !== 'POST' || req.url !== '/v1/chat/completions') {
|
|
185
|
-
res.writeHead(404, { 'content-type': 'application/json' })
|
|
186
|
-
res.end(JSON.stringify({ error: 'fixture route not found' }))
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
const body = await readRequestJson(req)
|
|
191
|
-
const target = piFixtureTarget
|
|
192
|
-
const messages = Array.isArray(body.messages) ? body.messages : []
|
|
193
|
-
const toolNames = (Array.isArray(body.tools) ? body.tools : [])
|
|
194
|
-
.map(tool => String(tool?.function?.name ?? ''))
|
|
195
|
-
.filter(Boolean)
|
|
196
|
-
const roles = messages.map(message => String(message?.role ?? ''))
|
|
197
|
-
const toolMessages = messages.filter(message => String(message?.role ?? '') === 'tool')
|
|
198
|
-
const latestToolMessage = toolMessages.at(-1)
|
|
199
|
-
const returnedToolContent = latestToolMessage?.content
|
|
200
|
-
const returnedToolText = typeof returnedToolContent === 'string'
|
|
201
|
-
? returnedToolContent
|
|
202
|
-
: JSON.stringify(returnedToolContent ?? '')
|
|
203
|
-
const callIndex = target ? piApiTrace.filter(item => item.scene === target.scene).length : 0
|
|
204
|
-
const requestId = `fixture-${target?.scene ?? 'unassigned'}-${callIndex + 1}`
|
|
205
|
-
const requestEvidence = {
|
|
206
|
-
requestId,
|
|
207
|
-
scene: target?.scene ?? null,
|
|
208
|
-
requestModel: safeText(body.model, 120),
|
|
209
|
-
apiPath: req.url,
|
|
210
|
-
loopbackPeer: req.socket.remoteAddress === '127.0.0.1' || req.socket.remoteAddress === '::ffff:127.0.0.1',
|
|
211
|
-
apiKeyMatchesLocalFixture: req.headers.authorization === 'Bearer local-fixture-key-not-a-secret',
|
|
212
|
-
streamRequested: body.stream === true,
|
|
213
|
-
toolNames,
|
|
214
|
-
messageRoles: roles,
|
|
215
|
-
toolResultMessageCount: toolMessages.length,
|
|
216
|
-
toolResultCallId: safeText(latestToolMessage?.tool_call_id ?? '', 120),
|
|
217
|
-
toolResultText: toolMessages.length ? safeText(returnedToolText, 1200) : null,
|
|
218
|
-
response: null,
|
|
219
|
-
}
|
|
220
|
-
if (!target || body.model !== PI_MODEL || !requestEvidence.loopbackPeer || !requestEvidence.apiKeyMatchesLocalFixture || body.stream !== true) {
|
|
221
|
-
throw new Error('model fixture rejected a request outside the expected loopback Pi custom-provider configuration')
|
|
222
|
-
}
|
|
223
|
-
const id = `chatcmpl-${requestId}`
|
|
224
|
-
if (callIndex === 0) {
|
|
225
|
-
const promptText = JSON.stringify(messages)
|
|
226
|
-
if (!toolNames.includes('recipe_trial')
|
|
227
|
-
|| roles.includes('tool')
|
|
228
|
-
|| !promptText.includes(target.recipeId)
|
|
229
|
-
|| !promptText.includes(target.nodeId)
|
|
230
|
-
|| !promptText.includes(String(target.value))) {
|
|
231
|
-
throw new Error(`${target.scene} initial Pi request did not include the registered recipe_trial declaration and task identifiers`)
|
|
232
|
-
}
|
|
233
|
-
const args = JSON.stringify({
|
|
234
|
-
recipe_id: target.recipeId,
|
|
235
|
-
params: [{ node_id: target.nodeId, value: target.value }],
|
|
236
|
-
hypothesis: 'Deterministic local fixture selection for a bounded simulator integration check.',
|
|
237
|
-
})
|
|
238
|
-
requestEvidence.response = { type: 'tool_call', toolName: 'recipe_trial', candidate: target.value }
|
|
239
|
-
piApiTrace.push(requestEvidence)
|
|
240
|
-
sendSse(res, [
|
|
241
|
-
chatChunk(id, { role: 'assistant' }),
|
|
242
|
-
chatChunk(id, { tool_calls: [{ index: 0, id: `call-${target.scene}`, type: 'function', function: { name: 'recipe_trial', arguments: args } }] }),
|
|
243
|
-
chatChunk(id, {}, 'tool_calls', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
|
|
244
|
-
])
|
|
245
|
-
return
|
|
246
|
-
}
|
|
247
|
-
if (callIndex === 1) {
|
|
248
|
-
if (!roles.includes('tool') || !toolNames.includes('recipe_trial')) {
|
|
249
|
-
throw new Error(`${target.scene} Pi follow-up request did not contain the platform tool result`)
|
|
250
|
-
}
|
|
251
|
-
if (toolMessages.length !== 1 || !requestEvidence.toolResultText || requestEvidence.toolResultCallId !== `call-${target.scene}`) {
|
|
252
|
-
throw new Error(`${target.scene} Pi follow-up did not preserve exactly one non-empty platform tool result`)
|
|
253
|
-
}
|
|
254
|
-
requestEvidence.response = { type: 'tool_call', toolName: 'complete_task', taskId: target.taskId }
|
|
255
|
-
piApiTrace.push(requestEvidence)
|
|
256
|
-
sendSse(res, [
|
|
257
|
-
chatChunk(id, { role: 'assistant' }),
|
|
258
|
-
chatChunk(id, { tool_calls: [{ index: 0, id: `complete-${target.scene}`, type: 'function', function: { name: 'complete_task', arguments: JSON.stringify({
|
|
259
|
-
task_id: target.taskId,
|
|
260
|
-
summary: 'Completed the bounded local simulator integration check after the approved recipe trial returned its verified command result.',
|
|
261
|
-
deliverable: `Task ${target.taskId}: the registered Pi host-tool bridge returned the recipe_trial result for candidate ${target.value}; this is integration evidence, not a process-improvement claim.`,
|
|
262
|
-
}) } }] }),
|
|
263
|
-
chatChunk(id, {}, 'tool_calls', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
|
|
264
|
-
])
|
|
265
|
-
return
|
|
266
|
-
}
|
|
267
|
-
if (callIndex === 2) {
|
|
268
|
-
if (!roles.includes('tool') || toolMessages.length !== 2 || !requestEvidence.toolResultText
|
|
269
|
-
|| requestEvidence.toolResultCallId !== `complete-${target.scene}`
|
|
270
|
-
|| !/COMPLETED/.test(requestEvidence.toolResultText)) {
|
|
271
|
-
throw new Error(`${target.scene} Pi follow-up did not preserve the successful complete_task result`)
|
|
272
|
-
}
|
|
273
|
-
requestEvidence.response = { type: 'final_text_after_task_completion' }
|
|
274
|
-
piApiTrace.push(requestEvidence)
|
|
275
|
-
sendSse(res, [
|
|
276
|
-
chatChunk(id, { role: 'assistant' }),
|
|
277
|
-
chatChunk(id, { content: 'The bounded simulator integration task is complete. The approved recipe trial returned a verified command result; no process improvement is claimed.' }),
|
|
278
|
-
chatChunk(id, {}, 'stop', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
|
|
279
|
-
])
|
|
280
|
-
return
|
|
281
|
-
}
|
|
282
|
-
throw new Error(`${target.scene} made an unexpected extra local model request`)
|
|
283
|
-
}
|
|
284
|
-
catch (error) {
|
|
285
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
286
|
-
res.writeHead(400, { 'content-type': 'application/json' })
|
|
287
|
-
res.end(JSON.stringify({ error: { message: safeText(message, 300) } }))
|
|
288
|
-
}
|
|
289
|
-
})
|
|
290
|
-
await new Promise((resolvePromise, reject) => {
|
|
291
|
-
piApiServer.once('error', reject)
|
|
292
|
-
piApiServer.listen(MODEL_API_PORT, '127.0.0.1', resolvePromise)
|
|
293
|
-
})
|
|
294
|
-
const address = piApiServer.address()
|
|
295
|
-
if (!address || typeof address === 'string' || address.address !== '127.0.0.1' || address.port !== MODEL_API_PORT) {
|
|
296
|
-
throw new Error('local Pi model fixture did not bind exactly to the approved IPv4 loopback endpoint')
|
|
297
|
-
}
|
|
298
|
-
noteIsolation('local-pi-model-api-bound-loopback', true, { host: address.address, port: address.port, route: '/v1/chat/completions' })
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function assertLoopbackUrl(url, expectedPort) {
|
|
302
|
-
const parsed = new URL(url)
|
|
303
|
-
if (parsed.protocol !== 'http:' || parsed.hostname !== '127.0.0.1' || Number(parsed.port) !== expectedPort || Number(parsed.port) === FORBIDDEN_PORT) {
|
|
304
|
-
throw new Error('network boundary rejected a non-approved loopback URL')
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function fixtureTracePath(sceneId) {
|
|
309
|
-
if (!['cast-film', 'annealing'].includes(sceneId)) throw new Error('fixture trace scene is not approved')
|
|
310
|
-
const root = resolve(ROOT)
|
|
311
|
-
const tracePath = resolve(root, `fixture-${sceneId}.json`)
|
|
312
|
-
const relativePath = relative(root, tracePath)
|
|
313
|
-
if (isAbsolute(relativePath) || relativePath === '..' || relativePath.startsWith(`..${sep}`)) {
|
|
314
|
-
throw new Error('fixture trace path escaped the experiment root')
|
|
315
|
-
}
|
|
316
|
-
return tracePath
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async function assertFreeLoopback(port, label) {
|
|
320
|
-
if (!Number.isInteger(port) || port < 1024 || port > 65535 || port === FORBIDDEN_PORT) {
|
|
321
|
-
throw new Error(`port allocation rejected for ${label}`)
|
|
322
|
-
}
|
|
323
|
-
const server = createServer()
|
|
324
|
-
await new Promise((resolvePromise, reject) => {
|
|
325
|
-
server.once('error', reject)
|
|
326
|
-
server.listen(port, '127.0.0.1', resolvePromise)
|
|
327
|
-
})
|
|
328
|
-
await new Promise(resolvePromise => server.close(resolvePromise))
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async function preflight() {
|
|
332
|
-
if (VERSION !== '0.8.0') throw new Error(`expected current package version 0.8.0; found ${safeText(VERSION, 80)}`)
|
|
333
|
-
if (!existsSync(join(SIM_SOURCE, 'src', 'server', 'index.ts')) || !existsSync(join(SIM_SOURCE, 'node_modules')) || !existsSync(NUXT_CLI)
|
|
334
|
-
|| !existsSync(PI_COMMAND) || !existsSync(PI_CLI_PACKAGE_PATH)) {
|
|
335
|
-
throw new Error('required registered Pi CLI, AgentWorkShop app, or simulator runtime is missing')
|
|
336
|
-
}
|
|
337
|
-
if (existsSync(HOME)) throw new Error('fresh AW_HOME path unexpectedly exists')
|
|
338
|
-
const mode = resolveRunMode({ cwd: REPO, packageRoot: REPO, env: { AW_HOME: HOME, AW_MODE: 'home' } })
|
|
339
|
-
if (mode.mode !== 'home' || resolve(mode.home) !== resolve(HOME) || resolve(mode.dataDir) !== resolve(join(HOME, 'data'))) {
|
|
340
|
-
throw new Error('AW_HOME did not resolve to a new isolated home-mode data directory')
|
|
341
|
-
}
|
|
342
|
-
noteIsolation('fresh-home-mode-resolution', true, { mode: mode.mode, dataDir: mode.dataDir })
|
|
343
|
-
for (const [label, port] of [['app', AW_PORT], ['simulator-http', SIM_PORT], ['local-model-api', MODEL_API_PORT], ['simulator-mqtt', MQTT_PORT], ['offline-app-mqtt-queue-probe', OFFLINE_APP_MQTT_QUEUE_PORT], ['offline-timescale-probe', OFFLINE_TSDB_PORT], ['offline-objectstore-probe', OFFLINE_OBJECTSTORE_PORT]]) {
|
|
344
|
-
await assertFreeLoopback(port, label)
|
|
345
|
-
noteIsolation(`${label}-free-loopback-port`, true, { port, host: '127.0.0.1' })
|
|
346
|
-
}
|
|
347
|
-
if ([AW_PORT, SIM_PORT, MODEL_API_PORT, MQTT_PORT].includes(FORBIDDEN_PORT)) {
|
|
348
|
-
throw new Error('forbidden service port appeared in explicit service configuration')
|
|
349
|
-
}
|
|
350
|
-
noteIsolation('project-version-and-local-inputs', true, {
|
|
351
|
-
version: VERSION,
|
|
352
|
-
simulatorSourcePresent: true,
|
|
353
|
-
piCommandPresent: true,
|
|
354
|
-
piVersion: JSON.parse(readFileSync(PI_CLI_PACKAGE_PATH, 'utf8')).version,
|
|
355
|
-
modelApiBoundToLoopback: true,
|
|
356
|
-
noExternalModelCredentialsRequired: true,
|
|
357
|
-
nuxtCliPresent: true,
|
|
358
|
-
noUserOrBusinessArchiveInput: true,
|
|
359
|
-
})
|
|
360
|
-
noteIsolation('strict-child-environment-allowlist', true, {
|
|
361
|
-
osKeys: CHILD_OS_ENV_KEYS,
|
|
362
|
-
harnessMode: HARNESS_MODE,
|
|
363
|
-
piAgentDirectoryIsolated: true,
|
|
364
|
-
piOfflineMode: true,
|
|
365
|
-
noStorageServiceEnvironment: true,
|
|
366
|
-
})
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function cleanChildEnv(extra = {}) {
|
|
370
|
-
const env = {}
|
|
371
|
-
for (const key of CHILD_OS_ENV_KEYS) {
|
|
372
|
-
if (process.env[key] !== undefined) env[key] = process.env[key]
|
|
373
|
-
}
|
|
374
|
-
env.AW_HOME = HOME
|
|
375
|
-
env.AW_MODE = 'home'
|
|
376
|
-
env.AW_PROMPTS_DIR = ISOLATED_PROMPTS_DIR
|
|
377
|
-
env.HOME = HOME
|
|
378
|
-
env.PI_CODING_AGENT_DIR = PI_AGENT_DIR
|
|
379
|
-
env.PI_CODING_AGENT_SESSION_DIR = join(PI_AGENT_DIR, 'sessions')
|
|
380
|
-
env.PI_OFFLINE = '1'
|
|
381
|
-
env.NUXT_SESSION_PASSWORD = generatedSessionPassword
|
|
382
|
-
env.NO_PROXY = '127.0.0.1,localhost'
|
|
383
|
-
env.no_proxy = '127.0.0.1,localhost'
|
|
384
|
-
for (const [key, value] of Object.entries(extra)) {
|
|
385
|
-
if (!CHILD_EXTRA_ENV_KEYS.has(key)) throw new Error(`child environment rejected unsupported override ${key}`)
|
|
386
|
-
env[key] = String(value)
|
|
387
|
-
}
|
|
388
|
-
return env
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function gitText(cwd, args) {
|
|
392
|
-
const result = spawnSync('git', args, {
|
|
393
|
-
cwd,
|
|
394
|
-
windowsHide: true,
|
|
395
|
-
encoding: 'utf8',
|
|
396
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
397
|
-
env: cleanChildEnv(),
|
|
398
|
-
})
|
|
399
|
-
if (result.error || result.status !== 0) {
|
|
400
|
-
throw new Error(`could not capture source identity: ${safeText(result.stderr || result.error?.message || result.status)}`)
|
|
401
|
-
}
|
|
402
|
-
return String(result.stdout ?? '').trim()
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function hashGitFiles(cwd, roots) {
|
|
406
|
-
const names = gitText(cwd, ['ls-files', '-co', '--exclude-standard', '--', ...roots])
|
|
407
|
-
.split(/\r?\n/).filter(Boolean).sort()
|
|
408
|
-
if (names.length === 0) throw new Error(`source identity has no files under ${roots.join(', ')}`)
|
|
409
|
-
return hashFileList(cwd, names)
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function hashFileList(cwd, names) {
|
|
413
|
-
const hash = createHash('sha256')
|
|
414
|
-
for (const name of names) {
|
|
415
|
-
hash.update(name.replaceAll('\\', '/') + '\0')
|
|
416
|
-
hash.update(readFileSync(join(cwd, name)))
|
|
417
|
-
hash.update('\0')
|
|
418
|
-
}
|
|
419
|
-
return { sha256: hash.digest('hex'), fileCount: names.length }
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
function hashDirectoryTree(root) {
|
|
423
|
-
if (!existsSync(root)) return hashFileList(root, [])
|
|
424
|
-
const names = []
|
|
425
|
-
const visit = (directory) => {
|
|
426
|
-
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
427
|
-
const absolute = join(directory, entry.name)
|
|
428
|
-
const name = relative(root, absolute).replaceAll('\\', '/')
|
|
429
|
-
if (entry.isSymbolicLink()) throw new Error(`source identity rejected symlink in plugin tree: ${name}`)
|
|
430
|
-
if (entry.isDirectory()) visit(absolute)
|
|
431
|
-
else if (entry.isFile()) names.push(name)
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
visit(root)
|
|
435
|
-
names.sort()
|
|
436
|
-
return hashFileList(root, names)
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function pluginNamesUnder(root) {
|
|
440
|
-
if (!existsSync(root)) return []
|
|
441
|
-
return readdirSync(root, { withFileTypes: true })
|
|
442
|
-
.filter(entry => entry.isDirectory() && existsSync(join(root, entry.name, 'index.mjs')))
|
|
443
|
-
.map(entry => entry.name)
|
|
444
|
-
.sort()
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function captureSourceIdentity() {
|
|
448
|
-
const appRoots = ['app', 'server', 'shared', 'mcp', 'cli', 'sdk', 'i18n', 'public', 'tsconfig.json', 'package.json', 'pnpm-lock.yaml', 'nuxt.config.ts', 'config.yml']
|
|
449
|
-
const simulatorRoots = ['src', 'package.json', 'package-lock.json']
|
|
450
|
-
const simulatorSourceFiles = gitText(SIM_SOURCE, ['ls-files', '-co', '--exclude-standard', '--', ...simulatorRoots])
|
|
451
|
-
.split(/\r?\n/).filter(Boolean).sort()
|
|
452
|
-
const executedSimulatorFiles = simulatorSourceFiles.filter(name => existsSync(join(SIM_ROOT, name)))
|
|
453
|
-
if (!executedSimulatorFiles.includes('src/server/index.ts') || !executedSimulatorFiles.includes('package.json')) {
|
|
454
|
-
throw new Error('executed simulator copy is missing required source files for provenance')
|
|
455
|
-
}
|
|
456
|
-
const projectPluginTree = hashDirectoryTree(join(REPO, '.AgentWorkShop', 'plugins'))
|
|
457
|
-
if (projectPluginTree.sha256 !== projectPluginTreeAtPrepare?.sha256) {
|
|
458
|
-
throw new Error('project plugin source changed after isolation was prepared')
|
|
459
|
-
}
|
|
460
|
-
const promptTree = hashDirectoryTree(ISOLATED_PROMPTS_DIR)
|
|
461
|
-
if (promptTree.sha256 !== promptTreeAtPrepare?.sha256) {
|
|
462
|
-
throw new Error('isolated prompt assets changed after isolation was prepared')
|
|
463
|
-
}
|
|
464
|
-
const piCliVersion = JSON.parse(readFileSync(PI_CLI_PACKAGE_PATH, 'utf8')).version
|
|
465
|
-
return {
|
|
466
|
-
recordedAt: new Date().toISOString(),
|
|
467
|
-
nodeVersion: process.version,
|
|
468
|
-
platform: process.platform,
|
|
469
|
-
architecture: process.arch,
|
|
470
|
-
app: {
|
|
471
|
-
version: VERSION,
|
|
472
|
-
gitHead: gitText(REPO, ['rev-parse', 'HEAD']),
|
|
473
|
-
sourceTree: hashGitFiles(REPO, appRoots),
|
|
474
|
-
workingTreeStatus: gitText(REPO, ['status', '--porcelain', '--', ...appRoots]),
|
|
475
|
-
packageManifestSha256: createHash('sha256').update(readFileSync(join(REPO, 'package.json'))).digest('hex'),
|
|
476
|
-
lockfileSha256: createHash('sha256').update(readFileSync(join(REPO, 'pnpm-lock.yaml'))).digest('hex'),
|
|
477
|
-
projectPluginTree,
|
|
478
|
-
projectPluginNames: pluginNamesUnder(join(REPO, '.AgentWorkShop', 'plugins')),
|
|
479
|
-
},
|
|
480
|
-
pluginIsolation: {
|
|
481
|
-
disabledNames: isolatedPluginNames,
|
|
482
|
-
enabledAllowlist: allowedEnabledPluginNames,
|
|
483
|
-
setupExpectedForOtherPlugins: false,
|
|
484
|
-
disabledStatePath: 'AW_HOME/plugins-state.json',
|
|
485
|
-
projectPluginNames: pluginNamesUnder(join(REPO, '.AgentWorkShop', 'plugins')),
|
|
486
|
-
projectPluginTree,
|
|
487
|
-
},
|
|
488
|
-
promptIsolation: {
|
|
489
|
-
sourceDirectory: 'repository/.AgentWorkShop/prompts',
|
|
490
|
-
isolatedDirectory: 'AW_HOME/prompts',
|
|
491
|
-
sourceTree: projectPromptTreeAtPrepare,
|
|
492
|
-
runtimeTree: promptTree,
|
|
493
|
-
},
|
|
494
|
-
experimentScriptSha256: createHash('sha256').update(readFileSync(fileURLToPath(import.meta.url))).digest('hex'),
|
|
495
|
-
registeredHarness: {
|
|
496
|
-
mode: HARNESS_MODE,
|
|
497
|
-
harness: 'pi',
|
|
498
|
-
command: PI_COMMAND,
|
|
499
|
-
piCliVersion,
|
|
500
|
-
provider: PI_PROVIDER,
|
|
501
|
-
model: PI_MODEL,
|
|
502
|
-
isolatedModelConfigSha256: createHash('sha256').update(readFileSync(PI_MODELS_PATH)).digest('hex'),
|
|
503
|
-
localModelFixtureSha256: createHash('sha256').update(readFileSync(fileURLToPath(import.meta.url))).digest('hex'),
|
|
504
|
-
externalCredentialsUsed: false,
|
|
505
|
-
},
|
|
506
|
-
simulator: {
|
|
507
|
-
gitlinkHead: gitText(REPO, ['rev-parse', 'HEAD:plc-node-simulator']),
|
|
508
|
-
gitHead: gitText(SIM_SOURCE, ['rev-parse', 'HEAD']),
|
|
509
|
-
sourceTree: hashGitFiles(SIM_SOURCE, simulatorRoots),
|
|
510
|
-
workingTreeStatus: gitText(SIM_SOURCE, ['status', '--porcelain', '--', ...simulatorRoots]),
|
|
511
|
-
executedTree: hashFileList(SIM_ROOT, executedSimulatorFiles),
|
|
512
|
-
lockfileSha256: createHash('sha256').update(readFileSync(join(SIM_SOURCE, 'package-lock.json'))).digest('hex'),
|
|
513
|
-
copyPatch: 'bind copied simulator HTTP and MQTT listeners to 127.0.0.1 and remap only their ports; source script hash records the transformation',
|
|
514
|
-
},
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
function prepareIsolatedHome() {
|
|
519
|
-
mkdirSync(join(HOME, 'data'), { recursive: true })
|
|
520
|
-
mkdirSync(join(PI_AGENT_DIR, 'sessions'), { recursive: true })
|
|
521
|
-
const piModels = {
|
|
522
|
-
providers: {
|
|
523
|
-
[PI_PROVIDER]: {
|
|
524
|
-
name: 'AgentWorkShop loopback deterministic fixture',
|
|
525
|
-
baseUrl: `http://127.0.0.1:${MODEL_API_PORT}/v1`,
|
|
526
|
-
apiKey: 'local-fixture-key-not-a-secret',
|
|
527
|
-
api: 'openai-completions',
|
|
528
|
-
models: [{
|
|
529
|
-
id: PI_MODEL,
|
|
530
|
-
name: 'AgentWorkShop deterministic paper fixture',
|
|
531
|
-
reasoning: false,
|
|
532
|
-
input: ['text'],
|
|
533
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
534
|
-
contextWindow: 64000,
|
|
535
|
-
maxTokens: 2048,
|
|
536
|
-
}],
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
}
|
|
540
|
-
writeFileSync(PI_MODELS_PATH, `${JSON.stringify(piModels, null, 2)}\n`, 'utf8')
|
|
541
|
-
assertLoopbackUrl(piModels.providers[PI_PROVIDER].baseUrl, MODEL_API_PORT)
|
|
542
|
-
noteIsolation('pi-custom-provider-isolated-to-local-fixture', true, {
|
|
543
|
-
configPath: 'AW_HOME/pi-agent/models.json',
|
|
544
|
-
provider: PI_PROVIDER,
|
|
545
|
-
model: PI_MODEL,
|
|
546
|
-
api: 'openai-completions',
|
|
547
|
-
baseUrl: piModels.providers[PI_PROVIDER].baseUrl,
|
|
548
|
-
apiKeyValueRecorded: false,
|
|
549
|
-
externalCredentialsUsed: false,
|
|
550
|
-
})
|
|
551
|
-
copyFileSync(join(REPO, 'config.yml'), join(HOME, 'config.yml'))
|
|
552
|
-
const overrides = {
|
|
553
|
-
'daq.startInfrastructure': 'never',
|
|
554
|
-
'daq.mqtt.host': '127.0.0.1',
|
|
555
|
-
'daq.mqtt.port': OFFLINE_APP_MQTT_QUEUE_PORT,
|
|
556
|
-
'daq.timescale.host': '127.0.0.1',
|
|
557
|
-
'daq.timescale.port': OFFLINE_TSDB_PORT,
|
|
558
|
-
'daq.objectstore.host': '127.0.0.1',
|
|
559
|
-
'daq.objectstore.port': OFFLINE_OBJECTSTORE_PORT,
|
|
560
|
-
'plugins.rag-bridge.base_url': RAG_BRIDGE_DISABLED_BASE_URL,
|
|
561
|
-
}
|
|
562
|
-
const runtimeSettingsPath = join(HOME, 'runtime-settings.json')
|
|
563
|
-
writeFileSync(runtimeSettingsPath, `${JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), overrides }, null, 2)}\n`, 'utf8')
|
|
564
|
-
const savedOverrides = JSON.parse(readFileSync(runtimeSettingsPath, 'utf8')).overrides
|
|
565
|
-
if (savedOverrides?.['plugins.rag-bridge.base_url'] !== overrides['plugins.rag-bridge.base_url']) {
|
|
566
|
-
throw new Error('isolated runtime settings did not preserve the rag-bridge outbound-disable host guard setting')
|
|
567
|
-
}
|
|
568
|
-
const ragBridgeKvDir = join(HOME, 'data', 'plugins', 'rag-bridge')
|
|
569
|
-
mkdirSync(ragBridgeKvDir, { recursive: true })
|
|
570
|
-
const ragBridgeKvPath = join(ragBridgeKvDir, 'kv.json')
|
|
571
|
-
writeFileSync(ragBridgeKvPath, `${JSON.stringify({ 'kb.base_url': RAG_BRIDGE_DISABLED_BASE_URL }, null, 2)}\n`, 'utf8')
|
|
572
|
-
const savedRagBridgeKv = JSON.parse(readFileSync(ragBridgeKvPath, 'utf8'))
|
|
573
|
-
if (savedRagBridgeKv?.['kb.base_url'] !== RAG_BRIDGE_DISABLED_BASE_URL) {
|
|
574
|
-
throw new Error('isolated rag-bridge KV fallback did not preserve the outbound-disable host guard setting')
|
|
575
|
-
}
|
|
576
|
-
const projectPromptsRoot = join(REPO, '.AgentWorkShop', 'prompts')
|
|
577
|
-
if (!existsSync(projectPromptsRoot)) throw new Error('project prompt source directory is missing')
|
|
578
|
-
cpSync(projectPromptsRoot, ISOLATED_PROMPTS_DIR, { recursive: true })
|
|
579
|
-
projectPromptTreeAtPrepare = hashDirectoryTree(projectPromptsRoot)
|
|
580
|
-
promptTreeAtPrepare = hashDirectoryTree(ISOLATED_PROMPTS_DIR)
|
|
581
|
-
if (projectPromptTreeAtPrepare.sha256 !== promptTreeAtPrepare.sha256) {
|
|
582
|
-
throw new Error('isolated prompt copy differs from the repository prompt source')
|
|
583
|
-
}
|
|
584
|
-
writeFileSync(EMPTY_DOTENV, '', 'utf8')
|
|
585
|
-
const builtinPlugins = pluginNamesUnder(join(REPO, 'server', 'plugins-builtin'))
|
|
586
|
-
const projectPluginsRoot = join(REPO, '.AgentWorkShop', 'plugins')
|
|
587
|
-
const projectPlugins = pluginNamesUnder(projectPluginsRoot)
|
|
588
|
-
const userPlugins = pluginNamesUnder(join(HOME, 'plugins'))
|
|
589
|
-
expectedPluginNames = [...new Set([...builtinPlugins, ...projectPlugins, ...userPlugins])].sort()
|
|
590
|
-
isolatedPluginNames = expectedPluginNames.filter(name => !allowedEnabledPluginNames.includes(name))
|
|
591
|
-
projectPluginTreeAtPrepare = hashDirectoryTree(projectPluginsRoot)
|
|
592
|
-
const pluginStatePath = join(HOME, 'plugins-state.json')
|
|
593
|
-
writeFileSync(pluginStatePath, `${JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), disabled: isolatedPluginNames }, null, 2)}\n`, 'utf8')
|
|
594
|
-
const savedPluginState = JSON.parse(readFileSync(pluginStatePath, 'utf8'))
|
|
595
|
-
if (JSON.stringify([...savedPluginState.disabled].sort()) !== JSON.stringify(isolatedPluginNames)) {
|
|
596
|
-
throw new Error('isolated plugin state did not disable every discovered plugin')
|
|
597
|
-
}
|
|
598
|
-
noteIsolation('isolated-runtime-config', true, {
|
|
599
|
-
configRoot: 'fresh isolated AW_HOME',
|
|
600
|
-
startInfrastructure: overrides['daq.startInfrastructure'],
|
|
601
|
-
simulatorMqttBroker: `127.0.0.1:${MQTT_PORT}`,
|
|
602
|
-
appMqttQueueProbe: `127.0.0.1:${OFFLINE_APP_MQTT_QUEUE_PORT}`,
|
|
603
|
-
offlineTimescaleProbe: `127.0.0.1:${OFFLINE_TSDB_PORT}`,
|
|
604
|
-
offlineObjectstoreProbe: `127.0.0.1:${OFFLINE_OBJECTSTORE_PORT}`,
|
|
605
|
-
ragBridgeOutboundGuardSetting: 'plugins.rag-bridge.base_url',
|
|
606
|
-
ragBridgeOutboundGuardConfigPresent: true,
|
|
607
|
-
ragBridgeOutboundGuardKvFallbackPresent: true,
|
|
608
|
-
emptyDotenv: true,
|
|
609
|
-
repoDotenvBypassed: true,
|
|
610
|
-
})
|
|
611
|
-
noteIsolation('pre-existing-plugin-scopes-disabled', true, {
|
|
612
|
-
builtinNames: builtinPlugins,
|
|
613
|
-
projectNames: projectPlugins,
|
|
614
|
-
userNames: userPlugins,
|
|
615
|
-
disabledStatePath: 'AW_HOME/plugins-state.json',
|
|
616
|
-
projectPluginTreeSha256: projectPluginTreeAtPrepare.sha256,
|
|
617
|
-
enabledPluginAllowlist: allowedEnabledPluginNames,
|
|
618
|
-
})
|
|
619
|
-
noteIsolation('project-prompt-assets-isolated', true, {
|
|
620
|
-
sourceDirectory: 'repository/.AgentWorkShop/prompts',
|
|
621
|
-
isolatedDirectory: 'AW_HOME/prompts',
|
|
622
|
-
sourceTreeSha256: projectPromptTreeAtPrepare.sha256,
|
|
623
|
-
runtimeTreeSha256: promptTreeAtPrepare.sha256,
|
|
624
|
-
awPromptsDir: 'AW_HOME/prompts',
|
|
625
|
-
})
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
async function assertPluginIsolation() {
|
|
629
|
-
const expectedNames = expectedPluginNames
|
|
630
|
-
let plugins = []
|
|
631
|
-
for (let attempt = 0; attempt < 40; attempt++) {
|
|
632
|
-
const result = requireSuccess(await app('GET', '/api/workshop/plugins'), 'isolated plugin manifest')
|
|
633
|
-
plugins = Array.isArray(result.plugins) ? result.plugins : []
|
|
634
|
-
const actualNames = plugins.map(plugin => plugin.name).sort()
|
|
635
|
-
if (JSON.stringify(actualNames) === JSON.stringify(expectedNames)) {
|
|
636
|
-
const enabledNames = plugins.filter(plugin => plugin.enabled === true).map(plugin => plugin.name).sort()
|
|
637
|
-
const enabledMatchesAllowlist = JSON.stringify(enabledNames) === JSON.stringify([...allowedEnabledPluginNames].sort())
|
|
638
|
-
const statesMatchPolicy = plugins.every(plugin => allowedEnabledPluginNames.includes(plugin.name)
|
|
639
|
-
? plugin.enabled === true
|
|
640
|
-
: plugin.enabled === false)
|
|
641
|
-
check('only-outbound-disabled-rag-bridge-enabled', enabledMatchesAllowlist && statesMatchPolicy, {
|
|
642
|
-
names: actualNames,
|
|
643
|
-
enabledNames,
|
|
644
|
-
disabledNames: plugins.filter(plugin => plugin.enabled === false).map(plugin => plugin.name).sort(),
|
|
645
|
-
invalidStateNames: plugins.filter(plugin => typeof plugin.enabled !== 'boolean').map(plugin => plugin.name),
|
|
646
|
-
})
|
|
647
|
-
return
|
|
648
|
-
}
|
|
649
|
-
await delay(250)
|
|
650
|
-
}
|
|
651
|
-
throw new Error(`isolated plugin manifest differed from the expected built-in/user set: ${plugins.map(plugin => plugin.name).sort().join(', ')}`)
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
function spawnLogged(command, args, { cwd = REPO, env = cleanChildEnv(), logFd, label }) {
|
|
655
|
-
const child = spawn(command, args, {
|
|
656
|
-
cwd,
|
|
657
|
-
env,
|
|
658
|
-
stdio: ['ignore', logFd, logFd],
|
|
659
|
-
windowsHide: true,
|
|
660
|
-
detached: process.platform !== 'win32',
|
|
661
|
-
})
|
|
662
|
-
child.label = label
|
|
663
|
-
children.add(child)
|
|
664
|
-
child.once('exit', () => children.delete(child))
|
|
665
|
-
child.once('error', () => children.delete(child))
|
|
666
|
-
return child
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
async function waitForExit(child, timeoutMs = 8_000) {
|
|
670
|
-
if (!child || child.exitCode !== null || child.signalCode !== null) return
|
|
671
|
-
await Promise.race([
|
|
672
|
-
new Promise(resolvePromise => child.once('exit', resolvePromise)),
|
|
673
|
-
delay(timeoutMs),
|
|
674
|
-
])
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function processGroupExists(pid) {
|
|
678
|
-
try {
|
|
679
|
-
process.kill(-pid, 0)
|
|
680
|
-
return true
|
|
681
|
-
}
|
|
682
|
-
catch (error) {
|
|
683
|
-
if (error?.code === 'ESRCH') return false
|
|
684
|
-
if (error?.code === 'EPERM') return true
|
|
685
|
-
throw error
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
function windowsProcessExists(pid) {
|
|
690
|
-
const result = spawnSync('tasklist.exe', ['/FI', `PID eq ${pid}`, '/FO', 'CSV', '/NH'], {
|
|
691
|
-
windowsHide: true,
|
|
692
|
-
encoding: 'utf8',
|
|
693
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
694
|
-
env: cleanChildEnv(),
|
|
695
|
-
})
|
|
696
|
-
if (result.error || result.status !== 0) return null
|
|
697
|
-
return (result.stdout ?? '').split(/\r?\n/).some((line) => {
|
|
698
|
-
const columns = line.match(/^"(?:[^"]|"")*","(\d+)"(?:,|$)/)
|
|
699
|
-
return columns?.[1] === String(pid)
|
|
700
|
-
})
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
async function stopProcessTree(child, label) {
|
|
704
|
-
if (!child?.pid) return false
|
|
705
|
-
const wasAlreadyExited = child.exitCode !== null || child.signalCode !== null
|
|
706
|
-
let terminationStatus = null
|
|
707
|
-
try {
|
|
708
|
-
if (process.platform === 'win32' && child.pid) {
|
|
709
|
-
const result = spawnSync('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore', env: cleanChildEnv() })
|
|
710
|
-
terminationStatus = result.error ? 'spawn-error' : result.status
|
|
711
|
-
}
|
|
712
|
-
else if (process.platform !== 'win32' && child.pid) {
|
|
713
|
-
process.kill(-child.pid, 'SIGTERM')
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
catch { /* a process may have already exited */ }
|
|
717
|
-
await waitForExit(child)
|
|
718
|
-
if (process.platform !== 'win32' && processGroupExists(child.pid)) {
|
|
719
|
-
try {
|
|
720
|
-
process.kill(-child.pid, 'SIGKILL')
|
|
721
|
-
terminationStatus = 'SIGKILL'
|
|
722
|
-
}
|
|
723
|
-
catch { /* already gone */ }
|
|
724
|
-
}
|
|
725
|
-
else if (process.platform === 'win32' && windowsProcessExists(child.pid) === true) {
|
|
726
|
-
const result = spawnSync('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore', env: cleanChildEnv() })
|
|
727
|
-
terminationStatus = result.error ? 'spawn-error' : result.status
|
|
728
|
-
}
|
|
729
|
-
await waitForExit(child, 2_000)
|
|
730
|
-
let treePresent
|
|
731
|
-
if (process.platform === 'win32') treePresent = windowsProcessExists(child.pid)
|
|
732
|
-
else {
|
|
733
|
-
const deadline = Date.now() + 3_000
|
|
734
|
-
do {
|
|
735
|
-
treePresent = processGroupExists(child.pid)
|
|
736
|
-
if (!treePresent) break
|
|
737
|
-
await delay(100)
|
|
738
|
-
} while (Date.now() < deadline)
|
|
739
|
-
}
|
|
740
|
-
const pass = !wasAlreadyExited && treePresent === false && (process.platform !== 'win32' || terminationStatus === 0)
|
|
741
|
-
evidence.checks.push({
|
|
742
|
-
id: `${label}-process-stopped`,
|
|
743
|
-
status: pass ? 'pass' : 'fail',
|
|
744
|
-
detail: { pid: child.pid, terminationStatus, processTreePresentAfterCleanup: treePresent, rootWasAlreadyExited: wasAlreadyExited },
|
|
745
|
-
})
|
|
746
|
-
return pass
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
function buildHarnessShim() {
|
|
750
|
-
if (process.platform === 'win32') {
|
|
751
|
-
const compiler = [
|
|
752
|
-
join(process.env.WINDIR || 'C:\\Windows', 'Microsoft.NET', 'Framework64', 'v4.0.30319', 'csc.exe'),
|
|
753
|
-
join(process.env.WINDIR || 'C:\\Windows', 'Microsoft.NET', 'Framework', 'v4.0.30319', 'csc.exe'),
|
|
754
|
-
].find(existsSync)
|
|
755
|
-
if (!compiler) throw new Error('Windows C# compiler unavailable; cannot safely launch a registered fixture executable')
|
|
756
|
-
const source = join(ROOT, 'omp-fixture-shim.cs')
|
|
757
|
-
wrapperPath = join(ROOT, 'omp-fixture-shim.exe')
|
|
758
|
-
writeFileSync(source, String.raw`using System;
|
|
759
|
-
using System.Diagnostics;
|
|
760
|
-
using System.IO;
|
|
761
|
-
using System.Linq;
|
|
762
|
-
using System.Text;
|
|
763
|
-
using System.Threading;
|
|
764
|
-
class OmpFixtureShim {
|
|
765
|
-
static string Quote(string value) {
|
|
766
|
-
var result = new StringBuilder("\"");
|
|
767
|
-
int backslashes = 0;
|
|
768
|
-
foreach (char c in value) {
|
|
769
|
-
if (c == '\\') { backslashes++; continue; }
|
|
770
|
-
if (c == '"') {
|
|
771
|
-
result.Append('\\', backslashes * 2 + 1);
|
|
772
|
-
result.Append('"');
|
|
773
|
-
}
|
|
774
|
-
else {
|
|
775
|
-
result.Append('\\', backslashes);
|
|
776
|
-
result.Append(c);
|
|
777
|
-
}
|
|
778
|
-
backslashes = 0;
|
|
779
|
-
}
|
|
780
|
-
result.Append('\\', backslashes * 2);
|
|
781
|
-
result.Append('"');
|
|
782
|
-
return result.ToString();
|
|
783
|
-
}
|
|
784
|
-
static void Copy(Stream source, Stream destination) {
|
|
785
|
-
byte[] buffer = new byte[4096];
|
|
786
|
-
int count;
|
|
787
|
-
while ((count = source.Read(buffer, 0, buffer.Length)) > 0) {
|
|
788
|
-
destination.Write(buffer, 0, count);
|
|
789
|
-
destination.Flush();
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
static int Main(string[] args) {
|
|
793
|
-
string node = Environment.GetEnvironmentVariable("AW_PAPER_FIXTURE_NODE");
|
|
794
|
-
string script = Environment.GetEnvironmentVariable("AW_PAPER_FIXTURE_SCRIPT");
|
|
795
|
-
if (String.IsNullOrWhiteSpace(node) || String.IsNullOrWhiteSpace(script)) return 125;
|
|
796
|
-
var psi = new ProcessStartInfo(node);
|
|
797
|
-
psi.UseShellExecute = false;
|
|
798
|
-
psi.CreateNoWindow = true;
|
|
799
|
-
psi.RedirectStandardInput = true;
|
|
800
|
-
psi.RedirectStandardOutput = true;
|
|
801
|
-
psi.RedirectStandardError = true;
|
|
802
|
-
psi.Arguments = Quote(script) + " " + String.Join(" ", args.Skip(2).Select(Quote));
|
|
803
|
-
using (var child = Process.Start(psi)) {
|
|
804
|
-
if (child == null) return 126;
|
|
805
|
-
var stdin = new Thread(() => {
|
|
806
|
-
try {
|
|
807
|
-
Copy(Console.OpenStandardInput(), child.StandardInput.BaseStream);
|
|
808
|
-
}
|
|
809
|
-
finally {
|
|
810
|
-
child.StandardInput.Close();
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
var stdout = new Thread(() => Copy(child.StandardOutput.BaseStream, Console.OpenStandardOutput()));
|
|
814
|
-
var stderr = new Thread(() => Copy(child.StandardError.BaseStream, Console.OpenStandardError()));
|
|
815
|
-
stdin.IsBackground = true;
|
|
816
|
-
stdout.IsBackground = true;
|
|
817
|
-
stderr.IsBackground = true;
|
|
818
|
-
stdin.Start();
|
|
819
|
-
stdout.Start();
|
|
820
|
-
stderr.Start();
|
|
821
|
-
child.WaitForExit();
|
|
822
|
-
stdout.Join();
|
|
823
|
-
stderr.Join();
|
|
824
|
-
return child.ExitCode;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
}`.replace(/\n/g, '\n'), 'utf8')
|
|
828
|
-
const result = spawnSync(compiler, ['/nologo', '/target:exe', `/out:${wrapperPath}`, source], { cwd: ROOT, windowsHide: true, encoding: 'utf8', timeout: 30_000, env: cleanChildEnv() })
|
|
829
|
-
if (result.error || result.status !== 0 || !existsSync(wrapperPath)) {
|
|
830
|
-
throw new Error(`could not compile isolated OMP fixture shim: ${safeText(result.stderr || result.stdout || result.error?.message || result.status)}`)
|
|
831
|
-
}
|
|
832
|
-
return wrapperPath
|
|
833
|
-
}
|
|
834
|
-
if (process.platform === 'linux' || process.platform === 'darwin') {
|
|
835
|
-
wrapperPath = join(ROOT, 'omp-fixture-shim')
|
|
836
|
-
writeFileSync(wrapperPath, '#!/bin/sh\nshift 2\nexec "$AW_PAPER_FIXTURE_NODE" "$AW_PAPER_FIXTURE_SCRIPT" "$@"\n', 'utf8')
|
|
837
|
-
chmodSync(wrapperPath, 0o755)
|
|
838
|
-
return wrapperPath
|
|
839
|
-
}
|
|
840
|
-
throw new Error(`unsupported fixture shim platform ${process.platform}`)
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
function extractPayload(body) {
|
|
844
|
-
return body && typeof body === 'object' && Object.prototype.hasOwnProperty.call(body, 'data') ? body.data : body
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
async function request(base, expectedPort, method, path, body, { token, timeoutMs = 10_000 } = {}) {
|
|
848
|
-
assertLoopbackUrl(base, expectedPort)
|
|
849
|
-
if (!path.startsWith('/api/')) throw new Error('API path boundary rejected')
|
|
850
|
-
const response = await fetch(`${base}${path}`, {
|
|
851
|
-
method,
|
|
852
|
-
headers: {
|
|
853
|
-
...(body === undefined ? {} : { 'content-type': 'application/json' }),
|
|
854
|
-
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
855
|
-
},
|
|
856
|
-
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
857
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
858
|
-
})
|
|
859
|
-
const parsed = await response.json().catch(() => null)
|
|
860
|
-
return { status: response.status, body: parsed, data: extractPayload(parsed) }
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
const app = (method, path, body, opts = {}) => request(APP_BASE, AW_PORT, method, path, body, { token: opts.token ?? authToken, timeoutMs: opts.timeoutMs })
|
|
864
|
-
const sim = (method, path, body) => request(SIM_BASE, SIM_PORT, method, path, body, { timeoutMs: 8_000 })
|
|
865
|
-
|
|
866
|
-
function requireSuccess(result, label, status = 200) {
|
|
867
|
-
if (result.status !== status) {
|
|
868
|
-
const payload = result.body && typeof result.body === 'object' ? result.body : {}
|
|
869
|
-
throw new Error(`${label} returned HTTP ${result.status}: ${safeText(payload.message || payload.statusMessage || payload.code || 'no response detail')}`)
|
|
870
|
-
}
|
|
871
|
-
return result.data
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
async function bootSimulator() {
|
|
875
|
-
mkdirSync(SIM_ROOT, { recursive: true })
|
|
876
|
-
cpSync(join(SIM_SOURCE, 'src'), join(SIM_ROOT, 'src'), { recursive: true })
|
|
877
|
-
cpSync(join(SIM_SOURCE, 'package.json'), join(SIM_ROOT, 'package.json'))
|
|
878
|
-
const simulatorEntry = join(SIM_ROOT, 'src', 'server', 'index.ts')
|
|
879
|
-
const originalSource = readFileSync(simulatorEntry, 'utf8')
|
|
880
|
-
const listenCall = 'server.listen(PORT, () => resolve())'
|
|
881
|
-
const brokerCall = 'await startBroker(Number(process.env.MQTT_BROKER_PORT ?? 18830))'
|
|
882
|
-
if (originalSource.split(listenCall).length !== 2) throw new Error('simulator copied source did not contain exactly one expected listener call')
|
|
883
|
-
if (originalSource.split(brokerCall).length !== 2) throw new Error('simulator copied source did not contain exactly one expected broker startup call')
|
|
884
|
-
const loopbackListenCall = `server.listen(PORT, '127.0.0.1', () => {
|
|
885
|
-
const boundAddress = server.address()
|
|
886
|
-
if (!boundAddress || typeof boundAddress === 'string' || boundAddress.address !== '127.0.0.1' || boundAddress.port !== PORT) {
|
|
887
|
-
console.error('[paper-isolation] simulator listener address verification failed')
|
|
888
|
-
server.close(() => process.exit(70))
|
|
889
|
-
return
|
|
890
|
-
}
|
|
891
|
-
console.log('[paper-isolation] listener=' + boundAddress.address + ':' + boundAddress.port)
|
|
892
|
-
resolve()
|
|
893
|
-
})`
|
|
894
|
-
const loopbackSource = originalSource
|
|
895
|
-
.replace(listenCall, loopbackListenCall)
|
|
896
|
-
.replace(brokerCall, `await startBroker(Number(process.env.MQTT_BROKER_PORT ?? 18830), '127.0.0.1')`)
|
|
897
|
-
writeFileSync(simulatorEntry, loopbackSource, 'utf8')
|
|
898
|
-
const modules = join(SIM_SOURCE, 'node_modules')
|
|
899
|
-
symlinkSync(modules, join(SIM_ROOT, 'node_modules'), process.platform === 'win32' ? 'junction' : 'dir')
|
|
900
|
-
simProcess = spawnLogged(process.execPath, [join(REPO, 'node_modules', 'tsx', 'dist', 'cli.mjs'), join(SIM_ROOT, 'src', 'server', 'index.ts')], {
|
|
901
|
-
cwd: SIM_ROOT,
|
|
902
|
-
logFd: SIM_LOG_FD,
|
|
903
|
-
label: 'simulator',
|
|
904
|
-
env: cleanChildEnv({ SIM_PORT: String(SIM_PORT), MQTT_BROKER_PORT: String(MQTT_PORT) }),
|
|
905
|
-
})
|
|
906
|
-
for (let i = 0; i < 50; i++) {
|
|
907
|
-
if (simProcess.exitCode !== null) throw new Error(`simulator exited during startup (code ${simProcess.exitCode})`)
|
|
908
|
-
try {
|
|
909
|
-
const result = await sim('GET', '/api/nodes')
|
|
910
|
-
if (result.status === 200) {
|
|
911
|
-
const data = result.data
|
|
912
|
-
const expectedListener = `[paper-isolation] listener=127.0.0.1:${SIM_PORT}`
|
|
913
|
-
const simulatorLog = readFileSync(SIM_LOG, 'utf8')
|
|
914
|
-
const expectedBroker = `[mqtt-broker] 内置 broker 就绪 mqtt://127.0.0.1:${MQTT_PORT}`
|
|
915
|
-
if (!simulatorLog.includes(expectedListener)) throw new Error('simulator did not report the verified 127.0.0.1 HTTP listener address')
|
|
916
|
-
if (!simulatorLog.includes(expectedBroker) || simulatorLog.includes('内置 broker 启动失败')) {
|
|
917
|
-
throw new Error('simulator did not confirm its embedded loopback MQTT broker before application startup')
|
|
918
|
-
}
|
|
919
|
-
noteIsolation('simulator-listener-address-verified', true, { address: '127.0.0.1', port: SIM_PORT, copiedSourceOnly: true })
|
|
920
|
-
noteIsolation('simulator-mqtt-broker-loopback-ready', true, { address: '127.0.0.1', port: MQTT_PORT, brokerStartupConfirmed: true })
|
|
921
|
-
noteIsolation('simulator-local-http-ready', true, { version: 'local repository source', port: SIM_PORT, host: '127.0.0.1' })
|
|
922
|
-
return data
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
catch { /* the local simulator is still starting */ }
|
|
926
|
-
await delay(400)
|
|
927
|
-
}
|
|
928
|
-
throw new Error('isolated simulator startup timed out')
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
function normalizeLocalNetworkConfig(value, portMap, key = '') {
|
|
932
|
-
if (Array.isArray(value)) return value.map(item => normalizeLocalNetworkConfig(item, portMap, key))
|
|
933
|
-
if (!value || typeof value !== 'object') {
|
|
934
|
-
if (typeof value !== 'string') return value
|
|
935
|
-
if (/^[a-z][a-z\d+.-]*:\/\//i.test(value)) {
|
|
936
|
-
const parsed = new URL(value)
|
|
937
|
-
if (!['127.0.0.1', 'localhost', '::1'].includes(parsed.hostname)) throw new Error('simulator preset contains a non-loopback endpoint')
|
|
938
|
-
if (parsed.port && portMap.has(Number(parsed.port))) parsed.port = String(portMap.get(Number(parsed.port)))
|
|
939
|
-
parsed.hostname = '127.0.0.1'
|
|
940
|
-
return parsed.toString()
|
|
941
|
-
}
|
|
942
|
-
if (/(?:host|hostname|ip|address)$/i.test(key)) return '127.0.0.1'
|
|
943
|
-
return value
|
|
944
|
-
}
|
|
945
|
-
const out = {}
|
|
946
|
-
for (const [childKey, childValue] of Object.entries(value)) {
|
|
947
|
-
if (/^port$/i.test(childKey) && typeof childValue === 'number' && portMap.has(childValue)) {
|
|
948
|
-
out[childKey] = portMap.get(childValue)
|
|
949
|
-
}
|
|
950
|
-
else if (/(?:host|hostname|ip|address)$/i.test(childKey) && typeof childValue === 'string') {
|
|
951
|
-
out[childKey] = '127.0.0.1'
|
|
952
|
-
}
|
|
953
|
-
else {
|
|
954
|
-
out[childKey] = normalizeLocalNetworkConfig(childValue, portMap, childKey)
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
return out
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
async function simulatorScene(scene) {
|
|
961
|
-
const presetResponse = await sim('GET', `/api/presets/${encodeURIComponent(scene.preset)}`)
|
|
962
|
-
const blueprint = requireSuccess(presetResponse, `${scene.id} simulator preset`)
|
|
963
|
-
if (!blueprint?.plantModel || !Array.isArray(blueprint.nodes)) throw new Error(`${scene.id} simulator preset shape is invalid`)
|
|
964
|
-
|
|
965
|
-
const portMapByDeviceId = new Map()
|
|
966
|
-
const toCreate = []
|
|
967
|
-
let nextPort = 44_000 + evidence.experiment.scenes.length * 100
|
|
968
|
-
for (const raw of blueprint.nodes) {
|
|
969
|
-
const node = structuredClone(raw)
|
|
970
|
-
if ((node.protocol && /serial|rtu/i.test(String(node.protocol))) || /serialPort|comPort|devicePath/i.test(JSON.stringify(node.config ?? {}))) continue
|
|
971
|
-
node.config ||= {}
|
|
972
|
-
const oldPort = Number(node.config.port)
|
|
973
|
-
const portMap = new Map()
|
|
974
|
-
if (Number.isInteger(oldPort) && oldPort > 0) {
|
|
975
|
-
while (allocatedDevicePorts.includes(nextPort) || nextPort === FORBIDDEN_PORT) nextPort += 1
|
|
976
|
-
await assertFreeLoopback(nextPort, `${scene.id}-simulator-device`)
|
|
977
|
-
portMap.set(oldPort, nextPort)
|
|
978
|
-
allocatedDevicePorts.push(nextPort)
|
|
979
|
-
noteIsolation(`${scene.id}-device-port-free-loopback`, true, { port: nextPort, host: '127.0.0.1', protocol: node.protocol ?? 'unspecified' })
|
|
980
|
-
node.config.port = nextPort
|
|
981
|
-
nextPort += 1
|
|
982
|
-
}
|
|
983
|
-
node.config = normalizeLocalNetworkConfig(node.config, portMap)
|
|
984
|
-
if (node.protocol === 'mqtt' || /mqtt/i.test(String(node.protocol))) node.config.brokerUrl = `mqtt://127.0.0.1:${MQTT_PORT}`
|
|
985
|
-
portMapByDeviceId.set(node.id, portMap)
|
|
986
|
-
toCreate.push(node)
|
|
987
|
-
}
|
|
988
|
-
if (toCreate.length === 0) throw new Error(`${scene.id} simulator preset has no loopback-safe device nodes`)
|
|
989
|
-
|
|
990
|
-
for (const node of toCreate) {
|
|
991
|
-
const created = await sim('POST', '/api/nodes', node)
|
|
992
|
-
requireSuccess(created, `${scene.id} simulator device ${safeText(node.id, 80)}`)
|
|
993
|
-
}
|
|
994
|
-
const plant = { ...blueprint.plantModel, id: `${TAG}-${scene.id}`, seed: 42, timeScale: 1, truthExport: false }
|
|
995
|
-
const loaded = await sim('PUT', '/api/plant/config', { plantModel: plant, warm: true, upsert: true })
|
|
996
|
-
requireSuccess(loaded, `${scene.id} simulator plant model`)
|
|
997
|
-
|
|
998
|
-
const exports = []
|
|
999
|
-
for (const node of toCreate) {
|
|
1000
|
-
const result = await sim('GET', `/api/nodes/${encodeURIComponent(node.id)}/export`)
|
|
1001
|
-
const data = requireSuccess(result, `${scene.id} simulator export ${safeText(node.id, 80)}`)
|
|
1002
|
-
for (const item of data?.items ?? []) exports.push({ ...item, deviceId: node.id })
|
|
1003
|
-
}
|
|
1004
|
-
for (const item of exports) {
|
|
1005
|
-
item.driverConfig = normalizeLocalNetworkConfig(item.driverConfig ?? {}, portMapByDeviceId.get(item.deviceId) ?? new Map())
|
|
1006
|
-
for (const [key, value] of Object.entries(item.driverConfig)) {
|
|
1007
|
-
if (/^(?:host|hostname|ip|address)$/i.test(key) && !['127.0.0.1', 'localhost', '::1'].includes(String(value))) {
|
|
1008
|
-
throw new Error(`${scene.id} exported driver config escaped loopback boundary`)
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
const mv = exports.find(item => item.deviceId === scene.sourceDevice && item.signal === scene.mvSignal)
|
|
1013
|
-
const cv = exports.find(item => item.signal === scene.cvSignal)
|
|
1014
|
-
if (!mv || !cv) throw new Error(`${scene.id} simulator export lacks required MV/CV signals`)
|
|
1015
|
-
if (!['opcua', 'modbus-tcp'].includes(String(mv.driver))) throw new Error(`${scene.id} MV driver is outside the approved simulator protocol set`)
|
|
1016
|
-
const evidenceSignal = signal => Object.fromEntries(Object.entries(signal).filter(([key]) => key !== 'curl'))
|
|
1017
|
-
return {
|
|
1018
|
-
mv: evidenceSignal(mv),
|
|
1019
|
-
cv: evidenceSignal(cv),
|
|
1020
|
-
plant: { id: plant.id, kind: plant.kind ?? 'simulator', seed: 42, timeScale: 1 },
|
|
1021
|
-
deviceCount: toCreate.length,
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
async function registerAdmin() {
|
|
1026
|
-
const response = await app('POST', '/api/users/register', {
|
|
1027
|
-
name: `Paper Test ${TAG}`,
|
|
1028
|
-
email: `${TAG}@example.invalid`,
|
|
1029
|
-
password: `Paper-${Date.now()}-safe9`,
|
|
1030
|
-
}, { token: undefined })
|
|
1031
|
-
const data = requireSuccess(response, 'isolated synthetic administrator registration')
|
|
1032
|
-
if (!data?.token || data?.user?.role !== 'admin') throw new Error('fresh-home registration did not return its first administrator token')
|
|
1033
|
-
authToken = String(data.token)
|
|
1034
|
-
syntheticAdminId = String(data.user.id)
|
|
1035
|
-
return { id: syntheticAdminId, role: 'admin' }
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
async function verifyRagBridgeOutboundDisabled() {
|
|
1039
|
-
const ragBridgeHealth = requireSuccess(await app('GET', '/api/plugins/rag-bridge/health'), 'rag-bridge outbound guard health check')
|
|
1040
|
-
const deadline = Date.now() + 3_000
|
|
1041
|
-
let startupLogConfirmed = false
|
|
1042
|
-
while (Date.now() < deadline) {
|
|
1043
|
-
startupLogConfirmed = /\[rag-bridge\].*出站调用已禁用:/.test(readFileSync(APP_LOG, 'utf8'))
|
|
1044
|
-
if (startupLogConfirmed) break
|
|
1045
|
-
await delay(100)
|
|
1046
|
-
}
|
|
1047
|
-
noteIsolation('rag-bridge-outbound-disabled', ragBridgeHealth?.outbound === false && startupLogConfirmed, {
|
|
1048
|
-
setting: 'plugins.rag-bridge.base_url',
|
|
1049
|
-
pluginHealthOutbound: ragBridgeHealth?.outbound ?? null,
|
|
1050
|
-
startupLogConfirmed,
|
|
1051
|
-
})
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
function piFixtureSystemPrompt(scene, recipe, control, decisionStimulus) {
|
|
1055
|
-
const selected = Number(scene.fixtureCandidate)
|
|
1056
|
-
return [
|
|
1057
|
-
'You are operating AgentWorkShop for a bounded integration test in a local process simulator.',
|
|
1058
|
-
`Process scene: ${scene.processDescription}.`,
|
|
1059
|
-
`Before task submission, the registered drivers measured the control at ${decisionStimulus.controlValue} ${control.unit} and the process variable at ${decisionStimulus.processValue} ${decisionStimulus.processUnit}.`,
|
|
1060
|
-
`The task target band is ${decisionStimulus.targetMin} to ${decisionStimulus.targetMax} ${decisionStimulus.processUnit}.`,
|
|
1061
|
-
`This local deterministic model fixture is configured to test one bounded candidate: ${selected} ${control.unit}. It is the only permitted value for this request.`,
|
|
1062
|
-
`Call recipe_trial exactly once with recipe_id "${recipe.id}", one params entry for node_id "${control.id}" and value ${selected}. State only that this is a deterministic integration fixture in hypothesis.`,
|
|
1063
|
-
'After receiving the recipe_trial result, call complete_task exactly once on the active root task. Include the selected value and returned command-verification outcome in a concise summary and deliverable.',
|
|
1064
|
-
'Do not make any other tool calls. Do not retry. Do not create, update, apply, or roll back a recipe. Do not claim that the trial improves or settles the process.',
|
|
1065
|
-
'After the complete_task result, give a brief factual report and make no further tool calls.',
|
|
1066
|
-
].join('\n')
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
async function setupScene(scene, simDetails) {
|
|
1070
|
-
currentScene = scene.id
|
|
1071
|
-
currentStage = `${scene.id}:application-setup`
|
|
1072
|
-
const sceneEvidence = {
|
|
1073
|
-
id: scene.id,
|
|
1074
|
-
simulatorPreset: scene.preset,
|
|
1075
|
-
simulator: simDetails,
|
|
1076
|
-
status: 'running',
|
|
1077
|
-
approvals: [],
|
|
1078
|
-
runs: [],
|
|
1079
|
-
}
|
|
1080
|
-
evidence.experiment.scenes.push(sceneEvidence)
|
|
1081
|
-
|
|
1082
|
-
const line = requireSuccess(await app('POST', '/api/workshop/dcw/lines', {
|
|
1083
|
-
name: `${TAG}-${scene.id}`,
|
|
1084
|
-
description: 'Synthetic isolated paper integration run',
|
|
1085
|
-
simulated: true,
|
|
1086
|
-
simSceneId: scene.preset,
|
|
1087
|
-
controlMode: 'manual',
|
|
1088
|
-
}), `${scene.id} line creation`).line
|
|
1089
|
-
const product = requireSuccess(await app('POST', '/api/workshop/dcw/products', {
|
|
1090
|
-
name: `${TAG}-${scene.id}-product`, lineId: line.id,
|
|
1091
|
-
}), `${scene.id} product creation`).product
|
|
1092
|
-
const template = requireSuccess(await app('POST', '/api/workshop/dcw/templates', {
|
|
1093
|
-
name: `${TAG}-${scene.id}-control-template`,
|
|
1094
|
-
unit: simDetails.mv.unit,
|
|
1095
|
-
min: simDetails.mv.min,
|
|
1096
|
-
max: simDetails.mv.max,
|
|
1097
|
-
decimals: simDetails.mv.decimals ?? 0,
|
|
1098
|
-
}), `${scene.id} control template creation`).template
|
|
1099
|
-
const control = requireSuccess(await app('POST', '/api/workshop/dcw', {
|
|
1100
|
-
templateRef: template.key,
|
|
1101
|
-
name: `${TAG}-${scene.id}-control`,
|
|
1102
|
-
driver: simDetails.mv.driver,
|
|
1103
|
-
driverConfig: simDetails.mv.driverConfig,
|
|
1104
|
-
lineId: line.id,
|
|
1105
|
-
min: simDetails.mv.min,
|
|
1106
|
-
max: simDetails.mv.max,
|
|
1107
|
-
unit: simDetails.mv.unit,
|
|
1108
|
-
decimals: simDetails.mv.decimals ?? 0,
|
|
1109
|
-
stepLimit: 30,
|
|
1110
|
-
writeLockSeconds: 0,
|
|
1111
|
-
holdIntervalMs: 0,
|
|
1112
|
-
readIntervalMs: 500,
|
|
1113
|
-
semantics: `Bounded simulated ${scene.mvSignal} setpoint for integration evidence`,
|
|
1114
|
-
}), `${scene.id} control node creation`).node
|
|
1115
|
-
const daq = requireSuccess(await app('POST', '/api/workshop/daq', {
|
|
1116
|
-
templateRef: 'daq-temp-tc',
|
|
1117
|
-
name: `${TAG}-${scene.id}-daq-cv`,
|
|
1118
|
-
driver: simDetails.cv.driver,
|
|
1119
|
-
driverConfig: simDetails.cv.driverConfig,
|
|
1120
|
-
lineId: line.id,
|
|
1121
|
-
min: simDetails.cv.min,
|
|
1122
|
-
max: simDetails.cv.max,
|
|
1123
|
-
unit: simDetails.cv.unit,
|
|
1124
|
-
intervalMs: 1000,
|
|
1125
|
-
publishIntervalMs: 0,
|
|
1126
|
-
semantics: `Bounded simulated ${scene.cvSignal} controlled variable for run-tagged sampling`,
|
|
1127
|
-
}), `${scene.id} DAQ node creation`).node
|
|
1128
|
-
const recipe = requireSuccess(await app('POST', '/api/workshop/dcw/recipes', {
|
|
1129
|
-
name: `${TAG}-${scene.id}-recipe`,
|
|
1130
|
-
productId: product.id,
|
|
1131
|
-
params: [{ nodeId: control.id, templateRef: template.key, value: scene.baseline, min: simDetails.mv.min, max: simDetails.mv.max, stepLimit: 30 }],
|
|
1132
|
-
daqWindows: [{ nodeId: daq.id, min: simDetails.cv.min, max: simDetails.cv.max }],
|
|
1133
|
-
}), `${scene.id} recipe creation`).recipe
|
|
1134
|
-
|
|
1135
|
-
const start = requireSuccess(await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(line.id)}/start`, { recipeId: recipe.id }), `${scene.id} line start`)
|
|
1136
|
-
const runId = String(start.run?.id ?? '')
|
|
1137
|
-
if (!runId) throw new Error(`${scene.id} line start returned no run identifier`)
|
|
1138
|
-
sceneEvidence.activeRun = { id: runId, status: start.run?.status ?? null, startedAt: start.run?.startedAt ?? null, recipeId: start.run?.recipeId ?? recipe.id }
|
|
1139
|
-
|
|
1140
|
-
let decisionStimulus
|
|
1141
|
-
if (HARNESS_MODE === 'pi-local-fixture') {
|
|
1142
|
-
let controlRead
|
|
1143
|
-
let controlReadAttempts = 0
|
|
1144
|
-
do {
|
|
1145
|
-
controlRead = await app('POST', `/api/workshop/dcw/${encodeURIComponent(control.id)}/read`)
|
|
1146
|
-
controlReadAttempts += 1
|
|
1147
|
-
if (controlRead.status === 409 && controlReadAttempts < 3) await delay(500)
|
|
1148
|
-
} while (controlRead.status === 409 && controlReadAttempts < 3)
|
|
1149
|
-
const controlReadData = requireSuccess(controlRead, `${scene.id} pre-task control read`)
|
|
1150
|
-
const controlData = controlReadData?.outcome ?? controlReadData?.read ?? controlReadData
|
|
1151
|
-
const controlValue = Number(controlData?.value ?? controlData?.data?.value)
|
|
1152
|
-
let processProbeResponse
|
|
1153
|
-
let processProbeAttempts = 0
|
|
1154
|
-
do {
|
|
1155
|
-
processProbeResponse = await app('POST', `/api/workshop/daq/${encodeURIComponent(daq.id)}/test`)
|
|
1156
|
-
processProbeAttempts += 1
|
|
1157
|
-
if (processProbeResponse.status === 409 && processProbeAttempts < 3) await delay(500)
|
|
1158
|
-
} while (processProbeResponse.status === 409 && processProbeAttempts < 3)
|
|
1159
|
-
const processProbe = requireSuccess(processProbeResponse, `${scene.id} pre-task process probe`).test
|
|
1160
|
-
const processValue = Number(processProbe?.sampleValue)
|
|
1161
|
-
if (!Number.isFinite(controlValue) || processProbe?.ok !== true || !Number.isFinite(processValue)) {
|
|
1162
|
-
throw new Error(`${scene.id} pre-task protocol reads did not provide finite control and process values`)
|
|
1163
|
-
}
|
|
1164
|
-
decisionStimulus = {
|
|
1165
|
-
controlValue,
|
|
1166
|
-
processValue,
|
|
1167
|
-
processUnit: simDetails.cv.unit,
|
|
1168
|
-
targetMin: scene.targetMin,
|
|
1169
|
-
targetMax: scene.targetMax,
|
|
1170
|
-
allowedValues: [...scene.candidates],
|
|
1171
|
-
probeDriver: simDetails.cv.driver,
|
|
1172
|
-
probeLatencyMs: Number.isFinite(Number(processProbe.latencyMs)) ? Number(processProbe.latencyMs) : null,
|
|
1173
|
-
controlReadAttempts,
|
|
1174
|
-
processProbeAttempts,
|
|
1175
|
-
measuredAt: new Date().toISOString(),
|
|
1176
|
-
}
|
|
1177
|
-
sceneEvidence.decisionStimulus = decisionStimulus
|
|
1178
|
-
sceneEvidence.simulator.candidateChoices = [...scene.candidates]
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
const channel = requireSuccess(await app('POST', '/api/workshop/channels', {
|
|
1182
|
-
name: `${TAG}-${scene.id}-harness-channel`,
|
|
1183
|
-
description: 'Registered Pi CLI with a local deterministic model API fixture for simulator integration evidence',
|
|
1184
|
-
}), `${scene.id} channel creation`)
|
|
1185
|
-
const agentConfig = {
|
|
1186
|
-
command: PI_COMMAND,
|
|
1187
|
-
cwd: HOME,
|
|
1188
|
-
baseUrl: APP_BASE,
|
|
1189
|
-
provider: PI_PROVIDER,
|
|
1190
|
-
model: PI_MODEL,
|
|
1191
|
-
promptTimeoutMs: PI_PROMPT_TIMEOUT_MS,
|
|
1192
|
-
systemPromptPrefix: piFixtureSystemPrompt(scene, recipe, control, decisionStimulus),
|
|
1193
|
-
}
|
|
1194
|
-
const agent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(channel.channelId)}/agents`, {
|
|
1195
|
-
name: `${TAG}-${scene.id}-pi-local-fixture`,
|
|
1196
|
-
harness: 'pi',
|
|
1197
|
-
role: 'lead',
|
|
1198
|
-
config: agentConfig,
|
|
1199
|
-
}), `${scene.id} registered OMP lead creation`)
|
|
1200
|
-
|
|
1201
|
-
const recipeBinding = requireSuccess(await app('POST', '/api/workshop/agent-tools/bindings', {
|
|
1202
|
-
agentId: agent.id, nodeId: recipe.id, kind: 'recipe',
|
|
1203
|
-
}), `${scene.id} recipe binding`).binding
|
|
1204
|
-
const daqBinding = requireSuccess(await app('POST', '/api/workshop/agent-tools/bindings', {
|
|
1205
|
-
agentId: agent.id, nodeId: daq.id, kind: 'daq', mode: 'auto',
|
|
1206
|
-
}), `${scene.id} DAQ binding`).binding
|
|
1207
|
-
check(`${scene.id}-registered-pi`, agent.harness === 'pi' && Boolean(agent.id), { harness: agent.harness, agentId: agent.id, provider: PI_PROVIDER, model: PI_MODEL })
|
|
1208
|
-
check(`${scene.id}-manual-recipe-binding`, recipeBinding.kind === 'recipe' && recipeBinding.mode === 'manual', { kind: recipeBinding.kind, mode: recipeBinding.mode })
|
|
1209
|
-
check(`${scene.id}-daq-observation-binding`, daqBinding.kind === 'daq', { kind: daqBinding.kind })
|
|
1210
|
-
|
|
1211
|
-
sceneEvidence.entities = { lineId: line.id, productId: product.id, recipeId: recipe.id, controlNodeId: control.id, daqNodeId: daq.id, channelId: channel.channelId, agentId: agent.id }
|
|
1212
|
-
sceneEvidence.bindings = { recipe: { kind: recipeBinding.kind, mode: recipeBinding.mode }, daq: { kind: daqBinding.kind, mode: daqBinding.mode } }
|
|
1213
|
-
sceneEvidence.routePolicy = { tool: 'recipe_trial', emergency: false, cadenceBypass: false, recipeBindingMode: recipeBinding.mode }
|
|
1214
|
-
sceneEvidence.status = 'setup-complete'
|
|
1215
|
-
return { line, product, template, control, daq, recipe, channel, agent, runId, evidence: sceneEvidence }
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
async function submitFixtureTask(context) {
|
|
1219
|
-
currentStage = `${context.evidence.id}:submit-lead-task`
|
|
1220
|
-
const sent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/tasks`, {
|
|
1221
|
-
title: `Isolated ${context.evidence.id} recipe_trial verification`,
|
|
1222
|
-
description: [
|
|
1223
|
-
`Execute the preconfigured isolated ${context.evidence.id} recipe_trial candidate exactly once and wait for synthetic human approval.`,
|
|
1224
|
-
'After the verified recipe_trial result returns, call complete_task exactly once with a concise factual deliverable. Do not claim process improvement.',
|
|
1225
|
-
'Do not make any other host-tool calls, retry, or create/update/apply/roll back a recipe.',
|
|
1226
|
-
].join(' '),
|
|
1227
|
-
fromLabel: 'Synthetic isolated test driver',
|
|
1228
|
-
}), `${context.evidence.id} lead task submission`)
|
|
1229
|
-
context.evidence.taskId = sent.id ?? sent.task?.id ?? null
|
|
1230
|
-
if (piFixtureTarget) piFixtureTarget.taskId = context.evidence.taskId
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
async function submitRealOmpTask(context) {
|
|
1234
|
-
currentStage = `${context.evidence.id}:submit-real-omp-task`
|
|
1235
|
-
const sent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/tasks`, {
|
|
1236
|
-
title: `R20 ${context.evidence.id} recipe_trial with explicit task closure`,
|
|
1237
|
-
description: [
|
|
1238
|
-
'Use the measured process context in your registered system prompt to choose one candidate from its prevalidated set.',
|
|
1239
|
-
`Call recipe_trial exactly once with recipe_id ${context.recipe.id} and one params entry for node_id ${context.control.id} using your selected value.`,
|
|
1240
|
-
'After receiving the recipe_trial result, call complete_task exactly once on the active root task shown in the supervision context. Include the selected value and returned command-verification outcome in a concise summary and deliverable.',
|
|
1241
|
-
'Do not make any other tool calls. Do not retry, save, update, apply, or roll back a recipe. If no candidate is justified, abstain and explicitly close the task with that limitation.',
|
|
1242
|
-
].join(' '),
|
|
1243
|
-
fromLabel: 'Synthetic isolated R20 test driver',
|
|
1244
|
-
}), `${context.evidence.id} real OMP lead task submission`)
|
|
1245
|
-
context.evidence.taskId = sent.id ?? sent.task?.id ?? null
|
|
1246
|
-
if (!context.evidence.taskId) throw new Error(`${context.evidence.id} real OMP task submission returned no task identifier`)
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
function taskToolEvents(task) {
|
|
1250
|
-
const events = []
|
|
1251
|
-
for (const message of task?.history ?? []) {
|
|
1252
|
-
for (const part of message?.parts ?? []) {
|
|
1253
|
-
const text = typeof part?.text === 'string' ? part.text : ''
|
|
1254
|
-
const match = text.match(/^🔧\s+([a-z][a-z\d_]*)/i)
|
|
1255
|
-
if (!match) continue
|
|
1256
|
-
events.push({
|
|
1257
|
-
toolName: match[1],
|
|
1258
|
-
phase: /(?:✅\s*完成|❌\s*失败)/.test(text) ? 'result' : 'call',
|
|
1259
|
-
isError: /❌\s*失败/.test(text),
|
|
1260
|
-
messageId: message.messageId ?? null,
|
|
1261
|
-
text,
|
|
1262
|
-
})
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
return events
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
async function readRealOmpTask(context) {
|
|
1269
|
-
const result = await app('GET', `/api/workshop/tasks/${encodeURIComponent(context.evidence.taskId)}?channelId=${encodeURIComponent(context.channel.channelId)}`)
|
|
1270
|
-
if (result.status !== 200) throw new Error(`${context.evidence.id} task detail returned HTTP ${result.status}`)
|
|
1271
|
-
return result.data
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
async function waitForRealOmpTaskCompletion(context) {
|
|
1275
|
-
const deadline = Date.now() + REAL_OMP_TASK_COMPLETION_TIMEOUT_MS
|
|
1276
|
-
let latest
|
|
1277
|
-
while (Date.now() < deadline) {
|
|
1278
|
-
latest = await readRealOmpTask(context)
|
|
1279
|
-
if (latest.state === 'COMPLETED') return latest
|
|
1280
|
-
if (['FAILED', 'CANCELED'].includes(latest.state)) {
|
|
1281
|
-
throw new Error(`${context.evidence.id} task reached ${latest.state} before completing the approved operation`)
|
|
1282
|
-
}
|
|
1283
|
-
await delay(500)
|
|
1284
|
-
}
|
|
1285
|
-
throw new Error(`${context.evidence.id} task did not reach COMPLETED within the bounded post-approval window (state=${latest?.state ?? 'unknown'})`)
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
function assertSingleRealOmpCall(context, task) {
|
|
1289
|
-
const events = taskToolEvents(task)
|
|
1290
|
-
const calls = events.filter(event => event.phase === 'call')
|
|
1291
|
-
const recipeCalls = calls.filter(event => event.toolName === 'recipe_trial')
|
|
1292
|
-
const recipeResults = events.filter(event => event.toolName === 'recipe_trial' && event.phase === 'result')
|
|
1293
|
-
const completionCalls = calls.filter(event => event.toolName === 'complete_task')
|
|
1294
|
-
// The active lead turn is journaled through both the task-event mapper and
|
|
1295
|
-
// the supervisor listener. A single host invocation can therefore appear
|
|
1296
|
-
// twice in history; identical start text identifies that mirror. Route
|
|
1297
|
-
// ledgers below remain authoritative for the number of executed trials.
|
|
1298
|
-
const uniqueRecipeCalls = [...new Set(recipeCalls.map(event => event.text))]
|
|
1299
|
-
if (events.some(event => !['recipe_trial', 'complete_task'].includes(event.toolName))
|
|
1300
|
-
|| recipeCalls.length < 1 || recipeCalls.length > 2 || uniqueRecipeCalls.length !== 1
|
|
1301
|
-
|| recipeResults.length < 1 || recipeResults.length > 2 || recipeResults.some(event => event.isError)
|
|
1302
|
-
|| completionCalls.length !== 1) {
|
|
1303
|
-
throw new Error(`${context.evidence.id} OMP task history must show one recipe_trial invocation (allowing its mirrored journal entry), a successful result, and one explicit task-completion call`)
|
|
1304
|
-
}
|
|
1305
|
-
return { events, calls: [recipeCalls[0]], results: [recipeResults[0]], completionCalls }
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
async function approveRealOmpTrial(context) {
|
|
1309
|
-
currentStage = `${context.evidence.id}:await-real-omp-hitl-approval`
|
|
1310
|
-
const deadline = Date.now() + REAL_OMP_APPROVAL_TIMEOUT_MS
|
|
1311
|
-
let pending
|
|
1312
|
-
let latestTask
|
|
1313
|
-
while (Date.now() < deadline) {
|
|
1314
|
-
latestTask = await readRealOmpTask(context)
|
|
1315
|
-
if (['FAILED', 'CANCELED', 'COMPLETED'].includes(latestTask.state)) {
|
|
1316
|
-
throw new Error(`${context.evidence.id} task reached ${latestTask.state} before synthetic approval`)
|
|
1317
|
-
}
|
|
1318
|
-
const result = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
|
|
1319
|
-
if (result.status === 200) {
|
|
1320
|
-
const matches = (result.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.nodeId === `recipe:${context.recipe.id}` && item.status === 'pending')
|
|
1321
|
-
if (matches.length > 1) throw new Error(`${context.evidence.id} has multiple pending real OMP trial approvals`)
|
|
1322
|
-
if (matches.length === 1) {
|
|
1323
|
-
const payload = matches[0].payload
|
|
1324
|
-
const params = Array.isArray(payload?.params) ? payload.params : []
|
|
1325
|
-
const proposedValue = Number(params[0]?.to)
|
|
1326
|
-
const decisionStimulus = context.evidence.decisionStimulus
|
|
1327
|
-
const allowedValues = decisionStimulus?.allowedValues ?? []
|
|
1328
|
-
const isExpectedTrial = payload?.kind === 'recipe-gate'
|
|
1329
|
-
&& payload?.op === 'trial'
|
|
1330
|
-
&& payload?.recipeId === context.recipe.id
|
|
1331
|
-
&& payload?.emergency !== true
|
|
1332
|
-
&& payload?.emergency !== 'true'
|
|
1333
|
-
&& params.length === 1
|
|
1334
|
-
&& params[0]?.nodeId === context.control.id
|
|
1335
|
-
&& Number.isFinite(proposedValue)
|
|
1336
|
-
&& allowedValues.includes(proposedValue)
|
|
1337
|
-
&& proposedValue >= Number(context.evidence.simulator.mv.min)
|
|
1338
|
-
&& proposedValue <= Number(context.evidence.simulator.mv.max)
|
|
1339
|
-
&& Math.abs(proposedValue - Number(decisionStimulus.controlValue)) <= 30
|
|
1340
|
-
if (!isExpectedTrial) throw new Error(`${context.evidence.id} refused a pending approval outside the registered recipe_trial candidate set`)
|
|
1341
|
-
context.evidence.simulator.candidate = proposedValue
|
|
1342
|
-
context.evidence.modelDecision = {
|
|
1343
|
-
source: 'registered OMP host-tool proposal, checked against current protocol reads and prevalidated set',
|
|
1344
|
-
controlValue: decisionStimulus.controlValue,
|
|
1345
|
-
processValue: decisionStimulus.processValue,
|
|
1346
|
-
targetBand: [decisionStimulus.targetMin, decisionStimulus.targetMax],
|
|
1347
|
-
allowedValues,
|
|
1348
|
-
selectedValue: proposedValue,
|
|
1349
|
-
selectionRationale: safeText(payload?.hypothesis ?? payload?.rationale ?? '', 400),
|
|
1350
|
-
selectedValueWithinRangeAndStep: true,
|
|
1351
|
-
}
|
|
1352
|
-
pending = matches[0]
|
|
1353
|
-
break
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
await delay(500)
|
|
1357
|
-
}
|
|
1358
|
-
if (!pending) throw new Error(`${context.evidence.id} real OMP recipe_trial approval did not appear within the bounded window`)
|
|
1359
|
-
context.evidence.approvals.push({ id: pending.id, statusBeforeDecision: pending.status, nodeId: pending.nodeId, title: pending.title ?? null, candidateValue: context.evidence.simulator.candidate, decision: 'approve' })
|
|
1360
|
-
requireSuccess(await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(pending.id)}/decide`, {
|
|
1361
|
-
approved: true,
|
|
1362
|
-
comment: 'Approved for the bounded R20 local simulator integration check.',
|
|
1363
|
-
}), `${context.evidence.id} synthetic real OMP HITL approval`)
|
|
1364
|
-
const history = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=history`)
|
|
1365
|
-
const finalApproval = (history.data?.approvals ?? []).find(item => item.id === pending.id)
|
|
1366
|
-
if (history.status !== 200 || finalApproval?.status !== 'approved' || finalApproval?.decidedBy !== syntheticAdminId) {
|
|
1367
|
-
throw new Error(`${context.evidence.id} real OMP HITL history did not confirm the synthetic administrator decision`)
|
|
1368
|
-
}
|
|
1369
|
-
context.evidence.approvals[0] = {
|
|
1370
|
-
...context.evidence.approvals[0],
|
|
1371
|
-
statusAfterDecision: finalApproval.status,
|
|
1372
|
-
decisionActor: 'synthetic isolated administrator via protected approval API',
|
|
1373
|
-
commentRecorded: finalApproval.comment === 'Approved for the bounded R20 local simulator integration check.',
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
async function captureRealOmpUsage(context) {
|
|
1378
|
-
const unavailable = {
|
|
1379
|
-
source: 'not exposed by the channel queue endpoint',
|
|
1380
|
-
context: null,
|
|
1381
|
-
requestInputTokens: null,
|
|
1382
|
-
requestOutputTokens: null,
|
|
1383
|
-
costUsd: null,
|
|
1384
|
-
costAvailable: false,
|
|
1385
|
-
}
|
|
1386
|
-
if (!context?.channel?.channelId || !context?.agent?.id) return unavailable
|
|
1387
|
-
try {
|
|
1388
|
-
const queueResult = await app('GET', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/queue`)
|
|
1389
|
-
if (queueResult.status !== 200) return unavailable
|
|
1390
|
-
const queue = extractPayload(queueResult.body)
|
|
1391
|
-
const agentStatus = (Array.isArray(queue) ? queue : []).find(item => item.agentId === context.agent.id)
|
|
1392
|
-
const raw = agentStatus?.context
|
|
1393
|
-
if (!raw) return unavailable
|
|
1394
|
-
return {
|
|
1395
|
-
source: 'channel queue OMP context snapshot (not request-level billing)',
|
|
1396
|
-
context: {
|
|
1397
|
-
usedTokens: Number.isFinite(Number(raw.usedTokens)) ? Number(raw.usedTokens) : null,
|
|
1398
|
-
contextWindow: Number.isFinite(Number(raw.contextWindow)) ? Number(raw.contextWindow) : null,
|
|
1399
|
-
percent: Number.isFinite(Number(raw.percent)) ? Number(raw.percent) : null,
|
|
1400
|
-
compacting: raw.compacting === true,
|
|
1401
|
-
},
|
|
1402
|
-
requestInputTokens: null,
|
|
1403
|
-
requestOutputTokens: null,
|
|
1404
|
-
costUsd: null,
|
|
1405
|
-
costAvailable: false,
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
catch { return unavailable }
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
async function approvePendingTrial(context) {
|
|
1412
|
-
currentStage = `${context.evidence.id}:manual-hitl-approval`
|
|
1413
|
-
const deadline = Date.now() + 20_000
|
|
1414
|
-
let pending
|
|
1415
|
-
while (Date.now() < deadline) {
|
|
1416
|
-
const result = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
|
|
1417
|
-
if (result.status === 200) {
|
|
1418
|
-
const matches = (result.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.nodeId === `recipe:${context.recipe.id}` && item.status === 'pending')
|
|
1419
|
-
if (matches.length > 1) throw new Error(`${context.evidence.id} has multiple pending trial approvals`)
|
|
1420
|
-
if (matches.length === 1) {
|
|
1421
|
-
pending = matches[0]
|
|
1422
|
-
break
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
await delay(400)
|
|
1426
|
-
}
|
|
1427
|
-
if (!pending) throw new Error(`${context.evidence.id} manual recipe_trial HITL approval did not appear within the bounded window`)
|
|
1428
|
-
const payload = pending.payload ?? {}
|
|
1429
|
-
const params = Array.isArray(payload.params) ? payload.params : []
|
|
1430
|
-
const proposedValue = Number(params[0]?.to)
|
|
1431
|
-
if (payload.kind !== 'recipe-gate'
|
|
1432
|
-
|| payload.op !== 'trial'
|
|
1433
|
-
|| payload.recipeId !== context.recipe.id
|
|
1434
|
-
|| params.length !== 1
|
|
1435
|
-
|| params[0]?.nodeId !== context.control.id
|
|
1436
|
-
|| proposedValue !== Number(piFixtureTarget?.value)
|
|
1437
|
-
|| payload.emergency === true
|
|
1438
|
-
|| payload.emergency === 'true') {
|
|
1439
|
-
throw new Error(`${context.evidence.id} refused a Pi approval outside the scripted bounded recipe_trial request`)
|
|
1440
|
-
}
|
|
1441
|
-
context.evidence.simulator.candidate = proposedValue
|
|
1442
|
-
context.evidence.modelDecision = {
|
|
1443
|
-
source: 'registered Pi host-tool request generated by a deterministic loopback model fixture',
|
|
1444
|
-
controlValue: context.evidence.decisionStimulus?.controlValue ?? null,
|
|
1445
|
-
processValue: context.evidence.decisionStimulus?.processValue ?? null,
|
|
1446
|
-
targetBand: [context.evidence.decisionStimulus?.targetMin, context.evidence.decisionStimulus?.targetMax],
|
|
1447
|
-
allowedValues: context.evidence.decisionStimulus?.allowedValues ?? [],
|
|
1448
|
-
selectedValue: proposedValue,
|
|
1449
|
-
selectionRationale: safeText(payload.hypothesis ?? payload.rationale ?? '', 400),
|
|
1450
|
-
selectedValueWithinRangeAndStep: true,
|
|
1451
|
-
}
|
|
1452
|
-
context.evidence.approvals.push({ id: pending.id, taskId: context.evidence.taskId, statusBeforeDecision: pending.status, nodeId: pending.nodeId, candidateValue: proposedValue, title: pending.title ?? null, decision: 'approve' })
|
|
1453
|
-
const decided = await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(pending.id)}/decide`, {
|
|
1454
|
-
approved: true,
|
|
1455
|
-
comment: 'Approved for the isolated deterministic simulator integration check.',
|
|
1456
|
-
})
|
|
1457
|
-
requireSuccess(decided, `${context.evidence.id} explicit HITL approval`)
|
|
1458
|
-
const history = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=history`)
|
|
1459
|
-
const finalApproval = (history.data?.approvals ?? []).find(item => item.id === pending.id)
|
|
1460
|
-
if (history.status !== 200 || finalApproval?.status !== 'approved' || finalApproval?.decidedBy !== syntheticAdminId) {
|
|
1461
|
-
throw new Error(`${context.evidence.id} HITL approval history failed to confirm the explicit administrator decision`)
|
|
1462
|
-
}
|
|
1463
|
-
context.evidence.approvals[0] = {
|
|
1464
|
-
...context.evidence.approvals[0],
|
|
1465
|
-
statusAfterDecision: finalApproval.status,
|
|
1466
|
-
decisionActor: 'synthetic isolated administrator via protected approval API',
|
|
1467
|
-
commentRecorded: finalApproval.comment === 'Approved for the isolated deterministic simulator integration check.',
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
async function waitForPiTaskCompletion(context) {
|
|
1472
|
-
const deadline = Date.now() + PI_TASK_COMPLETION_TIMEOUT_MS
|
|
1473
|
-
let latest
|
|
1474
|
-
while (Date.now() < deadline) {
|
|
1475
|
-
latest = await readRealOmpTask(context)
|
|
1476
|
-
if (latest.assigneeId !== context.agent.id) {
|
|
1477
|
-
throw new Error(`${context.evidence.id} Pi task was not executed by its registered agent`)
|
|
1478
|
-
}
|
|
1479
|
-
if (latest.state === 'COMPLETED') return latest
|
|
1480
|
-
if (['FAILED', 'CANCELED'].includes(latest.state)) {
|
|
1481
|
-
throw new Error(`${context.evidence.id} Pi task reached ${latest.state} before returning the tool result`)
|
|
1482
|
-
}
|
|
1483
|
-
await delay(300)
|
|
1484
|
-
}
|
|
1485
|
-
throw new Error(`${context.evidence.id} Pi task did not complete within the bounded window (state=${latest?.state ?? 'unknown'})`)
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
async function collectSceneEvidence(context) {
|
|
1489
|
-
currentStage = `${context.evidence.id}:collect-result-and-observations`
|
|
1490
|
-
let trace
|
|
1491
|
-
let toolName
|
|
1492
|
-
let toolText
|
|
1493
|
-
let toolIsError
|
|
1494
|
-
let realTask
|
|
1495
|
-
let realToolEvents
|
|
1496
|
-
if (HARNESS_MODE === 'pi-local-fixture') {
|
|
1497
|
-
const finalTask = await waitForPiTaskCompletion(context)
|
|
1498
|
-
const traceDeadline = Date.now() + 10_000
|
|
1499
|
-
let sceneRequests = piApiTrace.filter(item => item.scene === context.evidence.id)
|
|
1500
|
-
while (sceneRequests.length < 3 && Date.now() < traceDeadline) {
|
|
1501
|
-
await delay(100)
|
|
1502
|
-
sceneRequests = piApiTrace.filter(item => item.scene === context.evidence.id)
|
|
1503
|
-
}
|
|
1504
|
-
const proposal = sceneRequests[0]
|
|
1505
|
-
const recipeResult = sceneRequests[1]
|
|
1506
|
-
const completionResult = sceneRequests[2]
|
|
1507
|
-
const traceChecks = {
|
|
1508
|
-
exactlyThreeModelRequests: sceneRequests.length === 3,
|
|
1509
|
-
recipeTrialCall: proposal?.response?.type === 'tool_call' && proposal?.response?.toolName === 'recipe_trial',
|
|
1510
|
-
approvedCandidateMatches: Number(proposal?.response?.candidate) === Number(context.evidence.simulator.candidate),
|
|
1511
|
-
completionToolAvailable: proposal?.toolNames?.includes('complete_task') === true,
|
|
1512
|
-
recipeResultFollowedByTaskClosure: recipeResult?.response?.type === 'tool_call' && recipeResult?.response?.toolName === 'complete_task',
|
|
1513
|
-
recipeResultReturnedToPi: recipeResult?.toolResultCallId === `call-${context.evidence.id}` && recipeResult?.toolResultMessageCount === 1 && Boolean(recipeResult?.toolResultText),
|
|
1514
|
-
recipeResultWasSuccessful: !/(?:isError\s*[:=]\s*true|❌\s*失败|tool error)/i.test(recipeResult?.toolResultText ?? ''),
|
|
1515
|
-
completeTaskResultReturnedToPi: completionResult?.response?.type === 'final_text_after_task_completion'
|
|
1516
|
-
&& completionResult?.toolResultCallId === `complete-${context.evidence.id}`
|
|
1517
|
-
&& completionResult?.toolResultMessageCount === 2
|
|
1518
|
-
&& /COMPLETED/.test(completionResult?.toolResultText ?? ''),
|
|
1519
|
-
}
|
|
1520
|
-
if (Object.values(traceChecks).some(passed => !passed)) {
|
|
1521
|
-
throw new Error(`${context.evidence.id} Pi model trace check failed: ${JSON.stringify(Object.fromEntries(Object.entries(traceChecks).filter(([, passed]) => !passed)))}`)
|
|
1522
|
-
}
|
|
1523
|
-
toolName = 'recipe_trial'
|
|
1524
|
-
toolText = recipeResult.toolResultText
|
|
1525
|
-
toolIsError = /(?:isError\s*[:=]\s*true|❌\s*失败|tool error)/i.test(toolText)
|
|
1526
|
-
context.evidence.modelExecution = {
|
|
1527
|
-
harness: 'registered Pi CLI adapter',
|
|
1528
|
-
provider: PI_PROVIDER,
|
|
1529
|
-
model: PI_MODEL,
|
|
1530
|
-
modelMode: 'deterministic local OpenAI-compatible fixture; no LLM or external provider',
|
|
1531
|
-
taskId: context.evidence.taskId,
|
|
1532
|
-
taskState: finalTask.state,
|
|
1533
|
-
taskCompleted: finalTask.state === 'COMPLETED',
|
|
1534
|
-
taskAssigneeMatchesRegisteredPi: finalTask.assigneeId === context.agent.id,
|
|
1535
|
-
modelApiRequests: sceneRequests.map(item => ({
|
|
1536
|
-
requestId: item.requestId,
|
|
1537
|
-
requestModel: item.requestModel,
|
|
1538
|
-
loopbackPeer: item.loopbackPeer,
|
|
1539
|
-
apiKeyMatchesLocalFixture: item.apiKeyMatchesLocalFixture,
|
|
1540
|
-
streamRequested: item.streamRequested,
|
|
1541
|
-
toolNames: item.toolNames,
|
|
1542
|
-
messageRoles: item.messageRoles,
|
|
1543
|
-
toolResultMessageCount: item.toolResultMessageCount,
|
|
1544
|
-
response: item.response,
|
|
1545
|
-
})),
|
|
1546
|
-
recipeTrialResultReturnedToPi: recipeResult.toolResultMessageCount === 1,
|
|
1547
|
-
completeTaskCallIssued: recipeResult.response.toolName === 'complete_task',
|
|
1548
|
-
completeTaskResultReturnedToPi: completionResult.toolResultMessageCount === 2,
|
|
1549
|
-
completeTaskResultConfirmed: /COMPLETED/.test(completionResult.toolResultText),
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
else if (HARNESS_MODE === 'real-omp') {
|
|
1553
|
-
// The supervisor journals compact host-tool start/result events on the
|
|
1554
|
-
// active root task. Approval and operation ledgers remain authoritative
|
|
1555
|
-
// for the proposal and its execution.
|
|
1556
|
-
realTask = await waitForRealOmpTaskCompletion(context)
|
|
1557
|
-
if (realTask.assigneeId !== context.agent.id) throw new Error(`${context.evidence.id} real OMP task was not executed by its registered lead agent`)
|
|
1558
|
-
realToolEvents = assertSingleRealOmpCall(context, realTask)
|
|
1559
|
-
const channelMessages = requireSuccess(await app('GET', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/messages?limit=500`), `${context.evidence.id} channel task evidence`)
|
|
1560
|
-
const taskMessages = (Array.isArray(channelMessages) ? channelMessages : []).filter(message => message.taskId === context.evidence.taskId)
|
|
1561
|
-
const usage = await captureRealOmpUsage(context)
|
|
1562
|
-
context.evidence.modelExecution = {
|
|
1563
|
-
provider: REAL_OMP_PROVIDER,
|
|
1564
|
-
model: REAL_OMP_MODEL,
|
|
1565
|
-
taskId: context.evidence.taskId,
|
|
1566
|
-
taskState: realTask.state,
|
|
1567
|
-
taskArtifactCount: Array.isArray(realTask.artifacts) ? realTask.artifacts.length : 0,
|
|
1568
|
-
evidenceSource: 'registered OMP task history, approval payload, task state, and route-specific recipe/ACK records',
|
|
1569
|
-
hostToolCallEvents: realToolEvents.calls.length + realToolEvents.completionCalls.length,
|
|
1570
|
-
hostToolResultEvents: realToolEvents.results.length,
|
|
1571
|
-
taskCompletionToolCallEvents: realToolEvents.completionCalls.length,
|
|
1572
|
-
taskToolEvents: realToolEvents.events.map(event => ({ toolName: event.toolName, phase: event.phase, isError: event.isError })),
|
|
1573
|
-
hostToolEventHistoryAvailable: realToolEvents.events.length > 0,
|
|
1574
|
-
approvedProposalValue: context.evidence.modelDecision?.selectedValue ?? null,
|
|
1575
|
-
approvedProposalCount: context.evidence.approvals.length,
|
|
1576
|
-
channelEvidence: {
|
|
1577
|
-
source: 'GET /api/workshop/channels/:id/messages',
|
|
1578
|
-
taskMessageCount: taskMessages.length,
|
|
1579
|
-
agentMessageCount: taskMessages.filter(message => message.fromAgentId === context.agent.id).length,
|
|
1580
|
-
roles: [...new Set(taskMessages.map(message => safeText(message.role, 40)))],
|
|
1581
|
-
},
|
|
1582
|
-
usage,
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
else if (HARNESS_MODE === 'fixture') {
|
|
1586
|
-
const tracePath = fixtureTracePath(context.evidence.id)
|
|
1587
|
-
const deadline = Date.now() + 20_000
|
|
1588
|
-
while (Date.now() < deadline) {
|
|
1589
|
-
if (existsSync(tracePath)) {
|
|
1590
|
-
try {
|
|
1591
|
-
trace = JSON.parse(readFileSync(tracePath, 'utf8'))
|
|
1592
|
-
}
|
|
1593
|
-
catch { /* fixture is rewriting a small JSON trace */ }
|
|
1594
|
-
}
|
|
1595
|
-
if (trace?.hostToolResults?.length) break
|
|
1596
|
-
await delay(300)
|
|
1597
|
-
}
|
|
1598
|
-
if (!trace) throw new Error(`${context.evidence.id} deterministic fixture did not create its trace`)
|
|
1599
|
-
if (trace.hostToolCalls?.length !== 1 || trace.hostToolCalls[0]?.toolName !== 'recipe_trial' || trace.hostToolResults?.length !== 1) {
|
|
1600
|
-
throw new Error(`${context.evidence.id} fixture trace did not show exactly one recipe_trial host_tool_call/result`)
|
|
1601
|
-
}
|
|
1602
|
-
const toolResult = trace.hostToolResults[0].result
|
|
1603
|
-
toolText = String(toolResult?.content?.[0]?.text ?? '')
|
|
1604
|
-
toolName = trace.hostToolCalls[0].toolName
|
|
1605
|
-
toolIsError = Boolean(toolResult?.isError)
|
|
1606
|
-
if (toolIsError || !/全部设备证实|下发并全部设备证实/.test(toolText)) {
|
|
1607
|
-
throw new Error(`${context.evidence.id} recipe_trial did not return a fully verified device ACK`)
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
const readback = await app('POST', `/api/workshop/dcw/${encodeURIComponent(context.control.id)}/read`)
|
|
1612
|
-
requireSuccess(readback, `${context.evidence.id} DCW readback`)
|
|
1613
|
-
|
|
1614
|
-
const runData = await app('GET', `/api/workshop/dcw/runs/${encodeURIComponent(context.runId)}/data`)
|
|
1615
|
-
requireSuccess(runData, `${context.evidence.id} active run data`)
|
|
1616
|
-
const logs = await app('GET', `/api/workshop/ops-logs?scope=line&lineId=${encodeURIComponent(context.line.id)}&recipeId=${encodeURIComponent(context.recipe.id)}&limit=100`)
|
|
1617
|
-
requireSuccess(logs, `${context.evidence.id} recipe operation log`)
|
|
1618
|
-
const recipeRows = (logs.data?.logs ?? [])
|
|
1619
|
-
.filter(row => String(row.action).startsWith('recipe.'))
|
|
1620
|
-
.map((row) => {
|
|
1621
|
-
let detail = row.detail
|
|
1622
|
-
if (!detail || typeof detail !== 'object' || Array.isArray(detail)) {
|
|
1623
|
-
try {
|
|
1624
|
-
const parsed = JSON.parse(String(row.detailJson ?? '{}'))
|
|
1625
|
-
detail = parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}
|
|
1626
|
-
}
|
|
1627
|
-
catch { detail = {} }
|
|
1628
|
-
}
|
|
1629
|
-
return { ...row, detail }
|
|
1630
|
-
})
|
|
1631
|
-
const trialRows = recipeRows.filter(row => row.action === 'recipe.trial')
|
|
1632
|
-
const trialAckRows = recipeRows.filter(row => row.action === 'recipe.dispatch.ack' && row.detail?.trial === true)
|
|
1633
|
-
const trialRow = trialRows[0]
|
|
1634
|
-
const ackRow = trialAckRows[0]
|
|
1635
|
-
const trialRunId = String(ackRow?.detail?.runId ?? '')
|
|
1636
|
-
if (trialRows.length !== 1 || trialAckRows.length !== 1 || !trialRunId || String(trialRow?.detail?.runId ?? '') !== trialRunId) {
|
|
1637
|
-
throw new Error(`${context.evidence.id} recipe log did not contain exactly one matching recipe.trial and trial ACK pair`)
|
|
1638
|
-
}
|
|
1639
|
-
if (HARNESS_MODE === 'real-omp' && context.evidence.approvals.length !== 1) {
|
|
1640
|
-
throw new Error(`${context.evidence.id} expected exactly one approved real OMP proposal`)
|
|
1641
|
-
}
|
|
1642
|
-
const trialRunData = await app('GET', `/api/workshop/dcw/runs/${encodeURIComponent(trialRunId)}/data`)
|
|
1643
|
-
requireSuccess(trialRunData, `${context.evidence.id} trial run data`)
|
|
1644
|
-
const ack = ackRow.detail?.ackSummary ?? null
|
|
1645
|
-
if (!ack || ack.total !== 1 || ack.verified !== 1 || ack.failed !== 0 || ack.unverified !== 0) {
|
|
1646
|
-
throw new Error(`${context.evidence.id} logged trial ACK is not one-of-one verified`)
|
|
1647
|
-
}
|
|
1648
|
-
const returnedTrialRun = trialRunData.data?.run
|
|
1649
|
-
const trialResults = returnedTrialRun?.results
|
|
1650
|
-
if (returnedTrialRun?.id !== trialRunId || !Array.isArray(trialResults) || trialResults.length !== 1 || trialResults[0]?.verify?.verdict !== 'verified' || trialResults[0]?.ok !== true) {
|
|
1651
|
-
throw new Error(`${context.evidence.id} trial run data lacks an independently verified write result`)
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
|
-
const snapshotDelayStartedAt = new Date().toISOString()
|
|
1655
|
-
await delay(20_000)
|
|
1656
|
-
const probeStartedAt = new Date().toISOString()
|
|
1657
|
-
const probeResponse = await app('POST', `/api/workshop/daq/${encodeURIComponent(context.daq.id)}/test`)
|
|
1658
|
-
const probe = requireSuccess(probeResponse, `${context.evidence.id} DAQ driver probe`).test
|
|
1659
|
-
const sampleValue = Number(probe?.sampleValue)
|
|
1660
|
-
if (probe?.ok !== true || !Number.isFinite(sampleValue)) {
|
|
1661
|
-
throw new Error(`${context.evidence.id} DAQ driver probe did not return a finite simulator value`)
|
|
1662
|
-
}
|
|
1663
|
-
const probeCompletedAt = new Date().toISOString()
|
|
1664
|
-
const ingestAt = probeCompletedAt
|
|
1665
|
-
const ingest = requireSuccess(await app('POST', `/api/workshop/daq/${encodeURIComponent(context.daq.id)}/ingest`, {
|
|
1666
|
-
at: ingestAt,
|
|
1667
|
-
value: sampleValue,
|
|
1668
|
-
state: 'ok',
|
|
1669
|
-
}), `${context.evidence.id} DAQ snapshot ingest`)
|
|
1670
|
-
if (ingest?.accepted !== true || ingest.nodeId !== context.daq.id || ingest.lineId !== context.line.id) {
|
|
1671
|
-
throw new Error(`${context.evidence.id} DAQ snapshot ingest was not accepted for the expected node and line`)
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
const persistedAt = String(ingest.at ?? ingestAt)
|
|
1675
|
-
const persistedAtMs = Date.parse(persistedAt)
|
|
1676
|
-
if (!Number.isFinite(persistedAtMs)) throw new Error(`${context.evidence.id} DAQ snapshot ingest returned an invalid sample timestamp`)
|
|
1677
|
-
const fromMs = persistedAtMs
|
|
1678
|
-
const toMs = persistedAtMs + 1
|
|
1679
|
-
// Let the in-process queue and SQLite batch flush settle before a fixed-window query;
|
|
1680
|
-
// retries outlast the short query-cache TTL if the first lookup is still empty.
|
|
1681
|
-
await delay(800)
|
|
1682
|
-
const queryDeadline = Date.now() + 12_000
|
|
1683
|
-
let taggedQuery
|
|
1684
|
-
let taggedSeries
|
|
1685
|
-
let snapshotBucketAt
|
|
1686
|
-
while (Date.now() < queryDeadline) {
|
|
1687
|
-
const candidate = await app('GET', `/api/workshop/daq/query?line_id=${encodeURIComponent(context.line.id)}&node_ids=${encodeURIComponent(context.daq.id)}&run_id=${encodeURIComponent(context.runId)}&from=${fromMs}&to=${toMs}&bucket_ms=1000`)
|
|
1688
|
-
if (candidate.status === 200) {
|
|
1689
|
-
taggedQuery = candidate
|
|
1690
|
-
taggedSeries = candidate.data?.series?.find(series => series.nodeId === context.daq.id)
|
|
1691
|
-
const bucketMs = Number(candidate.data?.window?.bucketMs) || 1_000
|
|
1692
|
-
snapshotBucketAt = Math.floor(persistedAtMs / bucketMs) * bucketMs
|
|
1693
|
-
const matchingPoint = taggedSeries?.points?.find(point => Number(point.at) === snapshotBucketAt && Math.abs(Number(point.v) - sampleValue) <= 0.01)
|
|
1694
|
-
if (matchingPoint && candidate.data?.activeRun?.runId === context.runId) break
|
|
1695
|
-
}
|
|
1696
|
-
await delay(300)
|
|
1697
|
-
}
|
|
1698
|
-
if (!taggedQuery || !taggedSeries?.points?.length || taggedQuery.data?.activeRun?.runId !== context.runId) {
|
|
1699
|
-
throw new Error(`${context.evidence.id} platform DAQ query returned no snapshot tagged to the active run`)
|
|
1700
|
-
}
|
|
1701
|
-
const matchingProbePoint = taggedSeries.points.find(point => Number(point.at) === snapshotBucketAt && Math.abs(Number(point.v) - sampleValue) <= 0.01)
|
|
1702
|
-
if (!matchingProbePoint) {
|
|
1703
|
-
throw new Error(`${context.evidence.id} run-tagged DAQ data did not contain the driver-probe snapshot value`)
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
if (HARNESS_MODE === 'real-omp') {
|
|
1707
|
-
const finalTask = await readRealOmpTask(context)
|
|
1708
|
-
context.evidence.hostToolExecution = {
|
|
1709
|
-
provenance: 'registered OMP model proposal → protected synthetic approval → one recipe.trial and one verified DCW receipt',
|
|
1710
|
-
hostToolEventHistoryAvailable: realToolEvents.events.length > 0,
|
|
1711
|
-
taskStateAfterObservation: finalTask.state,
|
|
1712
|
-
taskCompleted: finalTask.state === 'COMPLETED',
|
|
1713
|
-
approvedProposalCount: context.evidence.approvals.length,
|
|
1714
|
-
recipeTrialCount: trialRows.length,
|
|
1715
|
-
recipeTrialAckCount: trialAckRows.length,
|
|
1716
|
-
toolName: 'recipe_trial',
|
|
1717
|
-
resultReceived: ack?.verified === 1 && ack?.failed === 0,
|
|
1718
|
-
}
|
|
1719
|
-
context.evidence.modelExecution.taskStateAfterObservation = finalTask.state
|
|
1720
|
-
context.evidence.modelExecution.taskCompleted = finalTask.state === 'COMPLETED'
|
|
1721
|
-
}
|
|
1722
|
-
else {
|
|
1723
|
-
context.evidence.fixtureTrace = {
|
|
1724
|
-
fixture: HARNESS_MODE === 'pi-local-fixture' ? 'registered Pi CLI with deterministic loopback model fixture' : trace.fixture,
|
|
1725
|
-
decisionSource: HARNESS_MODE === 'pi-local-fixture' ? 'Pi CLI tool call through the AgentWorkShop host-tool bridge' : trace.decisionSource,
|
|
1726
|
-
hostToolCallCount: HARNESS_MODE === 'pi-local-fixture' ? 1 : trace.hostToolCalls.length,
|
|
1727
|
-
toolName,
|
|
1728
|
-
resultReceived: HARNESS_MODE === 'pi-local-fixture' ? Boolean(context.evidence.modelExecution?.recipeTrialResultReturnedToPi) : trace.hostToolResults.length === 1,
|
|
1729
|
-
toolResultText: safeText(toolText, 1200),
|
|
1730
|
-
toolIsError,
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
context.evidence.trial = {
|
|
1734
|
-
taskId: context.evidence.taskId,
|
|
1735
|
-
runId: trialRunId,
|
|
1736
|
-
toolName,
|
|
1737
|
-
approvalId: context.evidence.approvals[0].id,
|
|
1738
|
-
ackSummary: ack,
|
|
1739
|
-
resultCount: trialResults.length,
|
|
1740
|
-
resultRows: trialResults,
|
|
1741
|
-
}
|
|
1742
|
-
context.evidence.readback = {
|
|
1743
|
-
expectedCandidate: context.evidence.simulator.candidate,
|
|
1744
|
-
response: readback.data?.outcome ?? readback.data?.read ?? readback.data,
|
|
1745
|
-
resultMatchesCandidate: (() => {
|
|
1746
|
-
const details = readback.data?.outcome ?? readback.data?.read ?? readback.data ?? {}
|
|
1747
|
-
const observed = Number(details.value ?? details.data?.value ?? details.result?.value)
|
|
1748
|
-
return Number.isFinite(observed) && Math.abs(observed - context.evidence.simulator.candidate) <= 0.01
|
|
1749
|
-
})(),
|
|
1750
|
-
}
|
|
1751
|
-
context.evidence.daq = {
|
|
1752
|
-
taskId: context.evidence.taskId,
|
|
1753
|
-
nodeId: context.daq.id,
|
|
1754
|
-
method: 'single driver-probe/ingest snapshot',
|
|
1755
|
-
storageBackend: 'isolated AW_HOME SQLite time-series fallback',
|
|
1756
|
-
postTrialDelaySeconds: 20,
|
|
1757
|
-
snapshotDelayStartedAt,
|
|
1758
|
-
sampleCount: taggedSeries.points.length,
|
|
1759
|
-
runTags: [context.runId],
|
|
1760
|
-
expectedActiveRunId: context.runId,
|
|
1761
|
-
probe: {
|
|
1762
|
-
driver: context.daq.driver,
|
|
1763
|
-
startedAt: probeStartedAt,
|
|
1764
|
-
completedAt: probeCompletedAt,
|
|
1765
|
-
sampleValue,
|
|
1766
|
-
latencyMs: Number.isFinite(Number(probe.latencyMs)) ? Number(probe.latencyMs) : null,
|
|
1767
|
-
},
|
|
1768
|
-
ingest: {
|
|
1769
|
-
accepted: ingest.accepted,
|
|
1770
|
-
at: persistedAt,
|
|
1771
|
-
value: sampleValue,
|
|
1772
|
-
state: 'ok',
|
|
1773
|
-
},
|
|
1774
|
-
taggedQuery: {
|
|
1775
|
-
requestedRunId: context.runId,
|
|
1776
|
-
returnedRunId: taggedQuery.data?.activeRun?.runId ?? null,
|
|
1777
|
-
seriesPointCount: taggedSeries.points.length,
|
|
1778
|
-
probeValueMatched: true,
|
|
1779
|
-
snapshotBucketAt: new Date(snapshotBucketAt).toISOString(),
|
|
1780
|
-
matchingProbePoint,
|
|
1781
|
-
series: taggedSeries.points.slice(-5),
|
|
1782
|
-
},
|
|
1783
|
-
activeRunDataKeys: Object.keys(runData.data ?? {}),
|
|
1784
|
-
}
|
|
1785
|
-
context.evidence.recipeLog = {
|
|
1786
|
-
taskId: context.evidence.taskId,
|
|
1787
|
-
query: 'ops-logs filtered by lineId and recipeId (recipe_log-equivalent audit view)',
|
|
1788
|
-
rowCount: recipeRows.length,
|
|
1789
|
-
trialAction: trialRow.action,
|
|
1790
|
-
trialSummary: safeText(trialRow.summary, 600),
|
|
1791
|
-
ackAction: ackRow.action,
|
|
1792
|
-
ackSummary: safeText(ackRow.summary, 600),
|
|
1793
|
-
trialRunDataKeys: Object.keys(trialRunData.data ?? {}),
|
|
1794
|
-
}
|
|
1795
|
-
context.evidence.status = 'verified'
|
|
1796
|
-
context.evidence.traceability = {
|
|
1797
|
-
taskId: context.evidence.taskId,
|
|
1798
|
-
approvalId: context.evidence.approvals[0].id,
|
|
1799
|
-
recipeId: context.recipe.id,
|
|
1800
|
-
trialRunId,
|
|
1801
|
-
activeRunId: context.runId,
|
|
1802
|
-
daqNodeId: context.daq.id,
|
|
1803
|
-
sampleAt: persistedAt,
|
|
1804
|
-
taskState: context.evidence.modelExecution?.taskState ?? null,
|
|
1805
|
-
taskCompleted: context.evidence.modelExecution?.taskCompleted === true,
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
async function runScene(scene) {
|
|
1810
|
-
const simDetails = await simulatorScene(scene)
|
|
1811
|
-
const context = await setupScene(scene, { ...simDetails, candidate: scene.candidate })
|
|
1812
|
-
context.evidence.simulator.candidate = scene.candidate
|
|
1813
|
-
context.evidence.simulator.baseline = scene.baseline
|
|
1814
|
-
piFixtureTarget = {
|
|
1815
|
-
scene: context.evidence.id,
|
|
1816
|
-
recipeId: context.recipe.id,
|
|
1817
|
-
nodeId: context.control.id,
|
|
1818
|
-
value: scene.candidate,
|
|
1819
|
-
}
|
|
1820
|
-
await submitFixtureTask(context)
|
|
1821
|
-
await approvePendingTrial(context)
|
|
1822
|
-
await collectSceneEvidence(context)
|
|
1823
|
-
check(`${scene.id}-pi-task-completed`, context.evidence.modelExecution?.taskCompleted === true && context.evidence.modelExecution?.taskAssigneeMatchesRegisteredPi === true, {
|
|
1824
|
-
taskId: context.evidence.taskId,
|
|
1825
|
-
state: context.evidence.modelExecution?.taskState ?? null,
|
|
1826
|
-
assigneeMatchesRegisteredPi: context.evidence.modelExecution?.taskAssigneeMatchesRegisteredPi === true,
|
|
1827
|
-
})
|
|
1828
|
-
const linked = context.evidence.traceability?.taskId === context.evidence.taskId
|
|
1829
|
-
&& context.evidence.approvals[0]?.taskId === context.evidence.taskId
|
|
1830
|
-
&& context.evidence.trial?.taskId === context.evidence.taskId
|
|
1831
|
-
&& context.evidence.daq?.taskId === context.evidence.taskId
|
|
1832
|
-
&& context.evidence.traceability?.approvalId === context.evidence.approvals[0]?.id
|
|
1833
|
-
&& context.evidence.traceability?.trialRunId === context.evidence.trial?.runId
|
|
1834
|
-
&& context.evidence.traceability?.activeRunId === context.evidence.daq?.expectedActiveRunId
|
|
1835
|
-
&& context.evidence.daq?.taggedQuery?.returnedRunId === context.evidence.daq?.expectedActiveRunId
|
|
1836
|
-
&& Boolean(context.evidence.traceability?.sampleAt)
|
|
1837
|
-
check(`${scene.id}-task-approval-receipt-sample-linked`, linked, context.evidence.traceability)
|
|
1838
|
-
piFixtureTarget = null
|
|
1839
|
-
const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
|
|
1840
|
-
requireSuccess(stopped, `${scene.id} line stop`)
|
|
1841
|
-
context.evidence.activeRun.endedAt = stopped.data?.run?.endedAt ?? null
|
|
1842
|
-
check(`${scene.id}-host-dispatch-one-call`, context.evidence.fixtureTrace.hostToolCallCount === 1, { tool: context.evidence.fixtureTrace.toolName })
|
|
1843
|
-
check(`${scene.id}-ack-verified`, context.evidence.trial.ackSummary.verified === 1 && context.evidence.trial.ackSummary.failed === 0, context.evidence.trial.ackSummary)
|
|
1844
|
-
check(`${scene.id}-readback-matches`, context.evidence.readback.resultMatchesCandidate, context.evidence.readback)
|
|
1845
|
-
check(`${scene.id}-run-tagged-daq-probe-ingest-snapshot`, context.evidence.daq.taggedQuery.seriesPointCount >= 1 && context.evidence.daq.taggedQuery.probeValueMatched, {
|
|
1846
|
-
method: context.evidence.daq.method,
|
|
1847
|
-
value: context.evidence.daq.probe.sampleValue,
|
|
1848
|
-
runId: context.evidence.daq.expectedActiveRunId,
|
|
1849
|
-
matchingPoint: context.evidence.daq.taggedQuery.matchingProbePoint,
|
|
1850
|
-
})
|
|
1851
|
-
check(`${scene.id}-recipe-log`, context.evidence.recipeLog.rowCount >= 2, { trialAction: context.evidence.recipeLog.trialAction, ackAction: context.evidence.recipeLog.ackAction })
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
async function recoverFailedRealOmpTrial(context, outcome) {
|
|
1855
|
-
const recovery = []
|
|
1856
|
-
if (context?.evidence?.taskId) {
|
|
1857
|
-
try {
|
|
1858
|
-
const task = await readRealOmpTask(context)
|
|
1859
|
-
if (!['COMPLETED', 'FAILED', 'CANCELED'].includes(task.state)) {
|
|
1860
|
-
const canceled = await app('POST', `/api/workshop/tasks/${encodeURIComponent(context.evidence.taskId)}/cancel`)
|
|
1861
|
-
recovery.push({ action: 'cancel-nonterminal-task', status: canceled.status === 200 ? 'completed' : `http-${canceled.status}` })
|
|
1862
|
-
}
|
|
1863
|
-
else recovery.push({ action: 'cancel-nonterminal-task', status: 'not-needed', taskState: task.state })
|
|
1864
|
-
}
|
|
1865
|
-
catch (error) { recovery.push({ action: 'cancel-nonterminal-task', status: 'failed', error: compactError(error) }) }
|
|
1866
|
-
}
|
|
1867
|
-
if (context?.channel?.channelId && context?.agent?.id) {
|
|
1868
|
-
try {
|
|
1869
|
-
const stopped = await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/agents/${encodeURIComponent(context.agent.id)}/stop`)
|
|
1870
|
-
recovery.push({ action: 'stop-agent-runtime', status: stopped.status === 200 ? 'completed' : `http-${stopped.status}` })
|
|
1871
|
-
}
|
|
1872
|
-
catch (error) { recovery.push({ action: 'stop-agent-runtime', status: 'failed', error: compactError(error) }) }
|
|
1873
|
-
try {
|
|
1874
|
-
const pendingResult = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
|
|
1875
|
-
const pending = pendingResult.status === 200
|
|
1876
|
-
? (pendingResult.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.status === 'pending')
|
|
1877
|
-
: []
|
|
1878
|
-
for (const approval of pending) {
|
|
1879
|
-
const denied = await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(approval.id)}/decide`, {
|
|
1880
|
-
approved: false,
|
|
1881
|
-
comment: 'Denied during bounded R20 failure cleanup.',
|
|
1882
|
-
})
|
|
1883
|
-
recovery.push({ action: 'deny-pending-agent-approval', approvalId: approval.id, status: denied.status === 200 ? 'completed' : `http-${denied.status}` })
|
|
1884
|
-
}
|
|
1885
|
-
if (pendingResult.status !== 200) recovery.push({ action: 'deny-pending-agent-approval', status: `list-http-${pendingResult.status}` })
|
|
1886
|
-
else if (pending.length === 0) recovery.push({ action: 'deny-pending-agent-approval', status: 'not-needed' })
|
|
1887
|
-
}
|
|
1888
|
-
catch (error) { recovery.push({ action: 'deny-pending-agent-approval', status: 'failed', error: compactError(error) }) }
|
|
1889
|
-
}
|
|
1890
|
-
if (context?.line?.id) {
|
|
1891
|
-
try {
|
|
1892
|
-
const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
|
|
1893
|
-
recovery.push({ action: 'stop-line', status: stopped.status === 200 ? 'completed' : `http-${stopped.status}` })
|
|
1894
|
-
}
|
|
1895
|
-
catch (error) { recovery.push({ action: 'stop-line', status: 'failed', error: compactError(error) }) }
|
|
1896
|
-
}
|
|
1897
|
-
outcome.recovery = recovery
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
async function runRealOmpScene(baseScene) {
|
|
1901
|
-
currentScene = baseScene.id
|
|
1902
|
-
let simDetails
|
|
1903
|
-
try {
|
|
1904
|
-
currentStage = `${baseScene.id}:simulator-setup-once`
|
|
1905
|
-
simDetails = await simulatorScene(baseScene)
|
|
1906
|
-
if (!Array.isArray(baseScene.candidates) || baseScene.candidates.length !== REAL_OMP_TRIALS_PER_SCENE
|
|
1907
|
-
|| baseScene.candidates.some(candidate => !Number.isFinite(candidate)
|
|
1908
|
-
|| candidate < Number(simDetails.mv.min)
|
|
1909
|
-
|| candidate > Number(simDetails.mv.max)
|
|
1910
|
-
|| Math.abs(candidate - baseScene.baseline) > 30)) {
|
|
1911
|
-
throw new Error(`${baseScene.id} real OMP candidates violate the configured count, process range, or 30-unit recipe step limit`)
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
catch (error) {
|
|
1915
|
-
for (let repetition = 1; repetition <= REAL_OMP_TRIALS_PER_SCENE; repetition++) {
|
|
1916
|
-
const outcome = {
|
|
1917
|
-
id: `${baseScene.id}-r${repetition}`,
|
|
1918
|
-
scene: baseScene.id,
|
|
1919
|
-
repetition,
|
|
1920
|
-
provider: REAL_OMP_PROVIDER,
|
|
1921
|
-
model: REAL_OMP_MODEL,
|
|
1922
|
-
candidate: baseScene.candidates[repetition - 1],
|
|
1923
|
-
usage: { source: 'not available because simulator setup failed', context: null, requestInputTokens: null, requestOutputTokens: null, costUsd: null, costAvailable: false },
|
|
1924
|
-
costUsd: null,
|
|
1925
|
-
status: 'failed',
|
|
1926
|
-
failure: compactError(error),
|
|
1927
|
-
}
|
|
1928
|
-
evidence.experiment.runOutcomes.push(outcome)
|
|
1929
|
-
}
|
|
1930
|
-
return
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
for (let repetition = 1; repetition <= REAL_OMP_TRIALS_PER_SCENE; repetition++) {
|
|
1934
|
-
const scene = { ...baseScene, id: `${baseScene.id}-r${repetition}` }
|
|
1935
|
-
const outcome = {
|
|
1936
|
-
id: scene.id,
|
|
1937
|
-
scene: baseScene.id,
|
|
1938
|
-
repetition,
|
|
1939
|
-
provider: REAL_OMP_PROVIDER,
|
|
1940
|
-
model: REAL_OMP_MODEL,
|
|
1941
|
-
candidate: null,
|
|
1942
|
-
candidateChoices: [...baseScene.candidates],
|
|
1943
|
-
usage: { source: 'not yet available', context: null, requestInputTokens: null, requestOutputTokens: null, costUsd: null, costAvailable: false },
|
|
1944
|
-
costUsd: null,
|
|
1945
|
-
status: 'running',
|
|
1946
|
-
startedAt: new Date().toISOString(),
|
|
1947
|
-
}
|
|
1948
|
-
evidence.experiment.runOutcomes.push(outcome)
|
|
1949
|
-
let context
|
|
1950
|
-
try {
|
|
1951
|
-
currentScene = scene.id
|
|
1952
|
-
const runSimDetails = { ...simDetails, candidateChoices: [...baseScene.candidates] }
|
|
1953
|
-
context = await setupScene(scene, runSimDetails)
|
|
1954
|
-
context.evidence.simulator.baseline = scene.baseline
|
|
1955
|
-
outcome.entities = context.evidence.entities
|
|
1956
|
-
outcome.runId = context.runId
|
|
1957
|
-
await submitRealOmpTask(context)
|
|
1958
|
-
outcome.taskId = context.evidence.taskId
|
|
1959
|
-
await approveRealOmpTrial(context)
|
|
1960
|
-
outcome.candidate = context.evidence.simulator.candidate
|
|
1961
|
-
outcome.modelDecision = context.evidence.modelDecision
|
|
1962
|
-
await collectSceneEvidence(context)
|
|
1963
|
-
const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
|
|
1964
|
-
requireSuccess(stopped, `${scene.id} line stop`)
|
|
1965
|
-
context.evidence.activeRun.endedAt = stopped.data?.run?.endedAt ?? null
|
|
1966
|
-
const finalTask = await readRealOmpTask(context)
|
|
1967
|
-
context.evidence.hostToolExecution.taskStateAfterObservation = finalTask.state
|
|
1968
|
-
context.evidence.hostToolExecution.taskCompleted = finalTask.state === 'COMPLETED'
|
|
1969
|
-
context.evidence.modelExecution.taskStateAfterObservation = finalTask.state
|
|
1970
|
-
context.evidence.modelExecution.taskCompleted = finalTask.state === 'COMPLETED'
|
|
1971
|
-
check(`${scene.id}-real-omp-approved-model-proposal`, context.evidence.modelExecution.approvedProposalCount === 1 && context.evidence.modelExecution.approvedProposalValue === context.evidence.simulator.candidate, {
|
|
1972
|
-
provider: REAL_OMP_PROVIDER,
|
|
1973
|
-
model: REAL_OMP_MODEL,
|
|
1974
|
-
selectedValue: context.evidence.modelExecution.approvedProposalValue,
|
|
1975
|
-
toolEventHistoryAvailable: context.evidence.modelExecution.hostToolEventHistoryAvailable,
|
|
1976
|
-
})
|
|
1977
|
-
check(`${scene.id}-real-omp-one-recipe-trial-ledger`, context.evidence.hostToolExecution.recipeTrialCount === 1 && context.evidence.hostToolExecution.recipeTrialAckCount === 1, {
|
|
1978
|
-
recipeTrialCount: context.evidence.hostToolExecution.recipeTrialCount,
|
|
1979
|
-
recipeTrialAckCount: context.evidence.hostToolExecution.recipeTrialAckCount,
|
|
1980
|
-
})
|
|
1981
|
-
check(`${scene.id}-ack-verified`, context.evidence.trial.ackSummary.verified === 1 && context.evidence.trial.ackSummary.failed === 0, context.evidence.trial.ackSummary)
|
|
1982
|
-
check(`${scene.id}-readback-matches`, context.evidence.readback.resultMatchesCandidate, context.evidence.readback)
|
|
1983
|
-
check(`${scene.id}-run-tagged-daq-probe-ingest-snapshot`, context.evidence.daq.taggedQuery.seriesPointCount >= 1 && context.evidence.daq.taggedQuery.probeValueMatched, {
|
|
1984
|
-
method: context.evidence.daq.method,
|
|
1985
|
-
value: context.evidence.daq.probe.sampleValue,
|
|
1986
|
-
runId: context.evidence.daq.expectedActiveRunId,
|
|
1987
|
-
matchingPoint: context.evidence.daq.taggedQuery.matchingProbePoint,
|
|
1988
|
-
})
|
|
1989
|
-
check(`${scene.id}-recipe-log`, context.evidence.recipeLog.rowCount >= 2, { trialAction: context.evidence.recipeLog.trialAction, ackAction: context.evidence.recipeLog.ackAction })
|
|
1990
|
-
check(`${scene.id}-real-omp-task-completed`, context.evidence.hostToolExecution.taskCompleted, {
|
|
1991
|
-
taskState: context.evidence.hostToolExecution.taskStateAfterObservation,
|
|
1992
|
-
})
|
|
1993
|
-
context.evidence.status = 'verified'
|
|
1994
|
-
outcome.status = context.evidence.hostToolExecution.taskCompleted ? 'verified' : 'verified-operation-task-incomplete'
|
|
1995
|
-
outcome.finishedAt = new Date().toISOString()
|
|
1996
|
-
outcome.trialRunId = context.evidence.trial.runId
|
|
1997
|
-
outcome.taskState = context.evidence.hostToolExecution.taskStateAfterObservation
|
|
1998
|
-
outcome.usage = context.evidence.modelExecution.usage
|
|
1999
|
-
outcome.costUsd = null
|
|
2000
|
-
outcome.evidenceSceneId = context.evidence.id
|
|
2001
|
-
}
|
|
2002
|
-
catch (error) {
|
|
2003
|
-
context && (context.evidence.status = 'failed')
|
|
2004
|
-
if (context) context.evidence.failure = compactError(error)
|
|
2005
|
-
outcome.status = 'failed'
|
|
2006
|
-
outcome.failure = compactError(error)
|
|
2007
|
-
outcome.finishedAt = new Date().toISOString()
|
|
2008
|
-
if (context) {
|
|
2009
|
-
outcome.usage = await captureRealOmpUsage(context)
|
|
2010
|
-
await recoverFailedRealOmpTrial(context, outcome)
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
|
|
2016
|
-
async function startApplication() {
|
|
2017
|
-
currentStage = 'application-startup'
|
|
2018
|
-
await assertFreeLoopback(OFFLINE_APP_MQTT_QUEUE_PORT, 'offline-app-mqtt-queue-probe-before-startup')
|
|
2019
|
-
noteIsolation('offline-app-mqtt-queue-port-free-immediately-before-startup', true, {
|
|
2020
|
-
port: OFFLINE_APP_MQTT_QUEUE_PORT,
|
|
2021
|
-
host: '127.0.0.1',
|
|
2022
|
-
})
|
|
2023
|
-
appProcess = spawnLogged(process.execPath, [NUXT_CLI, 'dev', '--host', '127.0.0.1', '--port', String(AW_PORT), '--dotenv', EMPTY_DOTENV], {
|
|
2024
|
-
cwd: REPO,
|
|
2025
|
-
env: cleanChildEnv(),
|
|
2026
|
-
logFd: APP_LOG_FD,
|
|
2027
|
-
label: 'agentworkshop',
|
|
2028
|
-
})
|
|
2029
|
-
for (let i = 0; i < 90; i++) {
|
|
2030
|
-
if (appProcess.exitCode !== null) throw new Error(`AgentWorkShop startup exited (code ${appProcess.exitCode})`)
|
|
2031
|
-
try {
|
|
2032
|
-
const response = await app('GET', '/api/health', undefined, { token: undefined, timeoutMs: 2_000 })
|
|
2033
|
-
if (response.status === 200 && response.data?.status === 'ok' && response.data?.workshop === 'ready') {
|
|
2034
|
-
if (response.data?.version !== '0.8.0') throw new Error(`server reported unexpected version ${safeText(response.data?.version, 80)}`)
|
|
2035
|
-
noteIsolation('application-loopback-ready', true, { version: response.data.version, workshop: response.data.workshop, port: AW_PORT, host: '127.0.0.1' })
|
|
2036
|
-
return response.data
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
catch (error) {
|
|
2040
|
-
if (error?.message?.startsWith('server reported unexpected version')) throw error
|
|
2041
|
-
}
|
|
2042
|
-
await delay(500)
|
|
2043
|
-
}
|
|
2044
|
-
throw new Error('isolated AgentWorkShop startup timed out or workshop manager did not become ready')
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
async function main() {
|
|
2048
|
-
mkdirSync(join(REPO, '.omc'), { recursive: true })
|
|
2049
|
-
if (VERSION !== '0.8.0') throw new Error(`expected current package version 0.8.0; found ${VERSION}`)
|
|
2050
|
-
await preflight()
|
|
2051
|
-
prepareIsolatedHome()
|
|
2052
|
-
if (HARNESS_MODE === 'pi-local-fixture') {
|
|
2053
|
-
await startPiModelFixture()
|
|
2054
|
-
noteIsolation('registered-pi-fixture-configured', true, {
|
|
2055
|
-
command: PI_COMMAND,
|
|
2056
|
-
provider: PI_PROVIDER,
|
|
2057
|
-
model: PI_MODEL,
|
|
2058
|
-
localModelApi: `127.0.0.1:${MODEL_API_PORT}`,
|
|
2059
|
-
noExternalProvider: true,
|
|
2060
|
-
})
|
|
2061
|
-
}
|
|
2062
|
-
else if (HARNESS_MODE === 'fixture') {
|
|
2063
|
-
currentStage = 'compile-local-omp-fixture-shim'
|
|
2064
|
-
wrapperPath = buildHarnessShim()
|
|
2065
|
-
noteIsolation('registered-omp-fixture-launcher-ready', true, { platform: process.platform, wrapper: 'local process shim; fixture is deterministic' })
|
|
2066
|
-
}
|
|
2067
|
-
else {
|
|
2068
|
-
noteIsolation('registered-omp-real-provider-model-declared', true, {
|
|
2069
|
-
command: 'omp from allowlisted PATH',
|
|
2070
|
-
provider: REAL_OMP_PROVIDER,
|
|
2071
|
-
model: REAL_OMP_MODEL,
|
|
2072
|
-
cwd: 'fresh isolated AW_HOME',
|
|
2073
|
-
authSource: 'local OMP auth store; value is not inspected or added to evidence',
|
|
2074
|
-
discoveryDisabled: ['extensions', 'skills', 'rules'],
|
|
2075
|
-
credentialValuesExposedToRunnerOrEvidence: false,
|
|
2076
|
-
})
|
|
2077
|
-
}
|
|
2078
|
-
currentStage = 'simulator-startup'
|
|
2079
|
-
await bootSimulator()
|
|
2080
|
-
const health = await startApplication()
|
|
2081
|
-
evidence.experiment.server = { version: health.version, mode: health.mode, workshop: health.workshop, uptimeMsAtReady: health.uptimeMs }
|
|
2082
|
-
evidence.experiment.sourceIdentity = captureSourceIdentity()
|
|
2083
|
-
const admin = await registerAdmin()
|
|
2084
|
-
evidence.experiment.syntheticAdmin = admin
|
|
2085
|
-
await assertPluginIsolation()
|
|
2086
|
-
await verifyRagBridgeOutboundDisabled()
|
|
2087
|
-
const daqStatus = requireSuccess(await app('GET', '/api/workshop/daq', undefined, { timeoutMs: 45_000 }), 'isolated DAQ backend status')
|
|
2088
|
-
const settings = requireSuccess(await app('GET', '/api/system/settings'), 'effective runtime settings snapshot')
|
|
2089
|
-
const effectiveMqttHost = settings.effective?.['daq.mqtt.host']
|
|
2090
|
-
const effectiveMqttPort = Number(settings.effective?.['daq.mqtt.port'])
|
|
2091
|
-
const effectiveMqttPortSource = settings.sources?.['daq.mqtt.port']
|
|
2092
|
-
const effectiveInfrastructurePolicy = settings.effective?.['daq.startInfrastructure']
|
|
2093
|
-
const effectiveInfrastructurePolicySource = settings.sources?.['daq.startInfrastructure']
|
|
2094
|
-
const runtimeTargetMatches = effectiveMqttHost === '127.0.0.1'
|
|
2095
|
-
&& effectiveMqttPort === OFFLINE_APP_MQTT_QUEUE_PORT
|
|
2096
|
-
&& effectiveMqttPortSource === 'runtime'
|
|
2097
|
-
&& effectiveInfrastructurePolicy === 'never'
|
|
2098
|
-
&& effectiveInfrastructurePolicySource === 'runtime'
|
|
2099
|
-
check('runtime-settings-target-offline-loopback-queue', runtimeTargetMatches, {
|
|
2100
|
-
mqttHost: effectiveMqttHost ?? null,
|
|
2101
|
-
mqttPort: effectiveMqttPort,
|
|
2102
|
-
mqttPortSource: effectiveMqttPortSource ?? null,
|
|
2103
|
-
infrastructurePolicy: effectiveInfrastructurePolicy ?? null,
|
|
2104
|
-
infrastructurePolicySource: effectiveInfrastructurePolicySource ?? null,
|
|
2105
|
-
})
|
|
2106
|
-
check('isolated-inproc-queue-and-sqlite-tsdb', runtimeTargetMatches && daqStatus.meta?.queue === 'inproc' && daqStatus.meta?.tsdb === 'sqlite-emulated', {
|
|
2107
|
-
queue: daqStatus.meta?.queue ?? null,
|
|
2108
|
-
tsdb: daqStatus.meta?.tsdb ?? null,
|
|
2109
|
-
effectiveMqttHost,
|
|
2110
|
-
effectiveMqttPort,
|
|
2111
|
-
effectiveMqttPortSource,
|
|
2112
|
-
})
|
|
2113
|
-
noteIsolation('application-message-path-is-inproc', runtimeTargetMatches && daqStatus.meta?.queue === 'inproc', {
|
|
2114
|
-
queue: daqStatus.meta?.queue ?? null,
|
|
2115
|
-
effectiveMqttHost,
|
|
2116
|
-
effectiveMqttPort,
|
|
2117
|
-
effectiveMqttPortSource: effectiveMqttPortSource ?? null,
|
|
2118
|
-
simulatorMqttBrokerRemainsLoopback: `127.0.0.1:${MQTT_PORT}`,
|
|
2119
|
-
})
|
|
2120
|
-
evidence.isolation.result = 'passed'
|
|
2121
|
-
noteIsolation('application-env-and-dotenv-isolation', true, {
|
|
2122
|
-
launch: 'direct Nuxt CLI; dev-guard .env preload bypassed',
|
|
2123
|
-
dotenvFile: EMPTY_DOTENV,
|
|
2124
|
-
childEnvironmentAllowlisted: true,
|
|
2125
|
-
storageEndpointsRestrictedToFreeLoopbackPorts: true,
|
|
2126
|
-
})
|
|
2127
|
-
|
|
2128
|
-
const scenes = [
|
|
2129
|
-
{
|
|
2130
|
-
id: 'cast-film', preset: 'cast-film-physics', sourceDevice: 'dev-extruder-opcua',
|
|
2131
|
-
mvSignal: 'ScrewSpeedSP', cvSignal: 'thick', baseline: 120, fixtureCandidate: 125,
|
|
2132
|
-
processDescription: 'cast-film extrusion; screw speed affects measured film thickness',
|
|
2133
|
-
targetMin: 48, targetMax: 52,
|
|
2134
|
-
candidates: [125, 130, 135],
|
|
2135
|
-
},
|
|
2136
|
-
{
|
|
2137
|
-
id: 'annealing', preset: 'anneal-line', sourceDevice: 'anneal-heating-mbtcp',
|
|
2138
|
-
mvSignal: '均热区3炉温SP', cvSignal: 'StripTemp', baseline: 730, fixtureCandidate: 735,
|
|
2139
|
-
processDescription: 'continuous annealing; zone-3 furnace setpoint affects measured strip temperature',
|
|
2140
|
-
targetMin: 700, targetMax: 760,
|
|
2141
|
-
candidates: [735, 740, 745],
|
|
2142
|
-
},
|
|
2143
|
-
]
|
|
2144
|
-
if (HARNESS_MODE === 'real-omp') {
|
|
2145
|
-
check('real-omp-six-unique-trials-planned', scenes.length * REAL_OMP_TRIALS_PER_SCENE === 6 && new Set(scenes.flatMap(scene => Array.from({ length: REAL_OMP_TRIALS_PER_SCENE }, (_, index) => `${scene.id}-r${index + 1}`))).size === 6, {
|
|
2146
|
-
scenes: scenes.map(scene => scene.id),
|
|
2147
|
-
repetitionsPerScene: REAL_OMP_TRIALS_PER_SCENE,
|
|
2148
|
-
})
|
|
2149
|
-
for (const scene of scenes) await runRealOmpScene(scene)
|
|
2150
|
-
const failedRuns = evidence.experiment.runOutcomes.filter(outcome => outcome.status !== 'verified')
|
|
2151
|
-
evidence.status = failedRuns.length === 0 ? 'passed' : 'failed'
|
|
2152
|
-
if (failedRuns.length) {
|
|
2153
|
-
evidence.failure = {
|
|
2154
|
-
stage: 'real-omp-trial-set',
|
|
2155
|
-
name: 'RealOmpTrialSetError',
|
|
2156
|
-
message: `${failedRuns.length} of ${evidence.experiment.runOutcomes.length} bounded real OMP trials failed`,
|
|
2157
|
-
failedRunIds: failedRuns.map(outcome => outcome.id),
|
|
2158
|
-
}
|
|
2159
|
-
evidence.isolation.result = 'incomplete'
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
else {
|
|
2163
|
-
for (const scene of scenes) await runScene({ ...scene, candidate: scene.fixtureCandidate })
|
|
2164
|
-
evidence.status = 'passed'
|
|
2165
|
-
}
|
|
2166
|
-
}
|
|
2167
|
-
|
|
2168
|
-
async function cleanup() {
|
|
2169
|
-
currentStage = 'cleanup'
|
|
2170
|
-
const processResults = []
|
|
2171
|
-
const processByChild = new Map()
|
|
2172
|
-
if (appProcess) processByChild.set(appProcess, 'agentworkshop')
|
|
2173
|
-
if (simProcess) processByChild.set(simProcess, 'simulator')
|
|
2174
|
-
for (const child of children) if (!processByChild.has(child)) processByChild.set(child, child.label ?? 'child')
|
|
2175
|
-
for (const [child, label] of [...processByChild.entries()].reverse()) {
|
|
2176
|
-
try {
|
|
2177
|
-
const stopped = await stopProcessTree(child, label)
|
|
2178
|
-
processResults.push(stopped)
|
|
2179
|
-
if (!evidence.checks.some(item => item.id === `${label}-process-stopped`)) {
|
|
2180
|
-
evidence.checks.push({ id: `${label}-process-stopped`, status: 'fail', detail: { pid: child.pid ?? null, reason: 'process pid unavailable for termination verification' } })
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
catch (error) {
|
|
2184
|
-
evidence.checks.push({ id: `${label}-process-stopped`, status: 'fail', detail: { pid: child.pid ?? null, error: compactError(error) } })
|
|
2185
|
-
processResults.push(false)
|
|
2186
|
-
}
|
|
2187
|
-
}
|
|
2188
|
-
if (piApiServer) {
|
|
2189
|
-
try {
|
|
2190
|
-
await new Promise((resolvePromise, reject) => {
|
|
2191
|
-
piApiServer.close(error => error ? reject(error) : resolvePromise())
|
|
2192
|
-
})
|
|
2193
|
-
piApiServer = null
|
|
2194
|
-
evidence.checks.push({ id: 'local-model-api-process-stopped', status: 'pass', detail: { host: '127.0.0.1', port: MODEL_API_PORT } })
|
|
2195
|
-
}
|
|
2196
|
-
catch (error) {
|
|
2197
|
-
evidence.checks.push({ id: 'local-model-api-process-stopped', status: 'fail', detail: { error: compactError(error) } })
|
|
2198
|
-
processResults.push(false)
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
const portResults = []
|
|
2202
|
-
for (const [label, port] of [
|
|
2203
|
-
['app', AW_PORT],
|
|
2204
|
-
['simulator-http', SIM_PORT],
|
|
2205
|
-
['local-model-api', MODEL_API_PORT],
|
|
2206
|
-
['simulator-mqtt', MQTT_PORT],
|
|
2207
|
-
['offline-app-mqtt-queue-probe', OFFLINE_APP_MQTT_QUEUE_PORT],
|
|
2208
|
-
['offline-timescale-probe', OFFLINE_TSDB_PORT],
|
|
2209
|
-
['offline-objectstore-probe', OFFLINE_OBJECTSTORE_PORT],
|
|
2210
|
-
...allocatedDevicePorts.map((port, index) => [`simulator-device-${index}`, port]),
|
|
2211
|
-
]) {
|
|
2212
|
-
try {
|
|
2213
|
-
await assertFreeLoopback(port, label)
|
|
2214
|
-
evidence.checks.push({ id: `${label}-port-released`, status: 'pass', detail: { port, host: '127.0.0.1' } })
|
|
2215
|
-
portResults.push(true)
|
|
2216
|
-
}
|
|
2217
|
-
catch (error) {
|
|
2218
|
-
evidence.checks.push({ id: `${label}-port-released`, status: 'fail', detail: { port, host: '127.0.0.1', error: compactError(error) } })
|
|
2219
|
-
portResults.push(false)
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
try {
|
|
2223
|
-
closeSync(SIM_LOG_FD)
|
|
2224
|
-
}
|
|
2225
|
-
catch { /* already closed */ }
|
|
2226
|
-
try {
|
|
2227
|
-
closeSync(APP_LOG_FD)
|
|
2228
|
-
}
|
|
2229
|
-
catch { /* already closed */ }
|
|
2230
|
-
const requiredProcessLabels = evidence.status === 'passed' ? ['agentworkshop', 'simulator'] : [...processByChild.values()]
|
|
2231
|
-
const verifiedProcessLabels = new Set(evidence.checks.filter(item => item.id.endsWith('-process-stopped') && item.status === 'pass').map(item => item.id.replace(/-process-stopped$/, '')))
|
|
2232
|
-
const allRequiredProcessesVerified = requiredProcessLabels.every(label => verifiedProcessLabels.has(label))
|
|
2233
|
-
return processResults.every(Boolean) && portResults.every(Boolean) && allRequiredProcessesVerified
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
try {
|
|
2237
|
-
await main()
|
|
2238
|
-
}
|
|
2239
|
-
catch (error) {
|
|
2240
|
-
const preflightFailed = currentStage === 'preflight' || currentStage === 'compile-local-omp-fixture-shim' || currentStage === 'simulator-startup'
|
|
2241
|
-
evidence.status = preflightFailed ? 'blocked' : 'failed'
|
|
2242
|
-
evidence.failure = { stage: currentStage, scene: currentScene ?? null, ...compactError(error) }
|
|
2243
|
-
if (evidence.isolation.result === 'pending') evidence.isolation.result = preflightFailed ? 'failed' : 'incomplete'
|
|
2244
|
-
}
|
|
2245
|
-
finally {
|
|
2246
|
-
const cleanupPassed = await cleanup()
|
|
2247
|
-
if (!cleanupPassed) {
|
|
2248
|
-
evidence.status = 'failed'
|
|
2249
|
-
evidence.isolation.result = 'failed'
|
|
2250
|
-
evidence.failure ??= { stage: 'cleanup', name: 'CleanupVerificationError', message: 'process stop or loopback port release verification failed' }
|
|
2251
|
-
evidence.failure.cleanupVerificationFailed = true
|
|
2252
|
-
}
|
|
2253
|
-
if (evidence.status === 'passed') {
|
|
2254
|
-
const failedChecks = [...evidence.checks, ...evidence.isolation.checks].filter(item => item.status !== 'pass')
|
|
2255
|
-
const cleanupChecks = evidence.checks.filter(item => RELEASE_CHECK_SUFFIXES.some(suffix => item.id.endsWith(suffix)))
|
|
2256
|
-
if (failedChecks.length || !cleanupChecks.length || cleanupChecks.some(item => item.status !== 'pass')) {
|
|
2257
|
-
evidence.status = 'failed'
|
|
2258
|
-
evidence.isolation.result = 'failed'
|
|
2259
|
-
evidence.failure ??= { stage: 'final-verification', name: 'FinalVerificationError', message: 'not all experiment and cleanup checks passed' }
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
evidence.cleanup = { status: cleanupPassed ? 'passed' : 'failed', requiredProcessAndPortChecks: true }
|
|
2263
|
-
evidence.experiment.finishedAt = new Date().toISOString()
|
|
2264
|
-
evidence.experiment.evidencePath = 'evidence.json'
|
|
2265
|
-
evidence.experiment.runtimeLogPaths = { app: 'agentworkshop.log', simulator: 'simulator.log' }
|
|
2266
|
-
evidence.experiment.modelApiTrace = piApiTrace
|
|
2267
|
-
const sanitizeArchiveText = content => content
|
|
2268
|
-
.replaceAll(ROOT, '<isolated-run>')
|
|
2269
|
-
.replaceAll(HOME, '<isolated-home>')
|
|
2270
|
-
.replaceAll(REPO, '<workspace>')
|
|
2271
|
-
.replaceAll(PI_COMMAND, 'pi.cmd')
|
|
2272
|
-
.replace(/[A-Za-z0-9._%+-]+@example\.invalid/gi, '<synthetic-admin>')
|
|
2273
|
-
.replace(/[A-Z]:\\Users\\[^\\\s]+/gi, '<user-home>')
|
|
2274
|
-
try {
|
|
2275
|
-
mkdirSync(OUTPUT_DIR, { recursive: false })
|
|
2276
|
-
writeFileSync(PI_API_TRACE_PATH, `${JSON.stringify(piApiTrace, null, 2)}\n`, 'utf8')
|
|
2277
|
-
const archiveName = OUTPUT_DIR.slice(OUTPUT_DIR.lastIndexOf(sep) + 1)
|
|
2278
|
-
evidence.experiment.archiveDirectory = archiveName
|
|
2279
|
-
const archiveFiles = ['evidence.json', 'agentworkshop.log', 'simulator.log', 'pi-model-api-trace.json', 'e2e-pi-simulator-paper.mjs', 'README.md']
|
|
2280
|
-
evidence.experiment.archiveFiles = archiveFiles
|
|
2281
|
-
writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
|
|
2282
|
-
const archivedEvidence = `${sanitizeArchiveText(JSON.stringify(evidence, null, 2))}\n`
|
|
2283
|
-
writeFileSync(join(OUTPUT_DIR, 'evidence.json'), archivedEvidence, 'utf8')
|
|
2284
|
-
writeFileSync(join(OUTPUT_DIR, 'agentworkshop.log'), sanitizeArchiveText(readFileSync(APP_LOG, 'utf8')), 'utf8')
|
|
2285
|
-
writeFileSync(join(OUTPUT_DIR, 'simulator.log'), sanitizeArchiveText(readFileSync(SIM_LOG, 'utf8')), 'utf8')
|
|
2286
|
-
copyFileSync(PI_API_TRACE_PATH, join(OUTPUT_DIR, 'pi-model-api-trace.json'))
|
|
2287
|
-
copyFileSync(fileURLToPath(import.meta.url), join(OUTPUT_DIR, 'e2e-pi-simulator-paper.mjs'))
|
|
2288
|
-
const readme = [
|
|
2289
|
-
'# R23 registered Pi CLI simulator evidence',
|
|
2290
|
-
'',
|
|
2291
|
-
`Run status: **${evidence.status}**.`,
|
|
2292
|
-
'',
|
|
2293
|
-
'This archive was produced by a bounded local integration run of the registered Pi CLI adapter, its AgentWorkShop host-tool extension, the protected synthetic approval endpoint, and the loopback process simulator. The model endpoint is a deterministic OpenAI-compatible fixture bound to IPv4 loopback; no external model, provider, or service was called.',
|
|
2294
|
-
'',
|
|
2295
|
-
'The fixture is scripted to issue one bounded `recipe_trial`, pass its returned host-tool result back into Pi, issue one explicit `complete_task`, and pass that result back into Pi. Device acknowledgement, direct readback, run-tagged DAQ sample persistence, task/approval/receipt/sample linkage, and process/port cleanup are recorded in `evidence.json` when observed.',
|
|
2296
|
-
'',
|
|
2297
|
-
'The archived application and simulator logs contain runtime diagnostics with workspace and temporary-home paths and the synthetic admin email scrubbed. The Pi API trace contains request metadata and bounded tool-result text only; it omits prompts, credentials, session files, and the temporary isolated home.',
|
|
2298
|
-
'',
|
|
2299
|
-
evidence.failure ? `Recorded blocker/failure: ${safeText(evidence.failure.message, 500)} (stage: ${safeText(evidence.failure.stage, 120)}).` : 'No run blocker was recorded.',
|
|
2300
|
-
'',
|
|
2301
|
-
].join('\n')
|
|
2302
|
-
writeFileSync(join(OUTPUT_DIR, 'README.md'), readme, 'utf8')
|
|
2303
|
-
writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
|
|
2304
|
-
writeFileSync(join(OUTPUT_DIR, 'evidence.json'), `${sanitizeArchiveText(JSON.stringify(evidence, null, 2))}\n`, 'utf8')
|
|
2305
|
-
}
|
|
2306
|
-
catch (error) {
|
|
2307
|
-
evidence.status = 'failed'
|
|
2308
|
-
evidence.failure ??= { stage: 'evidence-archive', ...compactError(error) }
|
|
2309
|
-
writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
|
|
2310
|
-
}
|
|
2311
|
-
console.log(`REGISTERED_HARNESS_E2E=${evidence.status}`)
|
|
2312
|
-
console.log(`EVIDENCE=${join(OUTPUT_DIR, 'evidence.json')}`)
|
|
2313
|
-
console.log(`STAGE=${evidence.failure?.stage ?? 'complete'}`)
|
|
2314
|
-
}
|
|
2315
|
-
|
|
2316
|
-
if (evidence.status !== 'passed') process.exitCode = evidence.status === 'blocked' ? 2 : 1
|