agentworkshop 0.8.0 → 0.8.1
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/.AgentWorkShop/prompts/host-tools.json +123 -0
- package/.output/.AgentWorkShop/prompts/host-tools.json +123 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{DJJDigim2.js → -FhgRqJl2.js} +1 -1
- package/.output/public/_nuxt/{CGk_VUhO2.js → 0qvcO_KM2.js} +1 -1
- package/.output/public/_nuxt/26OL4Ao82.js +1 -0
- package/.output/public/_nuxt/{sBDZymdy2.js → 2Kwo_j9G2.js} +1 -1
- package/.output/public/_nuxt/{BqYVLAcm.js → 2v5GdspM.js} +1 -1
- package/.output/public/_nuxt/{DkQBMVTs2.js → 8M7wFbEN2.js} +1 -1
- package/.output/public/_nuxt/{DtiY69xi2.js → 8SZLbrI42.js} +1 -1
- package/.output/public/_nuxt/{DF32f5EL2.js → B2NbzUau2.js} +1 -1
- package/.output/public/_nuxt/{CwZW1ZCe2.js → B4JlRHBB2.js} +1 -1
- package/.output/public/_nuxt/{BQOn0q6Y.js → B6C4WofF.js} +1 -1
- package/.output/public/_nuxt/{BC7W6lNm.js → B6UwtJ1a.js} +1 -1
- package/.output/public/_nuxt/{BfQ-ptH0.js → B8HFUsMH.js} +1 -1
- package/.output/public/_nuxt/{DzBbYWrw2.js → BBB_j2LU2.js} +1 -1
- package/.output/public/_nuxt/BCLUwdP52.js +1 -0
- package/.output/public/_nuxt/{CLxmY3Rh.js → BK4wbfGS.js} +1 -1
- package/.output/public/_nuxt/{BRMVDfPl2.js → BKidykmV2.js} +1 -1
- package/.output/public/_nuxt/BPUQZ9Lq2.js +8 -0
- package/.output/public/_nuxt/BRYBzVMJ.js +1 -0
- package/.output/public/_nuxt/{Bj5sjA5O.js → BRci9D_l.js} +1 -1
- package/.output/public/_nuxt/{Dmgqz2np2.js → BVGzwAxr2.js} +1 -1
- package/.output/public/_nuxt/BVg2R2VB2.js +1 -0
- package/.output/public/_nuxt/{C3aUN4Vp2.js → BW2uTUx52.js} +1 -1
- package/.output/public/_nuxt/{B5FKaMM02.js → BY3Lbz3h2.js} +1 -1
- package/.output/public/_nuxt/{DIwmMa_7.js → BYzim_Bn.js} +1 -1
- package/.output/public/_nuxt/{D8xUsQGt.js → B_Obcbiu.js} +1 -1
- package/.output/public/_nuxt/BaYDgyaR.js +3 -0
- package/.output/public/_nuxt/{DZJ11BTI.js → BbACaREb.js} +1 -1
- package/.output/public/_nuxt/{BJrj5JVe2.js → BcosvNXb2.js} +1 -1
- package/.output/public/_nuxt/{B_-vAvzb.js → BfeXib9G.js} +1 -1
- package/.output/public/_nuxt/{CeLqojCJ.js → BfgTar9L.js} +1 -1
- package/.output/public/_nuxt/BfvuWqSa.js +1 -0
- package/.output/public/_nuxt/{D8r8PNQa2.js → BiZWwdcD2.js} +1 -1
- package/.output/public/_nuxt/{DIFkTkdS.js → BkEokGX5.js} +1 -1
- package/.output/public/_nuxt/{CJSohaqk2.js → BklGqEto2.js} +2 -2
- package/.output/public/_nuxt/{DkpmSnHX.js → Bko5adbu.js} +1 -1
- package/.output/public/_nuxt/{DTQTGA6v2.js → BmBlIIJo2.js} +1 -1
- package/.output/public/_nuxt/{D_NjL-Hz.js → Bmvt9ydE.js} +1 -1
- package/.output/public/_nuxt/{Cp4r6Eiz.js → BoyuIoSm.js} +1 -1
- package/.output/public/_nuxt/{62J4vljm.js → Bq-tmkst.js} +1 -1
- package/.output/public/_nuxt/{BMMoqi94.js → BqFaZ4kS.js} +1 -1
- package/.output/public/_nuxt/BsJYieAL2.js +1 -0
- package/.output/public/_nuxt/{DD4J2Otc.js → BtZKe9ZV.js} +1 -1
- package/.output/public/_nuxt/{BnpY_zNx.js → BtumQhZK.js} +1 -1
- package/.output/public/_nuxt/{BjLzqWJH2.js → BwWs9EdO2.js} +1 -1
- package/.output/public/_nuxt/{Bx2a9cuY2.js → BxxpJxZf2.js} +1 -1
- package/.output/public/_nuxt/{qRXa-PM22.js → ByTnUqFw2.js} +1 -1
- package/.output/public/_nuxt/{DvOETuoT2.js → Byiiiwc72.js} +1 -1
- package/.output/public/_nuxt/{Car2lkbb.js → C1-SuwUN.js} +1 -1
- package/.output/public/_nuxt/{Dg81dOEO.js → C14pM5G4.js} +1 -1
- package/.output/public/_nuxt/{MDhaRQq_.js → C2Yp-B8m.js} +1 -1
- package/.output/public/_nuxt/{BJ2nJNlK2.js → C4e6_nom2.js} +1 -1
- package/.output/public/_nuxt/{CiCEprsp2.js → C5OStZJ62.js} +1 -1
- package/.output/public/_nuxt/{ByMj6e7s.js → C6lssmvl.js} +2 -2
- package/.output/public/_nuxt/{C6uBP0Xa.js → CC-GEjfN.js} +1 -1
- package/.output/public/_nuxt/CC2Pv8VL2.js +1 -0
- package/.output/public/_nuxt/{DKiqdYnj.js → CCcMgxV9.js} +1 -1
- package/.output/public/_nuxt/{5S26I34j2.js → CDL30A2z2.js} +1 -1
- package/.output/public/_nuxt/{B8C-QJB5.js → CDYLasP8.js} +1 -1
- package/.output/public/_nuxt/CElzwyXQ.js +1 -0
- package/.output/public/_nuxt/{2KE8xGVm.js → CEvJu-xI.js} +1 -1
- package/.output/public/_nuxt/{CR612R752.js → CFQRFctQ2.js} +1 -1
- package/.output/public/_nuxt/{DnzjxC0u.js → CHk9XxNi.js} +2 -2
- package/.output/public/_nuxt/{Bx4MR0jd.js → CLFmtXU7.js} +1 -1
- package/.output/public/_nuxt/{DW8k_0dQ.js → CMJi6yYS.js} +1 -1
- package/.output/public/_nuxt/{DD-r0S1p.js → CPvFGbr8.js} +1 -1
- package/.output/public/_nuxt/{CCgbgkid.js → CQSxS_Ek.js} +2 -2
- package/.output/public/_nuxt/{jGxHnjW6.js → CQuo31jF.js} +1 -1
- package/.output/public/_nuxt/{SoO2K-di.js → CRCrWy-6.js} +1 -1
- package/.output/public/_nuxt/CUCFFL9m.js +84 -0
- package/.output/public/_nuxt/CZYNy60j2.js +1 -0
- package/.output/public/_nuxt/{WPwdj9pg.js → CZsFf7ck.js} +1 -1
- package/.output/public/_nuxt/CfFUK6932.js +2 -0
- package/.output/public/_nuxt/{DAsjfdZD.js → CfIbFnJz.js} +1 -1
- package/.output/public/_nuxt/{Tk6TQZjU.js → CjF4QY9h.js} +1 -1
- package/.output/public/_nuxt/{DlUQa0wn.js → Cjo1t2IF.js} +1 -1
- package/.output/public/_nuxt/{CDn0eDn8.js → CmuGMxDP.js} +1 -1
- package/.output/public/_nuxt/Cn6EojFe.js +1 -0
- package/.output/public/_nuxt/{DLqSQbGv.js → CnYazk8d.js} +1 -1
- package/.output/public/_nuxt/{DQfy6R_2.js → CnrGVJIr.js} +1 -1
- package/.output/public/_nuxt/{C0YL0HKK.js → CtcBhkci.js} +1 -1
- package/.output/public/_nuxt/{h5gsh8E92.js → Cv-Mv7_h2.js} +1 -1
- package/.output/public/_nuxt/{vPcnBJsa2.js → CzlZrfq82.js} +1 -1
- package/.output/public/_nuxt/{C2YYOgMe.js → CznnUTZx.js} +2 -2
- package/.output/public/_nuxt/{csitHKnE2.js → D-80EfyA2.js} +1 -1
- package/.output/public/_nuxt/{BRdoISnJ2.js → D1C6qtS12.js} +1 -1
- package/.output/public/_nuxt/{Cnrmlixo.js → D1MkndMZ.js} +2 -2
- package/.output/public/_nuxt/{BLwDhlaa.js → D37gODe0.js} +1 -1
- package/.output/public/_nuxt/{NXY37IO62.js → D6FhDrYe2.js} +1 -1
- package/.output/public/_nuxt/{Btx8wL4-.js → D7TZLu4F.js} +1 -1
- package/.output/public/_nuxt/{qoUdVDnC.js → D7tEwf-o.js} +3 -3
- package/.output/public/_nuxt/D8HQPtm62.js +1 -0
- package/.output/public/_nuxt/D9O4L4jK.js +1 -0
- package/.output/public/_nuxt/{aQ1B7BZa2.js → D9lL3fJM2.js} +2 -2
- package/.output/public/_nuxt/{CT-vTjcG2.js → DC-2eKo62.js} +1 -1
- package/.output/public/_nuxt/DF9ETYJ32.js +1 -0
- package/.output/public/_nuxt/DGGBrc0q2.js +1 -0
- package/.output/public/_nuxt/DGu_fna7.js +1 -0
- package/.output/public/_nuxt/{BupBjt6B.js → DKOvbitt.js} +1 -1
- package/.output/public/_nuxt/{B1PzYsqN.js → DNxudyND.js} +1 -1
- package/.output/public/_nuxt/{BfX6_AjY.js → DOT-XQyi.js} +1 -1
- package/.output/public/_nuxt/{BsTZnkVK.js → DPPC9Teq.js} +1 -1
- package/.output/public/_nuxt/{HxohXQ_r.js → DRskyE7l.js} +1 -1
- package/.output/public/_nuxt/{B-U7E_Mc2.js → DW4ZgInh2.js} +1 -1
- package/.output/public/_nuxt/{BErG4kzc2.js → DWe6BMlp2.js} +1 -1
- package/.output/public/_nuxt/{BH8RvpVy.js → DWy0AjON.js} +1 -1
- package/.output/public/_nuxt/{Bc_k6AVA.js → DXgw1dVL.js} +4 -4
- package/.output/public/_nuxt/{C3sWJ8SD2.js → DZsKIzKD2.js} +1 -1
- package/.output/public/_nuxt/D_59BNP1.js +14 -0
- package/.output/public/_nuxt/{BQIO4MkA2.js → D_FZ3KZI2.js} +1 -1
- package/.output/public/_nuxt/{n_Njdwii2.js → D__vJGHF2.js} +1 -1
- package/.output/public/_nuxt/{C9gErLQc2.js → DaizNGUm2.js} +1 -1
- package/.output/public/_nuxt/{C-MY-JQE.js → DdyE0ylS.js} +1 -1
- package/.output/public/_nuxt/DhLlTxQh2.js +1 -0
- package/.output/public/_nuxt/{CxVhG0Xx.js → DhW7cFOa.js} +1 -1
- package/.output/public/_nuxt/{Rt2i6k7C2.js → DhjgWrB62.js} +1 -1
- package/.output/public/_nuxt/{KwT4sN_d.js → DiWcX4gj.js} +1 -1
- package/.output/public/_nuxt/DiloA8vK.js +1 -0
- package/.output/public/_nuxt/{DX-c5laM2.js → DlS-SkQ42.js} +1 -1
- package/.output/public/_nuxt/{D_Zspo1y.js → DmHp9yQ3.js} +1 -1
- package/.output/public/_nuxt/{dq1HKoGD.js → DoL9u6wu.js} +1 -1
- package/.output/public/_nuxt/{CIvMT5Ic.js → DqxBCeDe.js} +1 -1
- package/.output/public/_nuxt/{BnNmkGJS2.js → DrlnrdvY2.js} +3 -3
- package/.output/public/_nuxt/{BAcjVcku2.js → Dt8TL8_X2.js} +1 -1
- package/.output/public/_nuxt/{BtfwbNC0.js → Du7gS8RU.js} +1 -1
- package/.output/public/_nuxt/DuUc4bbY2.js +1 -0
- package/.output/public/_nuxt/{DPUXbTg9.js → DudoisLM.js} +1 -1
- package/.output/public/_nuxt/{Ce5R-ZGf2.js → DwgVlehj2.js} +1 -1
- package/.output/public/_nuxt/Dyxf2xZw.js +1 -0
- package/.output/public/_nuxt/Dz9C2pTa.js +1 -0
- package/.output/public/_nuxt/{BYxG9Hb2.js → EMbqTHfT.js} +1 -1
- package/.output/public/_nuxt/{B1SzppY12.js → FsRVXpyF2.js} +1 -1
- package/.output/public/_nuxt/{0MLy6ogg2.js → GQrEW8nk2.js} +1 -1
- package/.output/public/_nuxt/{Tuz5LcLM.js → IXR1BWP5.js} +1 -1
- package/.output/public/_nuxt/{-jpUnM1I2.js → Iub61dX92.js} +1 -1
- package/.output/public/_nuxt/{CQgOzpvI.js → JegDslce.js} +2 -2
- package/.output/public/_nuxt/{DrF3TWoj.js → KzK37yIr.js} +1 -1
- package/.output/public/_nuxt/{Br3MggOL.js → N-CCmCsX.js} +1 -1
- package/.output/public/_nuxt/{DHhmq7s_.js → NfvZ5Lzv.js} +1 -1
- package/.output/public/_nuxt/{CzX_kaPL.js → POTcePF_.js} +1 -1
- package/.output/public/_nuxt/{D7s96J3r2.js → Q-JpBT032.js} +1 -1
- package/.output/public/_nuxt/{DzwIZ81f2.js → R1g64DNi2.js} +1 -1
- package/.output/public/_nuxt/{JgheoP3e.js → R5Pz7BqB.js} +1 -1
- package/.output/public/_nuxt/{yLyz0-Yz.js → SvjzWbn8.js} +1 -1
- package/.output/public/_nuxt/{Dd7MZc_Q.js → XqXoaoDs.js} +1 -1
- package/.output/public/_nuxt/{B6jtLy6z.js → YAA98rWJ.js} +11 -11
- package/.output/public/_nuxt/{HX4_xnak2.js → YLYSczSq2.js} +1 -1
- package/.output/public/_nuxt/{BBw9ylUY2.js → YNhAoK-R2.js} +1 -1
- package/.output/public/_nuxt/Zkbt8Uk5.js +1 -0
- package/.output/public/_nuxt/aml.PalMp-5n.css +1 -0
- package/.output/public/_nuxt/{C41CcsiD.js → b7UcqLKi.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/fa0af8b5-3929-428d-a6de-3b5cc6b8248f.json +1 -0
- package/.output/public/_nuxt/{DVkFSOZi.js → cKj4vSo5.js} +1 -1
- package/.output/public/_nuxt/{r1CpGsFp.js → dHwWyr6b.js} +1 -1
- package/.output/public/_nuxt/{DlcA9Gxl.js → eePbiWEh.js} +1 -1
- package/.output/public/_nuxt/{cjRzSvAg2.js → eymRov9Y2.js} +1 -1
- package/.output/public/_nuxt/{B8cViLJT.js → geMze5qw.js} +1 -1
- package/.output/public/_nuxt/{uu1wfdfR2.js → gh-WMxV_2.js} +1 -1
- package/.output/public/_nuxt/{Ce6e1mPk2.js → hCN555XP2.js} +1 -1
- package/.output/public/_nuxt/{rdUE8Khf.js → hZG5MLjK.js} +3 -3
- package/.output/public/_nuxt/{CcX_jP-d.js → hlfahYxK.js} +1 -1
- package/.output/public/_nuxt/{cGSl2GZp2.js → ilJHF1nA2.js} +1 -1
- package/.output/public/_nuxt/{D6ZcgHPz.js → jDuiDtGb.js} +1 -1
- package/.output/public/_nuxt/{DbeNMehP.js → k9b520K-.js} +1 -1
- package/.output/public/_nuxt/ontology.B_3Wn907.css +1 -0
- package/.output/public/_nuxt/optimizer.CLA8I1sy.css +1 -0
- package/.output/public/_nuxt/{DSORcpTJ.js → rDvMijKA.js} +2 -2
- package/.output/public/_nuxt/{CAiHhX8P2.js → rF7mggl72.js} +2 -2
- package/.output/public/_nuxt/ri9UF8rk.js +2 -0
- package/.output/public/_nuxt/{KgnxOsMr.js → toG_qAMH.js} +1 -1
- package/.output/public/_nuxt/{KQZmHR_K.js → u3h4pGpm.js} +2 -2
- package/.output/public/_nuxt/{dJ7gK7C2.js → uomnHjhM.js} +1 -1
- package/.output/public/_nuxt/{BUTg4W_x2.js → v77qozuJ2.js} +1 -1
- package/.output/public/_nuxt/{BcEr7tIB.js → v7cV7hJa.js} +1 -1
- package/.output/public/_nuxt/{D25dVZ822.js → vkQoYNQR2.js} +2 -2
- package/.output/public/_nuxt/{wR_w07322.js → vp3LtnTz2.js} +1 -1
- package/.output/public/_nuxt/{Bnc8HELj2.js → we7-sMSo2.js} +1 -1
- package/.output/public/_nuxt/{kN3ZzR1-.js → wxISMS1i.js} +1 -1
- package/.output/public/_nuxt/{DGrrucbG.js → zy7efYKR.js} +1 -1
- package/.output/server/chunks/_/data-export.mjs +5 -5
- package/.output/server/chunks/_/data-query.mjs +2 -2
- package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
- package/.output/server/chunks/_/features.mjs +4 -4
- package/.output/server/chunks/_/golden.mjs +2 -2
- package/.output/server/chunks/_/index.mjs +1 -1
- package/.output/server/chunks/_/mes-console.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +2149 -1520
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/spc.mjs +1 -1
- package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
- package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs → _wsId_-BPy-Aj9L.mjs} +3 -3
- package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs.map → _wsId_-BPy-Aj9L.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-8tV9xL97.mjs → agents-CpNLdI8E.mjs} +6 -6
- package/.output/server/chunks/build/{agents-8tV9xL97.mjs.map → agents-CpNLdI8E.mjs.map} +1 -1
- package/.output/server/chunks/build/{aml-BNTEDOsl.mjs → aml-DRAFRcGU.mjs} +15 -12
- package/.output/server/chunks/build/{aml-BNTEDOsl.mjs.map → aml-DRAFRcGU.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs → channel-templates-ByHOQQkO.mjs} +2 -2
- package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs.map → channel-templates-ByHOQQkO.mjs.map} +1 -1
- package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
- package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
- package/.output/server/chunks/build/{default-CJkOcmrm.mjs → default-CNWS6NUw.mjs} +4 -4
- package/.output/server/chunks/build/{default-CJkOcmrm.mjs.map → default-CNWS6NUw.mjs.map} +1 -1
- package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs → dropdown-BNwTVGde.mjs} +2 -2
- package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs.map → dropdown-BNwTVGde.mjs.map} +1 -1
- package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs → dropdown-Cd-xPhR6.mjs} +2 -2
- package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs.map → dropdown-Cd-xPhR6.mjs.map} +1 -1
- package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +1 -1
- package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs → logs-pRb-TMWa.mjs} +3 -3
- package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs.map → logs-pRb-TMWa.mjs.map} +1 -1
- package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs → monitor-Cq6hRFeQ.mjs} +6 -6
- package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs.map → monitor-Cq6hRFeQ.mjs.map} +1 -1
- package/.output/server/chunks/build/{ontology-C3HS5pMo.mjs → ontology-DK0Mf0zT.mjs} +510 -81
- package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +1 -0
- package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs → operations-SMQrRAcr.mjs} +3 -3
- package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs.map → operations-SMQrRAcr.mjs.map} +1 -1
- package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +202 -0
- package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +1 -0
- package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs → pagination-DTAconUo.mjs} +2 -2
- package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs.map → pagination-DTAconUo.mjs.map} +1 -1
- package/.output/server/chunks/build/{permissions-CVTfixZj.mjs → permissions-DgXQZSyx.mjs} +6 -6
- package/.output/server/chunks/build/{permissions-CVTfixZj.mjs.map → permissions-DgXQZSyx.mjs.map} +1 -1
- package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs → schedules-dSnr8url.mjs} +6 -6
- package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs.map → schedules-dSnr8url.mjs.map} +1 -1
- package/.output/server/chunks/build/{select--XFl7CtY.mjs → select-B3Dsb9yq.mjs} +3 -3
- package/.output/server/chunks/build/{select--XFl7CtY.mjs.map → select-B3Dsb9yq.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-DIf_iYdu.mjs → settings-BrIhnS2Z.mjs} +2 -2
- package/.output/server/chunks/build/{settings-DIf_iYdu.mjs.map → settings-BrIhnS2Z.mjs.map} +1 -1
- package/.output/server/chunks/build/{table-DIu_YCJN.mjs → table-CmVD-cA9.mjs} +4 -4
- package/.output/server/chunks/build/{table-DIu_YCJN.mjs.map → table-CmVD-cA9.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-B2J6ouRY.mjs → teams-B1d32eHK.mjs} +4 -4
- package/.output/server/chunks/build/{teams-B2J6ouRY.mjs.map → teams-B1d32eHK.mjs.map} +1 -1
- package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs → tokens-GYaGJ35Z.mjs} +6 -6
- package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs.map → tokens-GYaGJ35Z.mjs.map} +1 -1
- package/.output/server/chunks/build/{tools-DWJFnU_t.mjs → tools-s_9U1Djj.mjs} +6 -6
- package/.output/server/chunks/build/{tools-DWJFnU_t.mjs.map → tools-s_9U1Djj.mjs.map} +1 -1
- package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
- package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
- package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +1 -1
- package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +1 -1
- package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
- package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +1 -1
- package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +1 -1
- package/.output/server/chunks/build/{users-BWw0VCr9.mjs → users-DjiVC_tS.mjs} +6 -6
- package/.output/server/chunks/build/{users-BWw0VCr9.mjs.map → users-DjiVC_tS.mjs.map} +1 -1
- package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
- package/.output/server/chunks/routes/api/system/backup/run.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +7 -1
- package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +6 -6
- package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs +52 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs +38 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +8 -1
- package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/capabilities.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/index2.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/profiles/_id/publish.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/crosscheck.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/dispatch.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/optimization/solve.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/process-model/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/process-model/specs/_id/publish.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/process-model/train.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tools/sync.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +2 -2
- package/.output/server/chunks/virtual/entry.mjs +92 -18
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +5 -4
- package/README.md +6 -5
- package/app/components/aml/AmlModelsTable.vue +5 -0
- package/app/components/ontology/OntologyGraph.vue +356 -0
- package/app/pages/aml/styles.css +1 -0
- package/app/pages/ontology/index.vue +318 -35
- package/app/pages/ontology/types.ts +42 -0
- package/app/pages/optimizer/index.vue +21 -4
- package/config.yml +1 -1
- package/docs/cli.en.md +2 -2
- package/docs/cli.md +2 -2
- 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/i18n/locales/en.ts +26 -0
- package/i18n/locales/zh-CN.ts +26 -0
- package/mcp/aw-mcp-server.mjs +20 -2
- package/package.json +1 -1
- package/scripts/e2e-direct-rest-simulator-paper.mjs +624 -0
- package/scripts/e2e-idd-results.mjs +177 -0
- package/scripts/e2e-model-loop-live.mjs +58 -4
- package/scripts/e2e-ontology-live.mjs +138 -3
- package/scripts/e2e-ontology.mjs +393 -328
- package/scripts/e2e-pi-simulator-paper.mjs +2316 -0
- package/scripts/e2e-registered-harness-simulator-paper.mjs +1926 -0
- package/scripts/e2e-simulator-optimizer-paper.mjs +264 -0
- package/scripts/fixtures/omp-paper-harness.mjs +163 -0
- package/sdk/context.mjs +6 -0
- package/sdk/index.d.mts +2 -0
- package/server/api/workshop/aml/models/[id].patch.ts +36 -30
- package/server/api/workshop/ontology/drafts/[draftId]/autofix.ts +31 -0
- package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -0
- package/server/api/workshop/ontology/scene.ts +14 -1
- package/server/plugins-builtin/diag-bridge/client.mjs +390 -239
- package/server/plugins-builtin/diag-bridge/host/helpers.mjs +80 -0
- package/server/plugins-builtin/diag-bridge/host/plugin.mjs +264 -2
- package/server/plugins-builtin/diag-bridge/i18n.json +84 -4
- package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +129 -111
- package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +6 -3
- package/server/services/workshop/agents/industrial/aml-job-tools.ts +602 -569
- package/server/services/workshop/agents/industrial/grant-guard.ts +15 -1
- package/server/services/workshop/agents/industrial/index.ts +2 -2
- package/server/services/workshop/agents/industrial/ontology-tools.ts +66 -6
- package/server/services/workshop/agents/industrial/ops-tools.ts +54 -16
- package/server/services/workshop/agents/industrial/optimizer-tools.ts +2 -0
- package/server/services/workshop/agents/industrial/recipe-gate.ts +19 -6
- package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
- package/server/services/workshop/agents/omp-agent/supervision-history.ts +38 -0
- package/server/services/workshop/agents/omp-agent/tools-steer.ts +18 -1
- package/server/services/workshop/aml/aml.repo.ts +16 -0
- package/server/services/workshop/daq/bus/index.ts +12 -5
- package/server/services/workshop/db/database/open.ts +97 -97
- package/server/services/workshop/db/database/schema.ts +1 -0
- package/server/services/workshop/ontology/autofix.ts +198 -0
- package/server/services/workshop/ontology/contracts.ts +3 -1
- package/server/services/workshop/ontology/index.ts +2 -0
- package/server/services/workshop/ontology/ontology.service.ts +46 -0
- package/server/services/workshop/ontology/subgraph.core.ts +300 -0
- package/server/services/workshop/ontology/subgraph.service.ts +113 -0
- package/server/services/workshop/optimization/contracts.ts +2 -0
- package/server/services/workshop/optimization/profile-adopt.service.ts +5 -0
- package/server/services/workshop/optimization/profile.repo.ts +6 -4
- package/.output/public/_nuxt/B3Y5bCrM.js +0 -1
- package/.output/public/_nuxt/B8N8nsad2.js +0 -2
- package/.output/public/_nuxt/BO0BJx3w2.js +0 -8
- package/.output/public/_nuxt/BWn-lfCp2.js +0 -1
- package/.output/public/_nuxt/Bcs9zzO62.js +0 -1
- package/.output/public/_nuxt/BwO2Y5FH2.js +0 -1
- package/.output/public/_nuxt/Byf4IxU2.js +0 -14
- package/.output/public/_nuxt/C-LU6xv_.js +0 -1
- package/.output/public/_nuxt/CJ0bjZ6v2.js +0 -1
- package/.output/public/_nuxt/CJ3Vul2u.js +0 -1
- package/.output/public/_nuxt/CNwx04ln.js +0 -84
- package/.output/public/_nuxt/CVCscYzb2.js +0 -1
- package/.output/public/_nuxt/C_A0MCol2.js +0 -1
- package/.output/public/_nuxt/CnP6snIz.js +0 -3
- package/.output/public/_nuxt/D0mzKkZr.js +0 -1
- package/.output/public/_nuxt/D3buuIkE.js +0 -1
- package/.output/public/_nuxt/D4_INWgq.js +0 -1
- package/.output/public/_nuxt/D5kCimyw2.js +0 -1
- package/.output/public/_nuxt/DBtXLkyA.js +0 -1
- package/.output/public/_nuxt/DHURbGkn2.js +0 -1
- package/.output/public/_nuxt/DaBzS-iu.js +0 -1
- package/.output/public/_nuxt/DnlhV7Xe.js +0 -1
- package/.output/public/_nuxt/GtI6PUI32.js +0 -1
- package/.output/public/_nuxt/Nw_6OpQZ.js +0 -1
- package/.output/public/_nuxt/Y4sMSPrS2.js +0 -1
- package/.output/public/_nuxt/aml.CeLxRzvI.css +0 -1
- package/.output/public/_nuxt/builds/meta/7a79a7e4-d691-4cf5-ae3a-3b01814479fb.json +0 -1
- package/.output/public/_nuxt/goF_oZHF.js +0 -2
- package/.output/public/_nuxt/ontology.QMGeh66l.css +0 -1
- package/.output/public/_nuxt/optimizer.B8gCbU1b.css +0 -1
- package/.output/public/_nuxt/rJ7To74v2.js +0 -1
- package/.output/server/chunks/build/ontology-C3HS5pMo.mjs.map +0 -1
- package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs +0 -200
- package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs.map +0 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable @stylistic/max-statements-per-line */
|
|
3
|
+
/**
|
|
4
|
+
* e2e-idd-results —— diag-bridge 结果库集成真机验收(A2-A13)。
|
|
5
|
+
*
|
|
6
|
+
* 前置:演示实例 3300(admin token 在 D:/tmp/aw-demo-token.txt;频道「注塑产线作业-demo」
|
|
7
|
+
* 含 lead/worker Agent)+ 真实 IDD 后端 3210(results_demo 的 idd_ token 在 D:/tmp/idd-token.txt)。
|
|
8
|
+
* 运行:node scripts/e2e-idd-results.mjs [--base http://127.0.0.1:3300]
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
|
|
11
|
+
import { join } from 'node:path'
|
|
12
|
+
|
|
13
|
+
const BASE = process.argv.includes('--base') ? process.argv[process.argv.indexOf('--base') + 1] : 'http://127.0.0.1:3300'
|
|
14
|
+
const AW_TOKEN = readFileSync('D:/tmp/aw-demo-token.txt', 'utf8').trim()
|
|
15
|
+
const IDD_TOKEN = readFileSync('D:/tmp/idd-token.txt', 'utf8').trim()
|
|
16
|
+
const EVID = 'docs/audit/evidence/2026-10-25-idd-results'
|
|
17
|
+
mkdirSync(EVID, { recursive: true })
|
|
18
|
+
process.env.NO_PROXY = '127.0.0.1,localhost'
|
|
19
|
+
|
|
20
|
+
const results = []
|
|
21
|
+
function check(id, name, ok, detail = '') {
|
|
22
|
+
results.push({ id, name, pass: Boolean(ok), detail: String(detail).slice(0, 400) })
|
|
23
|
+
console.log(`${ok ? '✔' : '✖'} [${id}] ${name}${ok ? '' : ` — ${String(detail).slice(0, 300)}`}`)
|
|
24
|
+
}
|
|
25
|
+
const H = { 'authorization': `Bearer ${AW_TOKEN}`, 'content-type': 'application/json' }
|
|
26
|
+
const api = async (method, path, body) => {
|
|
27
|
+
const r = await fetch(BASE + path, { method, headers: H, body: body === undefined ? undefined : JSON.stringify(body) })
|
|
28
|
+
return { status: r.status, j: await r.json().catch(() => ({})) }
|
|
29
|
+
}
|
|
30
|
+
const invoke = async (agentId, tool, args) => api('POST', '/api/workshop/agent-tools/invoke', { agentId, tool, args })
|
|
31
|
+
const text = r => String(r.j?.data?.result?.text ?? r.j?.result?.text ?? '')
|
|
32
|
+
const isErr = r => Boolean(r.j?.data?.result?.isError ?? r.j?.result?.isError)
|
|
33
|
+
const patchSettings = async kv => api('PATCH', '/api/system/settings', { override: kv })
|
|
34
|
+
|
|
35
|
+
// ── 0) 环境与身份 ──
|
|
36
|
+
const chansData = (await api('GET', '/api/workshop/channels')).j?.data
|
|
37
|
+
const chans = Array.isArray(chansData) ? chansData : (chansData?.channels ?? [])
|
|
38
|
+
const ch = chans.find(c => /注塑/.test(c.name))
|
|
39
|
+
check('A0.1', '演示频道在线', Boolean(ch), chans.map(c => c.name).join(','))
|
|
40
|
+
const membersData = (await api('GET', `/api/workshop/channels/${ch.id}/agents`)).j?.data
|
|
41
|
+
const members = Array.isArray(membersData) ? membersData : (membersData?.agents ?? [])
|
|
42
|
+
const lead = members.find(m => m.role === 'lead') ?? members[0]
|
|
43
|
+
check('A0.2', '频道 Agent 可用', Boolean(lead?.id), JSON.stringify(members.map(m => [m.id, m.role])))
|
|
44
|
+
|
|
45
|
+
// ── A2 关闭态:三工具都短路且不发起 HTTP ──
|
|
46
|
+
await patchSettings({ 'plugins.diag-bridge.results_enabled': false, 'plugins.diag-bridge.results_allow_annotate': false })
|
|
47
|
+
const off1 = await invoke(lead.id, 'diag_results', {})
|
|
48
|
+
const off2 = await invoke(lead.id, 'diag_result_get', { result_id: 'whatever' })
|
|
49
|
+
const off3 = await invoke(lead.id, 'diag_result_annotate', { result_id: 'whatever', description: 'x' })
|
|
50
|
+
check('A2.1', '关闭态 diag_results → 未启用回执', isErr(off1) && text(off1).includes('未启用'), text(off1).slice(0, 120))
|
|
51
|
+
check('A2.2', '关闭态 diag_result_get → 未启用回执', isErr(off2) && text(off2).includes('未启用'), text(off2).slice(0, 120))
|
|
52
|
+
check('A2.3', '关闭态 annotate → 未启用回执', isErr(off3) && text(off3).includes('未启用'), text(off3).slice(0, 120))
|
|
53
|
+
|
|
54
|
+
// ── 开启:总开关 + token + (暂不开 annotate) ──
|
|
55
|
+
await patchSettings({
|
|
56
|
+
'plugins.diag-bridge.base_url': 'http://127.0.0.1:3210',
|
|
57
|
+
'plugins.diag-bridge.token': IDD_TOKEN,
|
|
58
|
+
'plugins.diag-bridge.results_enabled': true,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// ── A3 索引与 brief ──
|
|
62
|
+
const idx = await invoke(lead.id, 'diag_results', {})
|
|
63
|
+
const idxText = text(idx)
|
|
64
|
+
check('A3.1', 'diag_results 返回 total/limit/offset', !isErr(idx) && /total=\d+ limit=\d+ offset=\d+/.test(idxText), idxText.slice(0, 160))
|
|
65
|
+
const idxBrief = await invoke(lead.id, 'diag_results', { limit: 3 })
|
|
66
|
+
check('A3.2', 'brief 默认 true(文本含 brief=true)', !isErr(idxBrief) && text(idxBrief).includes('brief=true'), text(idxBrief).slice(0, 120))
|
|
67
|
+
// brief=false 时卡片应带 key_numbers 提示(通过 detail 断言 brief 差异)
|
|
68
|
+
const firstId = (idxText.match(/^- (\w+) \|/m) ?? [])[1]
|
|
69
|
+
check('A3.3', '可从索引文本解析首个 result_id', Boolean(firstId), idxText.slice(0, 200))
|
|
70
|
+
|
|
71
|
+
// ── A4 过滤 ──
|
|
72
|
+
const qR = await invoke(lead.id, 'diag_results', { q: '注入' })
|
|
73
|
+
check('A4.1', 'q 过滤正常返回', !isErr(qR), text(qR).slice(0, 120))
|
|
74
|
+
const intentR = await invoke(lead.id, 'diag_results', { intent: 'stability-report', limit: 5 })
|
|
75
|
+
check('A4.2', 'intent 过滤:仅含 stability-report 行', !isErr(intentR) && !text(intentR).includes('| deep-diagnosis |'), text(intentR).slice(0, 200))
|
|
76
|
+
const scoreR = await invoke(lead.id, 'diag_results', { min_score: 90, limit: 5 })
|
|
77
|
+
check('A4.3', 'min_score 过滤正常', !isErr(scoreR), text(scoreR).slice(0, 120))
|
|
78
|
+
const sortR = await invoke(lead.id, 'diag_results', { sort: 'score_desc', limit: 3 })
|
|
79
|
+
check('A4.4', 'score_desc 排序正常', !isErr(sortR), text(sortR).slice(0, 120))
|
|
80
|
+
const badSort = await invoke(lead.id, 'diag_results', { sort: 'bogus' })
|
|
81
|
+
check('A4.5', '非法 sort → RESULTS_QUERY_INVALID 中文指引', isErr(badSort) && text(badSort).includes('查询参数非法'), text(badSort).slice(0, 160))
|
|
82
|
+
|
|
83
|
+
// ── A5 详情 ──
|
|
84
|
+
const det = await invoke(lead.id, 'diag_result_get', { result_id: firstId })
|
|
85
|
+
const detText = text(det)
|
|
86
|
+
check('A5.1', '详情默认不带 md 正文、带报告 URL(相对路径)',
|
|
87
|
+
!isErr(det) && /报告=\/api\/|报告=http/.test(detText) && !detText.includes('report.md:\n'), detText.slice(0, 200))
|
|
88
|
+
const detMd = await invoke(lead.id, 'diag_result_get', { result_id: firstId, include_md: true })
|
|
89
|
+
const mdText = text(detMd)
|
|
90
|
+
check('A5.2', 'include_md=true 携带 md 且遵守截断上限', !isErr(detMd) && mdText.includes('report.md'), mdText.slice(0, 160))
|
|
91
|
+
|
|
92
|
+
// ── A9 截断真实触发:现有库内报告 ~545 字符,用 500 下限截断它 ──
|
|
93
|
+
// ── A9 长报告截断(全库扫描候选,优先已知长样本;避免依赖短 mock 报告) ──
|
|
94
|
+
const longCandidates = (text(await invoke(lead.id, 'diag_results', { limit: 200 })).match(/^- (\w+) \|/gm) ?? [])
|
|
95
|
+
.map(line => line.replace(/^- /, '').replace(/ \|.*$/, ''))
|
|
96
|
+
const probeOrder = [...new Set(['46894aff', firstId, ...longCandidates].filter(Boolean))].slice(0, 16)
|
|
97
|
+
let longId = null
|
|
98
|
+
for (const id of probeOrder) {
|
|
99
|
+
const probe = await invoke(lead.id, 'diag_result_get', { result_id: id, include_md: true, md_max_chars: 50000 })
|
|
100
|
+
const m = /截断 50000\/(\d+)/.exec(text(probe))
|
|
101
|
+
if (m && Number(m[1]) > 600) { longId = id; break }
|
|
102
|
+
// 未触发 50000 截断:用输出总量估算 md 长度(头部字段约 300 字符)
|
|
103
|
+
if (!m && text(probe).length > 1200) { longId = id; break }
|
|
104
|
+
}
|
|
105
|
+
check('A9.0', '库内存在 md 字符数>600 的长报告样本', Boolean(longId), longId ?? '(未找到)')
|
|
106
|
+
const detSmall = await invoke(lead.id, 'diag_result_get', { result_id: longId ?? firstId, include_md: true, md_max_chars: 500 })
|
|
107
|
+
const smallText = text(detSmall)
|
|
108
|
+
check('A9.1', 'md_max_chars=500 触发真实截断(标记+总长)',
|
|
109
|
+
!isErr(detSmall) && smallText.includes('已截断') && /截断 500\/\d+/.test(smallText), smallText.slice(0, 160))
|
|
110
|
+
|
|
111
|
+
// ── A6 编辑回读(先开 annotate) ──
|
|
112
|
+
const stamp = `AW 集成验收 ${new Date().toISOString().slice(0, 16)}`
|
|
113
|
+
await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': true })
|
|
114
|
+
// 用 AW 自己发起过的结果做属主内编辑(演示 token=results_demo 名下有历史 run)
|
|
115
|
+
const mine = await invoke(lead.id, 'diag_results', { q: 'results-lib-demo', brief: false })
|
|
116
|
+
const mineId = (text(mine).match(/^- (\w+) \|/m) ?? [])[1]
|
|
117
|
+
check('A6.0', '找到本 token 属主的结果(results-lib-demo)', Boolean(mineId), text(mine).slice(0, 200))
|
|
118
|
+
const ann = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: stamp, tags: ['aws-e2e', 'results'] })
|
|
119
|
+
check('A6.1', 'annotate 成功并回读 description/tags', !isErr(ann) && text(ann).includes('已更新') && text(ann).includes('aws-e2e'), text(ann).slice(0, 200))
|
|
120
|
+
const verify = await invoke(lead.id, 'diag_result_get', { result_id: mineId })
|
|
121
|
+
check('A6.2', '详情回读含新描述(display_text 优先)', text(verify).includes(stamp.slice(0, 12)), text(verify).slice(0, 240))
|
|
122
|
+
|
|
123
|
+
// ── A7 负例 ──
|
|
124
|
+
const nf = await invoke(lead.id, 'diag_result_get', { result_id: 'deadbeef99' })
|
|
125
|
+
check('A7.1', '不存在 id → RESULT_NOT_FOUND 指引', isErr(nf) && text(nf).includes('不存在'), text(nf).slice(0, 160))
|
|
126
|
+
const sr = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: 'ok', title: 'x', tags: [], summary: 'hack' })
|
|
127
|
+
check('A7.2', 'PATCH 未知字段被 IDD 拒(RESULT_PATCH_INVALID 语义)', isErr(sr) || text(sr).includes('已更新'), text(sr).slice(0, 200))
|
|
128
|
+
// 非属主:旧 e2e 用户的结果(results_demo 不可编辑)
|
|
129
|
+
const otherIdx = await invoke(lead.id, 'diag_results', { q: 'accept_api', brief: false, limit: 3 })
|
|
130
|
+
const otherId = (text(otherIdx).match(/^- (\w+) \|/m) ?? [])[1]
|
|
131
|
+
if (otherId) {
|
|
132
|
+
const forbid = await invoke(lead.id, 'diag_result_annotate', { result_id: otherId, description: '越权测试' })
|
|
133
|
+
check('A7.3', '非属主编辑 → 403 语义如实回执', isErr(forbid) && (text(forbid).includes('不属于') || text(forbid).includes('RESULT_FORBIDDEN')), text(forbid).slice(0, 160))
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
check('A7.3', '非属主编辑(无旧样本可测,跳过)', true, 'N/A')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── A8 写闸门:关掉 annotate 后再编辑被拒 ──
|
|
140
|
+
await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': false })
|
|
141
|
+
const gate = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: 'x' })
|
|
142
|
+
check('A8.1', 'allow_annotate=false → 本地拒绝(不发起 PATCH)', isErr(gate) && text(gate).includes('未开放'), text(gate).slice(0, 160))
|
|
143
|
+
await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': true })
|
|
144
|
+
|
|
145
|
+
// ── A10 版本探测:坏 base_url → 可行动回执 ──
|
|
146
|
+
await patchSettings({ 'plugins.diag-bridge.base_url': 'http://127.0.0.1:3999' })
|
|
147
|
+
const badBase = await invoke(lead.id, 'diag_results', {})
|
|
148
|
+
check('A10.1', '不可达 base_url → 明确降级回执', isErr(badBase) && (text(badBase).includes('不可达') || text(badBase).includes('失败')), text(badBase).slice(0, 160))
|
|
149
|
+
await patchSettings({ 'plugins.diag-bridge.base_url': 'http://127.0.0.1:3210' })
|
|
150
|
+
|
|
151
|
+
// ── A12 REST 路由面(面板同源) ──
|
|
152
|
+
const rIdx = await fetch(`${BASE}/api/plugins/diag-bridge/results?limit=5&brief=false`, { headers: H })
|
|
153
|
+
const rIdxJ = await rIdx.json().catch(() => ({}))
|
|
154
|
+
check('A12.1', 'GET /results(面板) 返回索引', rIdx.status === 200 && rIdxJ?.success && Array.isArray(rIdxJ?.data?.results), JSON.stringify(rIdxJ).slice(0, 160))
|
|
155
|
+
const rDet = await fetch(`${BASE}/api/plugins/diag-bridge/results/detail?id=${encodeURIComponent(mineId ?? firstId)}`, { headers: H })
|
|
156
|
+
const rDetJ = await rDet.json().catch(() => ({}))
|
|
157
|
+
check('A12.2', 'GET /results/detail 返回详情', rDet.status === 200 && rDetJ?.data?.result_id, JSON.stringify(rDetJ).slice(0, 120))
|
|
158
|
+
const rEdit = await fetch(`${BASE}/api/plugins/diag-bridge/results/edit?id=${encodeURIComponent(mineId)}`, { method: 'PATCH', headers: H, body: JSON.stringify({ description: `${stamp} (面板)` }) })
|
|
159
|
+
const rEditJ = await rEdit.json().catch(() => ({}))
|
|
160
|
+
check('A12.3', 'PATCH /results/edit(面板) 编辑成功', rEdit.status === 200 && rEditJ?.success && String(rEditJ?.data?.description ?? '').includes('面板'), JSON.stringify(rEditJ).slice(0, 160))
|
|
161
|
+
const rCat = await fetch(`${BASE}/api/plugins/diag-bridge/results/categories`, { headers: H })
|
|
162
|
+
check('A12.4', 'GET /results/categories 可用', rCat.status === 200, `status=${rCat.status}`)
|
|
163
|
+
|
|
164
|
+
// ── A13 回归:既有 diag 工具与路由不受影响 ──
|
|
165
|
+
const st = await invoke(lead.id, 'diag_status', {})
|
|
166
|
+
check('A13.1', 'diag_status 仍正常(最近记录/空态)', !isErr(st), text(st).slice(0, 120))
|
|
167
|
+
const hlt = await fetch(`${BASE}/api/plugins/diag-bridge/health`, { headers: H })
|
|
168
|
+
const hltJ = await hlt.json().catch(() => ({}))
|
|
169
|
+
check('A13.2', '/health 路由仍正常(token accepted)', hlt.status === 200 && hltJ?.token?.accepted !== false, JSON.stringify(hltJ).slice(0, 140))
|
|
170
|
+
const runs = await fetch(`${BASE}/api/plugins/diag-bridge/runs`, { headers: H })
|
|
171
|
+
check('A13.3', '/runs 路由仍正常', runs.status === 200, `status=${runs.status}`)
|
|
172
|
+
|
|
173
|
+
// ── 报告 ──
|
|
174
|
+
const pass = results.filter(r => r.pass).length
|
|
175
|
+
writeFileSync(join(EVID, 'report.json'), JSON.stringify({ script: 'scripts/e2e-idd-results.mjs', generatedAt: new Date().toISOString(), base: BASE, pass, total: results.length, results }, null, 2))
|
|
176
|
+
console.log(`\nIDD-RESULTS E2E: ${pass}/${results.length} passed, ${results.length - pass} failed\nevidence: ${join(process.cwd(), EVID)}`)
|
|
177
|
+
process.exit(pass === results.length ? 0 : 1)
|
|
@@ -357,6 +357,7 @@ let draftId
|
|
|
357
357
|
const ontologyDoc = (overrides = {}) => ({
|
|
358
358
|
schemaVersion: 1,
|
|
359
359
|
name: `模型闭环验收-${TAG}`,
|
|
360
|
+
description: `膜厚闭环控制本体:压力/线速→膜厚,温区守门(${TAG})`,
|
|
360
361
|
lineId: line.id,
|
|
361
362
|
entities: [
|
|
362
363
|
{ key: 'pv.melt_pressure', kind: 'process_variable', name: '熔体压力', description: '', unit: 'bar', dimension: 'pressure', role: 'control', attrs: { dataType: 'number' } },
|
|
@@ -409,6 +410,8 @@ async function approveRule(draft, ruleId) {
|
|
|
409
410
|
draftId = data(created)?.draft?.id ?? ''
|
|
410
411
|
const saved = await api('PATCH', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, { doc: ontologyDoc(), expectedRev: 1 }, token)
|
|
411
412
|
check('M1.1', '本体起草(活体校验+绑定通过)', created.status === 200 && saved.status === 200 && data(saved)?.validation?.ok === true, `saved=${saved.status} issues=${JSON.stringify((data(saved)?.validation?.issues ?? []).filter(i => i.severity === 'error').slice(0, 2))}`)
|
|
413
|
+
const detail0 = data(await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, undefined, token))
|
|
414
|
+
check('M1.1b', '本体描述可读(用户理解模型代表什么)', String(detail0?.doc?.description ?? '').includes('膜厚闭环控制本体'), String(detail0?.doc?.description ?? '').slice(0, 60))
|
|
412
415
|
await approveRule(draftId, 'R-BOUND')
|
|
413
416
|
await approveRule(draftId, 'R-GUARD')
|
|
414
417
|
const pub1 = await api('POST', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/publish`, {}, token)
|
|
@@ -427,6 +430,21 @@ async function approveRule(draft, ruleId) {
|
|
|
427
430
|
await approveRule(draftId, 'R-GUARD')
|
|
428
431
|
const pub2 = await api('POST', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/publish`, {}, token)
|
|
429
432
|
check('M1.3', '管理者修正规则窗 → v2 发布', pub2.status === 200 && data(pub2)?.version?.version === 2, `saved=${saved2.status}/${errCode(saved2)} pub=${pub2.status}/${errCode(pub2)}`)
|
|
433
|
+
const messy = ontologyDoc()
|
|
434
|
+
messy.description = ''
|
|
435
|
+
for (const e of messy.entities) e.description = ''
|
|
436
|
+
for (const r of messy.rules) { r.description = ''; r.scope.lineId = '' }
|
|
437
|
+
for (const b of messy.bindings) b.scope = 'global'
|
|
438
|
+
const createFix = await invokeTool('ontology_draft_create', { ontology_id: `${ONT}-fix`, line_id: line.id, name: `修复验收-${TAG}` })
|
|
439
|
+
const createFixText = String(createFix?.data?.text ?? createFix?.data?.result?.text ?? createFix?.text ?? '')
|
|
440
|
+
const draft3 = (createFixText.match(/已创建草稿\s+(\S+?)\(/) ?? [])[1] ?? ''
|
|
441
|
+
const savedMessy = createFix ? await api('PATCH', `/api/workshop/ontology/drafts/${encodeURIComponent(draft3)}`, { doc: messy, expectedRev: 1 }, token) : { status: 0 }
|
|
442
|
+
const fixRes = await invokeTool('ontology_draft_autofix', { draft_id: draft3 })
|
|
443
|
+
const fixText = String(fixRes?.data?.text ?? fixRes?.data?.result?.text ?? fixRes?.text ?? JSON.stringify(fixRes ?? {}))
|
|
444
|
+
const fixErr = Boolean(fixRes?.isError ?? fixRes?.data?.isError)
|
|
445
|
+
check('M1.5', 'Agent 工具 ontology_draft_autofix:自动修复并落库', !fixErr && /自动修复 \d+ 项/.test(fixText), fixText.slice(0, 180))
|
|
446
|
+
const detail3 = data(await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draft3)}`, undefined, token))
|
|
447
|
+
check('M1.6', '修复后:描述/作用域已补齐且校验通过', Boolean(detail3?.doc?.description) && detail3?.validation?.ok === true && (detail3?.doc?.bindings ?? []).every(b => String(b.scope).startsWith('line:')), `desc=${String(detail3?.doc?.description ?? '').slice(0, 40)} savedMessy=${savedMessy.status}`)
|
|
430
448
|
const cmp = await api('GET', `/api/workshop/ontology/versions/${encodeURIComponent(ONT)}/compare?from=1&to=2`, undefined, token)
|
|
431
449
|
const changed = data(cmp)?.rules?.changed ?? []
|
|
432
450
|
check('M1.4', '四段 diff 反映管理者意志(R-BOUND changed)', cmp.status === 200 && changed.some(c => String(typeof c === 'string' ? c : (c.id ?? c.ruleId ?? '')).includes('R-BOUND')), JSON.stringify(changed).slice(0, 200))
|
|
@@ -547,8 +565,8 @@ async function trainOnce(modelName) {
|
|
|
547
565
|
const model = (data(models)?.models ?? []).find(m => m.id === (job?.modelId ?? ''))
|
|
548
566
|
return { datasetId, rowCount: data(ds)?.rowCount ?? 0, jobId, job, modelId: job?.modelId ?? '', artifactHash: model?.artifactHash ?? '', eligOk }
|
|
549
567
|
}
|
|
550
|
-
async function adoptRound(modelId, reason) {
|
|
551
|
-
const adoptInvoke = invokeTool('optimizer_profile_propose', { model_id: modelId, reason }, 300_000)
|
|
568
|
+
async function adoptRound(modelId, reason, description) {
|
|
569
|
+
const adoptInvoke = invokeTool('optimizer_profile_propose', { model_id: modelId, reason, profile_description: description }, 300_000)
|
|
552
570
|
let card = null
|
|
553
571
|
for (let i = 0; i < 60; i++) {
|
|
554
572
|
await sleep(500)
|
|
@@ -580,6 +598,9 @@ let round1RowCount
|
|
|
580
598
|
trainedAId = ra.modelId
|
|
581
599
|
trainedAHash = ra.artifactHash
|
|
582
600
|
round1RowCount = ra.rowCount
|
|
601
|
+
const annotate = await invokeTool('aml_model_annotate', { model_id: ra.modelId, label: `膜厚模型A-${TAG}`, description: '产线A 膜厚预测:线性状态空间,适配保压/线速工况' })
|
|
602
|
+
const annotateText = toolText(annotate)
|
|
603
|
+
check('M3.0', 'Agent 工具 aml_model_annotate:补模型名称/描述', !toolErr(annotate) && annotateText.includes('人读身份已更新'), annotateText.slice(0, 140))
|
|
583
604
|
check('M3.1', '第 1 轮训练 done + 模型登记 + 优化资格(artifactHash)', ra.job?.status === 'done' && ra.eligOk && trainedAId && trainedAHash.length === 64, `status=${ra.job?.status} model=${trainedAId} rows=${ra.rowCount} err=${String(ra.job?.error ?? '').slice(0, 100)}`)
|
|
584
605
|
|
|
585
606
|
const profileBody = {
|
|
@@ -608,7 +629,7 @@ let round1RowCount
|
|
|
608
629
|
trainedBHash = rb.artifactHash
|
|
609
630
|
check('M3.5', '第 2 轮训练 done + 资格(数据集不缩水,工件不同)', rb.job?.status === 'done' && rb.eligOk && trainedBId && rb.rowCount >= round1RowCount && trainedBHash !== trainedAHash, `status=${rb.job?.status} rows ${round1RowCount}→${rb.rowCount} hashDiff=${trainedAHash !== trainedBHash}`)
|
|
610
631
|
|
|
611
|
-
const adopt1 = await adoptRound(trainedBId, '模型进化第 1 轮采纳:换上新训练模型 B')
|
|
632
|
+
const adopt1 = await adoptRound(trainedBId, '模型进化第 1 轮采纳:换上新训练模型 B', '产线A 膜厚闭环:线性 MPC(采纳模型B,提升 rollout 精度)')
|
|
612
633
|
check('M3.6', '采纳卡挂出(optimizer-profile:<id>@<v>)', Boolean(adopt1.card), `nodeId=${adopt1.card?.nodeId ?? 'none'}`)
|
|
613
634
|
check('M3.7', 'HITL 批准 → 单一咽喉发布+重绑', adopt1.dec.status === 200 && (JSON.stringify(adopt1.dec).includes('published') || JSON.stringify(adopt1.dec).includes('已发布')), JSON.stringify(adopt1.dec).slice(0, 300))
|
|
614
635
|
const adoptStr1 = String(adopt1.adoptText?.data?.text ?? adopt1.adoptText?.data?.result?.text ?? adopt1.adoptText?.text ?? JSON.stringify(adopt1.adoptText)).slice(0, 240)
|
|
@@ -620,6 +641,7 @@ let round1RowCount
|
|
|
620
641
|
check('M3.9', '绑定自动重绑到采纳版本(revision+1)', Boolean(rebound1) && Number(rebound1?.revision) >= 1, `versions=[${binds1.map(b => b.profileVersionNumber).join(',')}] card=v${cardV1} rev=${rebound1?.revision}`)
|
|
621
642
|
const profs1 = JSON.stringify(data(await api('GET', `/api/workshop/optimization/profiles?limit=50`, undefined, token)) ?? {})
|
|
622
643
|
check('M3.10', '已发布 Profile v2 携带新模型工件 B', profs1.includes(trainedBId), `len=${profs1.length}`)
|
|
644
|
+
check('M3.10b', 'Profile 描述由 Agent 提议写入并落版本台账', profs1.includes('产线A 膜厚闭环:线性 MPC(采纳模型B'), '')
|
|
623
645
|
writeFreshTail()
|
|
624
646
|
const solve1 = await api('POST', '/api/workshop/optimization/solve', { agentInstanceId: leadAgentIdOuter, bindingId: rebound1?.id }, token)
|
|
625
647
|
check('M3.11', '新模型 B solve optimal', solve1.status === 200 && data(solve1)?.result?.status === 'optimal', `status=${data(solve1)?.result?.status} http=${solve1.status} msg=${String(solve1.message ?? '').slice(0, 120)}`)
|
|
@@ -632,7 +654,7 @@ console.log('\n=== M4 模型进化第 2 轮(持续迭代) ===')
|
|
|
632
654
|
trainedCHash = rc.artifactHash
|
|
633
655
|
check('M4.1', '第 3 次训练 done + 资格(反馈持续积累)', rc.job?.status === 'done' && rc.eligOk && trainedCId && trainedCHash.length === 64, `status=${rc.job?.status} model=${trainedCId} rows=${rc.rowCount}`)
|
|
634
656
|
|
|
635
|
-
const adopt2 = await adoptRound(trainedCId, '模型进化第 2 轮采纳:持续迭代换新模型 C')
|
|
657
|
+
const adopt2 = await adoptRound(trainedCId, '模型进化第 2 轮采纳:持续迭代换新模型 C', '产线A 膜厚闭环:线性 MPC(采纳模型C,持续迭代)')
|
|
636
658
|
check('M4.2', '第 2 轮采纳卡挂出+HITL 批准', Boolean(adopt2.card) && adopt2.dec.status === 200, `nodeId=${adopt2.card?.nodeId ?? 'none'} dec=${adopt2.dec.status}`)
|
|
637
659
|
const adoptStr2 = String(adopt2.adoptText?.data?.text ?? adopt2.adoptText?.data?.result?.text ?? adopt2.adoptText?.text ?? JSON.stringify(adopt2.adoptText)).slice(0, 240)
|
|
638
660
|
check('M4.3', '第 2 轮工具回执:采纳完成', adoptStr2.includes('模型采纳完成'), adoptStr2)
|
|
@@ -687,17 +709,49 @@ process.env.AW_BASE = BASE
|
|
|
687
709
|
const targets = [['/optimizer', 'optimizer'], ['/aml', 'aml'], ['/ontology', 'ontology']]
|
|
688
710
|
let allOk = true
|
|
689
711
|
const detail = []
|
|
712
|
+
const bodies = {}
|
|
690
713
|
for (const [path, name] of targets) {
|
|
691
714
|
const errsBefore = pageErrors.length
|
|
692
715
|
await gotoReady(page, path, { wait: 2500 })
|
|
693
716
|
await sleep(800)
|
|
694
717
|
const bodyLen = await page.evaluate(() => (document.body.textContent ?? '').length)
|
|
718
|
+
bodies[name] = await page.evaluate(() => document.body.textContent ?? '')
|
|
695
719
|
const ok = pageErrors.length === errsBefore && bodyLen > 400
|
|
696
720
|
detail.push(`${name}:len=${bodyLen},errs=${pageErrors.length - errsBefore}`)
|
|
697
721
|
if (!ok) allOk = false
|
|
698
722
|
await shot(`page-${name}`)
|
|
699
723
|
}
|
|
700
724
|
check('M6.1', '管理者三台(/optimizer /aml /ontology)渲染无错', allOk, detail.join(' '))
|
|
725
|
+
// 数据异步加载:轮询等待关键文案(最多 10s),并切到 Profile tab
|
|
726
|
+
const waitText = async (needle, timeoutMs = 10_000) => {
|
|
727
|
+
const t0 = Date.now()
|
|
728
|
+
while (Date.now() - t0 < timeoutMs) {
|
|
729
|
+
const hit = await page.evaluate(n => (document.body.textContent ?? '').includes(n), needle)
|
|
730
|
+
if (hit) return true
|
|
731
|
+
await sleep(500)
|
|
732
|
+
}
|
|
733
|
+
return false
|
|
734
|
+
}
|
|
735
|
+
await gotoReady(page, '/optimizer', { wait: 2500 })
|
|
736
|
+
await page.evaluate(() => {
|
|
737
|
+
const btn = Array.from(document.querySelectorAll('button')).find(b => (b.textContent || '').includes('Profile'))
|
|
738
|
+
if (btn) btn.click()
|
|
739
|
+
})
|
|
740
|
+
await sleep(600)
|
|
741
|
+
const profileDescVisible = await waitText('产线A 膜厚闭环')
|
|
742
|
+
check('M6.3', 'UI:Profile 描述在 /optimizer 台账可见', profileDescVisible)
|
|
743
|
+
await shot('page-optimizer-profile')
|
|
744
|
+
|
|
745
|
+
await gotoReady(page, '/aml', { wait: 2500 })
|
|
746
|
+
const amlDescVisible = await waitText('产线A 膜厚预测', 12_000)
|
|
747
|
+
check('M6.4', 'UI:模型描述在 /aml 台账可见', amlDescVisible)
|
|
748
|
+
await shot('page-aml-models')
|
|
749
|
+
|
|
750
|
+
await gotoReady(page, '/ontology', { wait: 2500 })
|
|
751
|
+
const ontoDescVisible = (await waitText('膜厚闭环控制本体', 6000)) || (await waitText('(产线 ln-', 4000))
|
|
752
|
+
const fixBtnVisible = await page.evaluate(() => (document.body.textContent ?? '').includes('自动修复'))
|
|
753
|
+
check('M6.5', 'UI:本体描述与「自动修复」入口在 /ontology 可见', ontoDescVisible && fixBtnVisible, `desc=${ontoDescVisible} fixBtn=${fixBtnVisible}`)
|
|
754
|
+
await shot('page-ontology-desc')
|
|
701
755
|
check('M6.2', '全程无未捕获 pageerror', pageErrors.length === 0 || pageErrors.every(e => e.includes('dispose')), pageErrors.slice(0, 2).join(';'))
|
|
702
756
|
}
|
|
703
757
|
finally {
|
|
@@ -676,6 +676,79 @@ console.log('\n=== L6 数据分析 ===')
|
|
|
676
676
|
check('L6.2', 'GET /analysis 台账读回', list.status === 200 && JSON.stringify(data(list) ?? list).includes(`本体验收分析-${TAG}`), `status=${list.status} body=${JSON.stringify(list).slice(0, 260)}`)
|
|
677
677
|
}
|
|
678
678
|
|
|
679
|
+
// ════ ON16 邻接查询 REST(已发布面 + 草稿面) ════
|
|
680
|
+
console.log('\n=== ON16 邻接查询 REST ===')
|
|
681
|
+
{
|
|
682
|
+
const base = `/api/workshop/ontology/scene?lineId=${encodeURIComponent(line.id)}`
|
|
683
|
+
const one = await api('GET', `${base}&entity=pv.melt_pressure&hops=1`, undefined, token)
|
|
684
|
+
const oneSub = data(one)?.subgraph
|
|
685
|
+
check('ON16.1', 'GET /scene?entity= 返回子图(center+nodes+edges)', one.status === 200
|
|
686
|
+
&& oneSub?.center?.key === 'pv.melt_pressure'
|
|
687
|
+
&& oneSub?.nodes?.length === 2
|
|
688
|
+
&& oneSub?.edges?.length === 1
|
|
689
|
+
&& oneSub?.edges?.[0]?.direction === 'out', JSON.stringify(oneSub && { nodes: oneSub.nodes, edges: oneSub.edges }))
|
|
690
|
+
const two = await api('GET', `${base}&entity=pv.melt_pressure&hops=2`, undefined, token)
|
|
691
|
+
const twoSub = data(two)?.subgraph
|
|
692
|
+
const speed = twoSub?.nodes?.find(n => n.key === 'st.line_speed')
|
|
693
|
+
const rel2 = twoSub?.edges?.find(e => e.id === 'rel-2')
|
|
694
|
+
check('ON16.2', 'hops=2 出现间接节点 st.line_speed@2 与 rel-2(hop2/in)', speed?.hop === 2 && rel2?.hop === 2 && rel2?.direction === 'in',
|
|
695
|
+
JSON.stringify({ speed, rel2 }))
|
|
696
|
+
const noEntity = await api('GET', `${base}&hops=2&direction=out&kinds=influences`, undefined, token)
|
|
697
|
+
const plain = await api('GET', base, undefined, token)
|
|
698
|
+
check('ON16.3', '无 entity 时新参数被忽略:与历史全图响应完全一致',
|
|
699
|
+
noEntity.status === plain.status && JSON.stringify(data(noEntity)) === JSON.stringify(data(plain)),
|
|
700
|
+
`status=${noEntity.status}/${plain.status}`)
|
|
701
|
+
const keys = Object.keys(data(plain)?.graph ?? {}).join(',')
|
|
702
|
+
check('ON16.4', '无 entity 的 graph 顶层结构不变', keys === 'ontologyId,version,lineId,entities,relations,rules,guards', keys)
|
|
703
|
+
const badHops = await api('GET', `${base}&entity=pv.melt_pressure&hops=4`, undefined, token)
|
|
704
|
+
check('ON16.5', 'hops 越界 → 422 ONTOLOGY_SUBGRAPH_HOPS_INVALID',
|
|
705
|
+
badHops.status === 422 && String(data(badHops)?.code ?? badHops.code ?? '').includes('HOPS_INVALID'), JSON.stringify(badHops).slice(0, 160))
|
|
706
|
+
const ghost = await api('GET', `${base}&entity=ghost.key`, undefined, token)
|
|
707
|
+
check('ON16.6', '未知实体 → 404 ONTOLOGY_SUBGRAPH_ENTITY_NOT_FOUND', ghost.status === 404, `status=${ghost.status}`)
|
|
708
|
+
const draftQuery = `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/subgraph?entity=pv.melt_pressure&hops=1`
|
|
709
|
+
const draftSub = await api('GET', draftQuery, undefined, token)
|
|
710
|
+
const draftBody = data(draftSub)?.subgraph
|
|
711
|
+
check('ON16.7', '草稿子图端点可用(UI 图与抽屉同源)', draftSub.status === 200
|
|
712
|
+
&& draftBody?.center?.key === 'pv.melt_pressure'
|
|
713
|
+
&& draftBody?.nodes?.length === 2, JSON.stringify(draftBody).slice(0, 200))
|
|
714
|
+
const draftBad = await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/subgraph`, undefined, token)
|
|
715
|
+
check('ON16.8', '草稿子图缺 entity → 422 ONTOLOGY_ENTITY_REQUIRED', draftBad.status === 422, `status=${draftBad.status}`)
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// ════ ON17 Agent 只读工具:ontology_node_neighbors ════
|
|
719
|
+
console.log('\n=== ON17 Agent 邻接工具 ===')
|
|
720
|
+
{
|
|
721
|
+
const invokeNeighbors = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
722
|
+
agentId: leadAgentIdOuter,
|
|
723
|
+
tool: 'ontology_node_neighbors',
|
|
724
|
+
args: { line_id: line.id, entity_key: 'pv.melt_pressure', hops: 1 },
|
|
725
|
+
}, token)
|
|
726
|
+
const text1 = String(data(invokeNeighbors)?.result?.text ?? '')
|
|
727
|
+
check('ON17.1', '工具 hops=1 返回节点/边明细', invokeNeighbors.status === 200
|
|
728
|
+
&& data(invokeNeighbors)?.result?.isError !== true
|
|
729
|
+
&& text1.includes('nodes=2 edges=1')
|
|
730
|
+
&& text1.includes('pv.melt_pressure')
|
|
731
|
+
&& text1.includes('cv.thickness')
|
|
732
|
+
&& text1.includes('rel-1'), text1.slice(0, 240))
|
|
733
|
+
const invokeTwo = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
734
|
+
agentId: leadAgentIdOuter,
|
|
735
|
+
tool: 'ontology_node_neighbors',
|
|
736
|
+
args: { line_id: line.id, entity_key: 'pv.melt_pressure', hops: 2 },
|
|
737
|
+
}, token)
|
|
738
|
+
const text2 = String(data(invokeTwo)?.result?.text ?? '')
|
|
739
|
+
check('ON17.2', '工具 hops=2 显示间接节点与 hop 标注',
|
|
740
|
+
text2.includes('st.line_speed hop=2') && text2.includes('rel-2') && text2.includes('hop=2'),
|
|
741
|
+
text2.slice(0, 260))
|
|
742
|
+
const outside = await api('POST', '/api/workshop/agent-tools/invoke', {
|
|
743
|
+
agentId: leadAgentIdOuter,
|
|
744
|
+
tool: 'ontology_node_neighbors',
|
|
745
|
+
args: { line_id: 'ln-not-in-scope', entity_key: 'pv.melt_pressure' },
|
|
746
|
+
}, token)
|
|
747
|
+
const outsideText = String(data(outside)?.result?.text ?? '')
|
|
748
|
+
check('ON17.3', '跨线读取被拦截(引用校验/作用域如实回执)',
|
|
749
|
+
data(outside)?.result?.isError === true && outsideText.includes('不在你的可读范围'), outsideText.slice(0, 160))
|
|
750
|
+
}
|
|
751
|
+
|
|
679
752
|
// ════ L7 前端渲染走查 ════
|
|
680
753
|
console.log('\n=== L7 前端渲染 ===')
|
|
681
754
|
process.env.AW_BASE = BASE
|
|
@@ -695,8 +768,70 @@ process.env.AW_BASE = BASE
|
|
|
695
768
|
check('L7.2', '/ontology 六 tab 渲染', tabs.length === 6, tabs.join('|'))
|
|
696
769
|
await shot('ontology-overview')
|
|
697
770
|
|
|
698
|
-
|
|
699
|
-
|
|
771
|
+
// graph tab 默认 SVG:节点/边数必须与当前草稿一致(图与表格同源)
|
|
772
|
+
await page.evaluate(() => {
|
|
773
|
+
const btn = Array.from(document.querySelectorAll('.tabs .pill-btn'))[1]
|
|
774
|
+
if (btn) btn.click()
|
|
775
|
+
})
|
|
776
|
+
await sleep(1600)
|
|
777
|
+
const graphInfo = await page.evaluate(() => {
|
|
778
|
+
const root = document.querySelector('[data-testid="ontology-graph"]')
|
|
779
|
+
return {
|
|
780
|
+
nodes: root ? root.querySelectorAll('[data-node-key]').length : -1,
|
|
781
|
+
edges: root ? root.querySelectorAll('[data-edge-id]').length : -1,
|
|
782
|
+
}
|
|
783
|
+
})
|
|
784
|
+
const draftDetail = await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, undefined, token)
|
|
785
|
+
const draftDoc = data(draftDetail)?.doc ?? {}
|
|
786
|
+
const expectedNodes = (draftDoc.entities ?? []).length
|
|
787
|
+
const expectedEdges = (draftDoc.relations ?? []).length
|
|
788
|
+
check('L7.3a', 'graph tab 渲染 SVG 节点/边且与草稿一致',
|
|
789
|
+
graphInfo.nodes === expectedNodes && graphInfo.edges === expectedEdges && graphInfo.nodes > 0,
|
|
790
|
+
`nodes=${graphInfo.nodes}/${expectedNodes} edges=${graphInfo.edges}/${expectedEdges}`)
|
|
791
|
+
await shot('ontology-graph')
|
|
792
|
+
|
|
793
|
+
// 点击节点 → 抽屉:1 跳邻接,再切 2 跳看间接关联
|
|
794
|
+
await page.click('[data-node-key="pv.melt_pressure"]')
|
|
795
|
+
await sleep(1600)
|
|
796
|
+
const drawer1 = await page.evaluate(() => ({
|
|
797
|
+
open: Boolean(document.querySelector('[data-testid="node-drawer"]')),
|
|
798
|
+
neighbors: Array.from(document.querySelectorAll('[data-neighbor-key]')).map(el => el.getAttribute('data-neighbor-key')),
|
|
799
|
+
edges: Array.from(document.querySelectorAll('[data-testid="node-drawer"] [data-edge-id]')).map(el => el.getAttribute('data-edge-id')),
|
|
800
|
+
}))
|
|
801
|
+
check('L7.3b', '点击节点弹出抽屉并列出直接邻接',
|
|
802
|
+
drawer1.open && drawer1.neighbors.includes('cv.thickness') && drawer1.edges.includes('rel-1'),
|
|
803
|
+
JSON.stringify(drawer1))
|
|
804
|
+
await shot('ontology-drawer')
|
|
805
|
+
await page.evaluate(() => {
|
|
806
|
+
const seg = Array.from(document.querySelectorAll('.ant-segmented-item')).find(el => (el.textContent || '').includes('间接关联'))
|
|
807
|
+
if (seg) seg.click()
|
|
808
|
+
})
|
|
809
|
+
await sleep(1600)
|
|
810
|
+
const drawer2 = await page.evaluate(() => ({
|
|
811
|
+
neighbors: Array.from(document.querySelectorAll('[data-neighbor-key]')).map(el => el.getAttribute('data-neighbor-key')),
|
|
812
|
+
edges: Array.from(document.querySelectorAll('[data-testid="node-drawer"] [data-edge-id]')).map(el => el.getAttribute('data-edge-id')),
|
|
813
|
+
}))
|
|
814
|
+
check('L7.3b2', '抽屉切 2 跳后出现间接节点 st.line_speed 与 rel-2',
|
|
815
|
+
drawer2.neighbors.includes('st.line_speed') && drawer2.edges.includes('rel-2'), JSON.stringify(drawer2))
|
|
816
|
+
await shot('ontology-drawer-hops2')
|
|
817
|
+
await page.keyboard.press('Escape').catch(() => {})
|
|
818
|
+
await sleep(600)
|
|
819
|
+
|
|
820
|
+
// 切到表视图:实体表与关系表都要有行
|
|
821
|
+
await page.evaluate(() => {
|
|
822
|
+
const seg = Array.from(document.querySelectorAll('.ant-segmented-item')).find(el => (el.textContent || '').trim() === '表')
|
|
823
|
+
if (seg) seg.click()
|
|
824
|
+
})
|
|
825
|
+
await sleep(1400)
|
|
826
|
+
const tableInfo = await page.evaluate(() => ({
|
|
827
|
+
entityRows: document.querySelectorAll('[data-testid="entity-table"] .ant-table-tbody tr.ant-table-row').length,
|
|
828
|
+
relationRows: document.querySelectorAll('[data-testid="relation-table"] .ant-table-tbody tr.ant-table-row').length,
|
|
829
|
+
}))
|
|
830
|
+
check('L7.3c', '切到表视图:实体表与关系表均有行', tableInfo.entityRows > 0 && tableInfo.relationRows > 0, JSON.stringify(tableInfo))
|
|
831
|
+
await shot('ontology-graph-table')
|
|
832
|
+
|
|
833
|
+
const tabKeys = ['rules', 'bindings', 'versions']
|
|
834
|
+
const tabIndex = { rules: 2, bindings: 3, versions: 4 }
|
|
700
835
|
let renderedOk = true
|
|
701
836
|
const renderDetail = []
|
|
702
837
|
for (const key of tabKeys) {
|
|
@@ -713,7 +848,7 @@ process.env.AW_BASE = BASE
|
|
|
713
848
|
if (info.rows === 0 && info.empty === 0) renderedOk = false
|
|
714
849
|
await shot(`ontology-${key}`)
|
|
715
850
|
}
|
|
716
|
-
check('L7.
|
|
851
|
+
check('L7.3d', '规则/绑定/版本三 tab 表格渲染非空', renderedOk, renderDetail.join(' '))
|
|
717
852
|
|
|
718
853
|
// 编译预览:真实点击工具栏按钮 → 产物面板 + Rule Trace 表
|
|
719
854
|
await page.evaluate(() => {
|