agentworkshop 0.8.5 → 0.8.6
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.en.json +3 -3
- package/.AgentWorkShop/prompts/host-tools.json +14 -4
- package/.output/.AgentWorkShop/prompts/host-tools.en.json +3 -3
- package/.output/.AgentWorkShop/prompts/host-tools.json +14 -4
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{U_n8pryv2.js → 7op-BMk82.js} +1 -1
- package/.output/public/_nuxt/{zWZ26UWi.js → B1SIgyrl.js} +1 -1
- package/.output/public/_nuxt/{C4tXwpSt.js → BA2lmfW4.js} +1 -1
- package/.output/public/_nuxt/{EJkmXP432.js → BDXQqSkl2.js} +1 -1
- package/.output/public/_nuxt/{CY_7u1ST2.js → BI9jj13f2.js} +1 -1
- package/.output/public/_nuxt/{CGf9neEK2.js → BiXqyYNw2.js} +1 -1
- package/.output/public/_nuxt/{D9GoOkyP2.js → BlOm8JIs2.js} +1 -1
- package/.output/public/_nuxt/{CQ31GiJU2.js → BoXKUOiN2.js} +1 -1
- package/.output/public/_nuxt/{DZzbCFY2.js → BuLoPmcf.js} +1 -1
- package/.output/public/_nuxt/{D9ppMCbw.js → BwOK42JQ.js} +1 -1
- package/.output/public/_nuxt/{CZJ5cw6r2.js → C1RMfPoB2.js} +1 -1
- package/.output/public/_nuxt/{CGviZq4E.js → COfo_Bg3.js} +1 -1
- package/.output/public/_nuxt/CTGJHZ8X2.js +1 -0
- package/.output/public/_nuxt/{SgsmmrsZ.js → CY2NkFvI.js} +1 -1
- package/.output/public/_nuxt/{B4GOTVfN.js → C_4mzQ5X.js} +1 -1
- package/.output/public/_nuxt/{DGmFHb7m.js → CdvMP3lv.js} +1 -1
- package/.output/public/_nuxt/{iqxZGXsY.js → CooauJ7D.js} +1 -1
- package/.output/public/_nuxt/{C3vxePED.js → D1eVi1zr.js} +1 -1
- package/.output/public/_nuxt/{DnuJ66Jy.js → D6PUmBb0.js} +1 -1
- package/.output/public/_nuxt/{BBhroEeN.js → DC8sMA36.js} +1 -1
- package/.output/public/_nuxt/{DOUuGOQR2.js → DDHh85c42.js} +1 -1
- package/.output/public/_nuxt/{Cy_HDgSl.js → DDXOfmo2.js} +2 -2
- package/.output/public/_nuxt/{Cr2xJ_CY.js → DMFwLxfu.js} +1 -1
- package/.output/public/_nuxt/{BZg_MIK42.js → DoprKJ5a2.js} +1 -1
- package/.output/public/_nuxt/{BzBBEE-o2.js → Dr1FVeQG2.js} +1 -1
- package/.output/public/_nuxt/{W0sNnJQh.js → DtnsTW7e.js} +1 -1
- package/.output/public/_nuxt/{gUYi1hLJ2.js → DxDqd6T42.js} +1 -1
- package/.output/public/_nuxt/{B0UUODeh.js → DzU3zEKX.js} +1 -1
- package/.output/public/_nuxt/{BkO5WdX5.js → EgO70wrE.js} +1 -1
- package/.output/public/_nuxt/{7OZQiw002.js → HJKu4eEV2.js} +1 -1
- package/.output/public/_nuxt/{ChF6qLpY2.js → K5Xen0wZ2.js} +1 -1
- package/.output/public/_nuxt/{CNrRZmSx2.js → Rb4o4o-82.js} +1 -1
- package/.output/public/_nuxt/{BqBTlfiz.js → Tf6SJSDj.js} +1 -1
- package/.output/public/_nuxt/{DJaGVY4v2.js → ZzOyoXex2.js} +1 -1
- package/.output/public/_nuxt/{PbzVdCTA2.js → azOGy_tU2.js} +1 -1
- package/.output/public/_nuxt/{D1thFC3z.js → be-4wyTo.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/593b65bd-cf1d-4b7f-a993-57e939c38f36.json +1 -0
- package/.output/public/_nuxt/{8b9CKi6F.js → dcjPjLPI.js} +1 -1
- package/.output/public/_nuxt/{ae2-5ZPt.js → h-Fn7pRD.js} +1 -1
- package/.output/public/_nuxt/{-gy9k_TE2.js → hyLdZsOd2.js} +1 -1
- package/.output/public/_nuxt/{BHxG41IQ2.js → o8sYG6xx2.js} +1 -1
- package/.output/server/chunks/_/access.mjs +1 -1
- package/.output/server/chunks/_/agent-dto.mjs +26 -0
- package/.output/server/chunks/_/agent-dto.mjs.map +1 -0
- package/.output/server/chunks/_/data-export.mjs +6 -6
- package/.output/server/chunks/_/data-query.mjs +3 -3
- package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
- package/.output/server/chunks/_/features.mjs +5 -5
- package/.output/server/chunks/_/golden.mjs +3 -3
- package/.output/server/chunks/_/harness-spawn-policy.mjs +77 -0
- package/.output/server/chunks/_/harness-spawn-policy.mjs.map +1 -0
- package/.output/server/chunks/_/index.mjs +1 -1
- package/.output/server/chunks/_/line-scope.mjs +32 -0
- package/.output/server/chunks/_/line-scope.mjs.map +1 -0
- package/.output/server/chunks/_/mes-console.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +2429 -1726
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/ocap.mjs +1 -1
- package/.output/server/chunks/_/rest-auth.mjs +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/daq-CdxcfY_G.mjs +1 -1
- package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +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/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/agent-tools/index.post.mjs +17 -9
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +3 -0
- package/.output/server/chunks/routes/api/workshop/agents/_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/channel-templates/_id_.patch.mjs +6 -0
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +5 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +5 -2
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +7 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +3 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +8 -6
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +29 -49
- package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +6 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +4 -2
- package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +14 -5
- package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +7 -4
- package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +6 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +7 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +7 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/mes-hook-test.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/mes-test-read.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +4 -2
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +5 -2
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs +7 -3
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +8 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +7 -4
- package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/commonality.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/vm/predict.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/exp/confirmations/_id/decide.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/exp/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.post.mjs +2 -0
- package/.output/server/chunks/routes/api/workshop/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +8 -3
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/datasets.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs +1 -1
- 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 +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.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 +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.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 +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +4 -2
- package/README.md +9 -2
- package/config.yml +1 -1
- package/docker-compose.yml +4 -2
- 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/package.json +1 -1
- package/scripts/_audit/_live-mqtt-e2e-20261028.mjs +219 -0
- package/scripts/_audit/prompt-injection-probe.mts +76 -0
- package/scripts/api-live-e2e.mjs +9 -3
- package/scripts/e2e-multiexpert-remediation-real.mjs +453 -0
- package/scripts/e2e-node-binding-3mode-real.mjs +697 -0
- package/scripts/e2e-node-binding-authz.mjs +332 -0
- package/scripts/security-acceptance.mjs +218 -0
- package/server/api/workshop/agent-tools/bindings/index.post.ts +33 -17
- package/server/api/workshop/agents/[id].patch.ts +3 -0
- package/server/api/workshop/agents/index.post.ts +3 -0
- package/server/api/workshop/channel-templates/[id].patch.ts +5 -0
- package/server/api/workshop/channel-templates/index.post.ts +6 -0
- package/server/api/workshop/channels/[id]/agents/[agentId].patch.ts +5 -0
- package/server/api/workshop/channels/[id]/agents/index.get.ts +8 -2
- package/server/api/workshop/channels/[id]/agents/index.post.ts +7 -0
- package/server/api/workshop/channels/[id]/index.get.ts +10 -4
- package/server/api/workshop/channels.post.ts +3 -0
- package/server/api/workshop/daq/[id]/ingest.post.ts +26 -22
- package/server/api/workshop/daq/[id].patch.ts +8 -0
- package/server/api/workshop/daq/alarms.get.ts +18 -16
- package/server/api/workshop/daq/infra/reconnect.post.ts +21 -5
- package/server/api/workshop/daq/test-driver.post.ts +10 -3
- package/server/api/workshop/dcw/[id]/param-ledger.get.ts +7 -1
- package/server/api/workshop/dcw/[id]/read.post.ts +6 -1
- package/server/api/workshop/dcw/[id].patch.ts +49 -40
- package/server/api/workshop/dcw/journal/index.get.ts +7 -3
- package/server/api/workshop/dcw/mes-artifacts/file.get.ts +7 -1
- package/server/api/workshop/dcw/mes-artifacts/index.get.ts +7 -1
- package/server/api/workshop/dcw/optimizations/[id]/series.get.ts +6 -1
- package/server/api/workshop/dcw/optimizations/[id].get.ts +3 -1
- package/server/api/workshop/dcw/optimizations/index.get.ts +6 -3
- package/server/api/workshop/dcw/params/[id]/read.post.ts +22 -17
- package/server/api/workshop/dcw/recipes/[id]/versions.get.ts +20 -14
- package/server/api/workshop/dcw/recipes/[id].delete.ts +33 -25
- package/server/api/workshop/dcw/recipes/index.get.ts +17 -12
- package/server/api/workshop/dcw/runs/[id]/close.post.ts +21 -15
- package/server/api/workshop/dcw/test-driver.post.ts +21 -16
- package/server/api/workshop/ws/hub.ts +2 -1
- package/server/plugins/01-instance-guard.ts +82 -0
- package/server/plugins/daq.ts +40 -8
- package/server/plugins/workshop.ts +12 -0
- package/server/services/workshop/agents/adapters/line-spawn.ts +24 -1
- package/server/services/workshop/agents/agent-dto.ts +54 -0
- package/server/services/workshop/agents/harness-spawn-policy.ts +114 -0
- package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +22 -0
- package/server/services/workshop/agents/host-tool-bridge/index.ts +1 -1
- package/server/services/workshop/agents/host-tool-bridge/per-agent.ts +17 -3
- package/server/services/workshop/agents/host-tool-bridge/tools/tasks.ts +1 -1
- package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +5 -1
- package/server/services/workshop/agents/industrial/dcw-tools.ts +6 -2
- package/server/services/workshop/agents/industrial/ops-tools.ts +54 -12
- package/server/services/workshop/agents/industrial/recipe-gate.ts +68 -15
- package/server/services/workshop/agents/industrial/tool-verify-legacy-specs.ts +2 -2
- package/server/services/workshop/agents/industrial/tool-verify.ts +31 -2
- package/server/services/workshop/agents/node-bindings.repo.ts +4 -3
- package/server/services/workshop/agents/node-delegation.ts +49 -4
- package/server/services/workshop/agents/tool-approvals.ts +23 -0
- package/server/services/workshop/agents/tool-reference-spec.ts +3 -0
- package/server/services/workshop/daq/bus/mqtt.adapter.ts +12 -0
- package/server/services/workshop/daq/daq-controller/crud.ts +5 -3
- package/server/services/workshop/daq/daq-controller/ingest.ts +23 -0
- package/server/services/workshop/daq/daq-controller/push.ts +24 -3
- package/server/services/workshop/daq/daq-controller/runtime-control.ts +6 -0
- package/server/services/workshop/daq/daq-controller/sweep-alarms.ts +3 -1
- package/server/services/workshop/daq/daq-controller/tsdb-twin.ts +21 -1
- package/server/services/workshop/daq/daq-node.repo.ts +10 -7
- package/server/services/workshop/daq/daq-node.ts +2 -0
- package/server/services/workshop/daq/daq-runtime.ts +10 -2
- package/server/services/workshop/daq/drivers/modbus-tcp.ts +8 -5
- package/server/services/workshop/daq/drivers/registry.ts +5 -4
- package/server/services/workshop/daq/infra.ts +13 -0
- package/server/services/workshop/daq/ingest-policy.ts +24 -1
- package/server/services/workshop/daq/storage/timescale.adapter.ts +42 -3
- package/server/services/workshop/db/database/migrations.ts +83 -68
- package/server/services/workshop/dcw/dcw-controller/crud.ts +27 -2
- package/server/services/workshop/dcw/dcw-controller/lines.ts +14 -3
- package/server/services/workshop/dcw/dcw-controller/recipes.ts +63 -5
- package/server/services/workshop/dcw/dcw-recipe.repo.ts +10 -1
- package/server/services/workshop/dcw/dcw-runtime.ts +37 -14
- package/server/services/workshop/dcw/drivers/shared.ts +62 -6
- package/server/services/workshop/dcw/recipe-op-anchor.ts +28 -0
- package/server/services/workshop/dcw/recipe-rollback-manager/rollback.ts +204 -190
- package/server/services/workshop/dcw/recipe-rollback-manager/sweep.ts +97 -77
- package/server/services/workshop/line-scope.ts +80 -0
- package/server/services/workshop/optimization/dispatch.service.ts +18 -2
- package/server/services/workshop/permissions.ts +2 -0
- package/server/services/workshop/runtime/agent-runtime/message.ts +17 -0
- package/server/services/workshop/runtime/agent-runtime/state.ts +9 -3
- package/server/services/workshop/runtime/agent-runtime/types.ts +2 -1
- package/server/services/workshop/runtime/channel-runtime.ts +3 -1
- package/server/services/workshop/runtime/mailbox.ts +6 -3
- package/server/services/workshop/runtime/manager/a2a.ts +4 -2
- package/server/services/workshop/runtime/manager/admin-channel.ts +1 -1
- package/server/services/workshop/runtime/manager/chat.ts +3 -1
- package/server/services/workshop/runtime/manager/host-tools.ts +1 -1
- package/server/services/workshop/runtime/manager/runtime-wiring.ts +31 -19
- package/server/services/workshop/runtime/manager/state.ts +43 -1
- package/server/services/workshop/runtime/permission-scope.ts +21 -0
- package/server/services/workshop/runtime/scheduler-loop/tick.ts +16 -4
- package/server/services/workshop/scene-events.ts +19 -0
- package/shared/daq-protocol.ts +24 -5
- package/shared/dcw-protocol/catalog.ts +4 -4
- package/.output/public/_nuxt/CCI-fwcS2.js +0 -1
- package/.output/public/_nuxt/builds/meta/5cd11284-05bf-4fcd-9a69-56a01c9f56dd.json +0 -1
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 多专家审查整改 · 真实场景验收(2026-10-28)。
|
|
4
|
+
*
|
|
5
|
+
* 真实平台(.output 生产构建)+ 真实 omp 子进程 + 本机 LM Studio Qwen3.5-9B(32k),
|
|
6
|
+
* 单频道、**worker 身份执行**(lead 只存在不派活):
|
|
7
|
+
* R1 AgentChannel 创建(lead + worker 成员)
|
|
8
|
+
* R2 worker 绑定节点(DAQ 观察 + DCW 点位写授权)落库
|
|
9
|
+
* R3 运行时提示词注入:节点语义卡(名称/量程/单步/手动确认)+ 执行模式卡
|
|
10
|
+
* R4 工具注入面按绑定面差异化(recipe_trial 描述含该 worker 的 dcw 节点)
|
|
11
|
+
* R5 任务 COMPLETED(omp + Qwen3.5),工具链 my_industrial_nodes → daq_query → recipe_trial
|
|
12
|
+
* R6 手动模式 HITL:审批卡挂起 → 人工批准 → ACK 设备证实
|
|
13
|
+
* R7 效果:节点值变更、trial 不改配方版本、journal 锚点新增、TSDB 有真实样本
|
|
14
|
+
*
|
|
15
|
+
* 运行:node scripts/e2e-multiexpert-remediation-real.mjs
|
|
16
|
+
* 证据:docs/audit/evidence/2026-10-28-multiexpert-remediation/report.json
|
|
17
|
+
*/
|
|
18
|
+
import { spawn, spawnSync } from 'node:child_process'
|
|
19
|
+
import { existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
20
|
+
import { dirname, join, resolve } from 'node:path'
|
|
21
|
+
import { fileURLToPath } from 'node:url'
|
|
22
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
23
|
+
|
|
24
|
+
const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
25
|
+
const HOME = process.env.AW_ACCEPT_HOME ?? 'D:/tmp/aw-multiexpert-20261028'
|
|
26
|
+
const PORT = Number(process.env.AW_ACCEPT_PORT ?? 3411)
|
|
27
|
+
const BASE = `http://127.0.0.1:${PORT}`
|
|
28
|
+
const MODEL = { provider: 'lm-studio', model: 'qwen3.5-9b-32k', contextTokens: 32768 }
|
|
29
|
+
const EVIDENCE_DIR = join(REPO, 'docs', 'audit', 'evidence', '2026-10-28-multiexpert-remediation')
|
|
30
|
+
const results = []
|
|
31
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
32
|
+
const ok = (id, name, cond, detail = '') => {
|
|
33
|
+
results.push({ id, name, pass: Boolean(cond), detail: String(detail).slice(0, 1200) })
|
|
34
|
+
console.log(`${cond ? '✔' : '✖'} [${id}] ${name}${cond ? '' : ` — ${String(detail).slice(0, 800)}`}`)
|
|
35
|
+
return Boolean(cond)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function stopOwnedInstance() {
|
|
39
|
+
const pidFile = join(HOME, 'server.pid')
|
|
40
|
+
if (!existsSync(pidFile)) return
|
|
41
|
+
const pid = Number(readFileSync(pidFile, 'utf8').trim())
|
|
42
|
+
if (!Number.isInteger(pid) || pid <= 0) return
|
|
43
|
+
try {
|
|
44
|
+
spawnSync('taskkill', ['/PID', String(pid), '/T', '/F'], { windowsHide: true })
|
|
45
|
+
}
|
|
46
|
+
catch { /* 已退出 */ }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function health() {
|
|
50
|
+
try {
|
|
51
|
+
const r = await fetch(`${BASE}/api/health`, { signal: AbortSignal.timeout(2500) })
|
|
52
|
+
if (!r.ok) return null
|
|
53
|
+
return (await r.json())?.data ?? null
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function startInstance() {
|
|
61
|
+
stopOwnedInstance()
|
|
62
|
+
await sleep(1500)
|
|
63
|
+
const running = await health()
|
|
64
|
+
if (running) throw new Error(`端口 ${PORT} 已被非本验收实例占用:${running.app} ${running.version}`)
|
|
65
|
+
if (process.env.AW_ACCEPT_RESET !== '0') {
|
|
66
|
+
if (!/aw-multiexpert/.test(HOME)) throw new Error(`拒绝清理非验收目录:${HOME}`)
|
|
67
|
+
rmSync(HOME, { recursive: true, force: true })
|
|
68
|
+
}
|
|
69
|
+
mkdirSync(HOME, { recursive: true })
|
|
70
|
+
const log = openSync(join(HOME, 'server.log'), 'a')
|
|
71
|
+
const child = spawn(process.execPath, [join(REPO, '.output', 'server', 'index.mjs')], {
|
|
72
|
+
cwd: REPO,
|
|
73
|
+
env: {
|
|
74
|
+
...process.env,
|
|
75
|
+
AW_MODE: 'home',
|
|
76
|
+
AW_HOME: HOME,
|
|
77
|
+
PORT: String(PORT),
|
|
78
|
+
NUXT_SESSION_PASSWORD: 'multiexpert-20261028-session-key-abcdef',
|
|
79
|
+
AW_TRIAL_INTERVAL_MS: '0',
|
|
80
|
+
AW_RATE_LIMIT_OFF: '1',
|
|
81
|
+
NO_PROXY: '127.0.0.1,localhost',
|
|
82
|
+
},
|
|
83
|
+
detached: true,
|
|
84
|
+
stdio: ['ignore', log, log],
|
|
85
|
+
windowsHide: true,
|
|
86
|
+
})
|
|
87
|
+
child.unref()
|
|
88
|
+
writeFileSync(join(HOME, 'server.pid'), String(child.pid))
|
|
89
|
+
for (let i = 0; i < 120; i++) {
|
|
90
|
+
await sleep(1000)
|
|
91
|
+
const h = await health()
|
|
92
|
+
if (h?.workshop === 'ready') return h
|
|
93
|
+
}
|
|
94
|
+
throw new Error('隔离实例未在 120s 内就绪')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let admin = ''
|
|
98
|
+
async function api(method, path, body, token = admin, extraHeaders = {}, timeoutMs = 120_000) {
|
|
99
|
+
const res = await fetch(BASE + path, {
|
|
100
|
+
method,
|
|
101
|
+
headers: {
|
|
102
|
+
...(body !== undefined ? { 'content-type': 'application/json' } : {}),
|
|
103
|
+
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
104
|
+
...extraHeaders,
|
|
105
|
+
},
|
|
106
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
107
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
108
|
+
})
|
|
109
|
+
let json = null
|
|
110
|
+
try {
|
|
111
|
+
json = await res.json()
|
|
112
|
+
}
|
|
113
|
+
catch { /* 非 JSON */ }
|
|
114
|
+
return { status: res.status, ...json }
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const dbPath = join(HOME, 'data', 'workshop.sqlite')
|
|
118
|
+
function agentTokenOf(agentId) {
|
|
119
|
+
const db = new DatabaseSync(dbPath, { readOnly: true })
|
|
120
|
+
try {
|
|
121
|
+
return String(db.prepare('SELECT token FROM channel_agents WHERE id = ?').get(agentId)?.token ?? '')
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
db.close()
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function pendingOf(agentId) {
|
|
129
|
+
const r = await api('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(agentId)}`)
|
|
130
|
+
return (r?.data?.approvals ?? []).filter(a => a.status === 'pending')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function approvalsHistory(agentId) {
|
|
134
|
+
const r = await api('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(agentId)}&scope=history`)
|
|
135
|
+
return r?.data?.approvals ?? []
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function approve(cardId, comment) {
|
|
139
|
+
return api('POST', `/api/workshop/agent-tools/approvals/${cardId}/decide`, { approved: true, comment })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function taskOf(r) {
|
|
143
|
+
return r?.data?.task ?? r?.data ?? null
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function deliverableOf(task) {
|
|
147
|
+
const art = (task?.artifacts ?? []).find(a => a.name === 'deliverable')
|
|
148
|
+
return String(art?.parts?.map(p => p.text ?? '').join('\n') ?? '')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function toolCallsOf(task) {
|
|
152
|
+
return (task?.history ?? [])
|
|
153
|
+
.map(h => String(h?.parts?.map(p => p.text ?? '').join(' ') ?? ''))
|
|
154
|
+
.filter(t => t.includes('🔧'))
|
|
155
|
+
.map(t => t.replace(/\s+/g, ' ').slice(0, 300))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function waitTask(taskId, { timeoutMs = 15 * 60_000, autoApprove = false, onCard = null } = {}) {
|
|
159
|
+
const started = Date.now()
|
|
160
|
+
const cards = []
|
|
161
|
+
let lastState = ''
|
|
162
|
+
while (Date.now() - started < timeoutMs) {
|
|
163
|
+
const r = await api('GET', `/api/workshop/tasks/${taskId}`)
|
|
164
|
+
const task = taskOf(r)
|
|
165
|
+
const state = String(task?.state ?? '')
|
|
166
|
+
if (state !== lastState) {
|
|
167
|
+
lastState = state
|
|
168
|
+
console.log(` · task ${taskId.slice(0, 8)} state=${state}`)
|
|
169
|
+
}
|
|
170
|
+
if (autoApprove && task?.assigneeId) {
|
|
171
|
+
const pending = await pendingOf(String(task.assigneeId))
|
|
172
|
+
for (const card of pending) {
|
|
173
|
+
if (cards.some(c => c.id === card.id)) continue
|
|
174
|
+
cards.push(card)
|
|
175
|
+
if (onCard) onCard(card)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (['COMPLETED', 'FAILED', 'CANCELED', 'CANCELLED'].includes(state)) return { task, cards, timedOut: false }
|
|
179
|
+
await sleep(3000)
|
|
180
|
+
}
|
|
181
|
+
const r = await api('GET', `/api/workshop/tasks/${taskId}`)
|
|
182
|
+
return { task: taskOf(r), cards, timedOut: true }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function submitTask(channelId, title, description, assigneeId) {
|
|
186
|
+
const r = await api('POST', `/api/workshop/channels/${channelId}/tasks`, { title, description, assigneeId })
|
|
187
|
+
const task = taskOf(r)
|
|
188
|
+
if (!task?.id) throw new Error(`任务创建失败: ${JSON.stringify(r).slice(0, 400)}`)
|
|
189
|
+
return task
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const scenarioLine = (name, controlMode, description) =>
|
|
193
|
+
api('POST', '/api/workshop/dcw/lines', { name, simulated: true, controlMode, description }).then(r => r.data.line)
|
|
194
|
+
|
|
195
|
+
const makeDaq = async attrs => (await api('POST', '/api/workshop/daq', {
|
|
196
|
+
driver: 'mock', intervalMs: 1000, enabled: true, publishIntervalMs: 0, ...attrs,
|
|
197
|
+
})).data.node
|
|
198
|
+
|
|
199
|
+
const makeDcw = async attrs => (await api('POST', '/api/workshop/dcw', {
|
|
200
|
+
driver: 'mock', enabled: true, holdIntervalMs: 0, readIntervalMs: 0, writeLockSeconds: 0, stepLimit: 5, ...attrs,
|
|
201
|
+
})).data.node
|
|
202
|
+
|
|
203
|
+
async function remapParam(lineId, nodeId, key, desc) {
|
|
204
|
+
const params = (await api('GET', `/api/workshop/dcw/params?lineId=${lineId}`)).data.params ?? []
|
|
205
|
+
const pm = params.find(p => p.nodeId === nodeId)
|
|
206
|
+
if (!pm) throw new Error(`参数映射不存在: node=${nodeId}`)
|
|
207
|
+
await api('PATCH', `/api/workshop/dcw/params/${pm.id}`, { key, desc, min: 0, max: 100 })
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** 注:本函数创建 lead;worker 另经 /agents 路由加入(worker 才是本轮的作业身份) */
|
|
211
|
+
async function makeChannel(name, lineId, scenarioPrompt, mode, toolNames) {
|
|
212
|
+
const ch = (await api('POST', '/api/workshop/channels', {
|
|
213
|
+
name,
|
|
214
|
+
lineId,
|
|
215
|
+
scenarioPrompt,
|
|
216
|
+
leadAgent: { name: `${name}-线长`, harness: 'omp', config: { rpcMode: 'rpc', args: ['--no-tools'] } },
|
|
217
|
+
})).data
|
|
218
|
+
const channelId = ch?.channelId
|
|
219
|
+
if (!channelId) throw new Error(`频道创建失败: ${JSON.stringify(ch).slice(0, 300)}`)
|
|
220
|
+
await api('PATCH', `/api/workshop/channels/${channelId}`, { llm: { provider: MODEL.provider, model: MODEL.model } })
|
|
221
|
+
await api('PATCH', `/api/workshop/channels/${channelId}/execution-mode`, mode === 'auto' ? { mode: 'auto', confirm: true } : { mode })
|
|
222
|
+
const put = await api('PUT', `/api/workshop/channels/${channelId}/tools`, {
|
|
223
|
+
mode: 'selected',
|
|
224
|
+
tools: toolNames.map(n => ({ name: n, enabled: true })),
|
|
225
|
+
})
|
|
226
|
+
const agents = (await api('GET', `/api/workshop/channels/${channelId}`))?.data?.agents ?? []
|
|
227
|
+
const lead = agents.find(a => a.role === 'lead')
|
|
228
|
+
return { channelId, lead, toolsSaved: put.status, agents }
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function addWorker(channelId, name) {
|
|
232
|
+
const r = await api('POST', `/api/workshop/channels/${channelId}/agents`, {
|
|
233
|
+
name,
|
|
234
|
+
harness: 'omp',
|
|
235
|
+
role: 'worker',
|
|
236
|
+
config: { rpcMode: 'rpc', args: ['--no-tools'] },
|
|
237
|
+
})
|
|
238
|
+
const worker = r?.data?.agent ?? r?.data
|
|
239
|
+
if (!worker?.id) throw new Error(`worker 创建失败: ${JSON.stringify(r).slice(0, 400)}`)
|
|
240
|
+
return worker
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function bindNode(agentId, nodeId, kind, mode = 'manual') {
|
|
244
|
+
const created = await api('POST', '/api/workshop/agent-tools/bindings', { agentId, nodeId, kind, mode })
|
|
245
|
+
const b = created?.data?.binding
|
|
246
|
+
if (!b) throw new Error(`绑定失败: ${JSON.stringify(created).slice(0, 300)}`)
|
|
247
|
+
if (mode === 'auto' && b.mode !== 'auto') {
|
|
248
|
+
const patched = await api('PATCH', `/api/workshop/agent-tools/bindings/${b.id}`, { mode: 'auto', confirm: true })
|
|
249
|
+
return patched?.data?.binding ?? b
|
|
250
|
+
}
|
|
251
|
+
return b
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** 提示词注入探针:同一 AW_HOME 的只读 sidecar,调用运行时同一个 buildIndustrialContext */
|
|
255
|
+
function promptProbe(agentId) {
|
|
256
|
+
const r = spawnSync(process.execPath, [
|
|
257
|
+
join(REPO, 'node_modules', 'tsx', 'dist', 'cli.mjs'),
|
|
258
|
+
'--tsconfig', '.nuxt/tsconfig.server.json',
|
|
259
|
+
join(REPO, 'scripts', '_audit', 'prompt-injection-probe.mts'),
|
|
260
|
+
agentId,
|
|
261
|
+
], {
|
|
262
|
+
cwd: REPO,
|
|
263
|
+
env: { ...process.env, AW_MODE: 'home', AW_HOME: HOME, AW_SKIP_DATA_LOCK: '1' },
|
|
264
|
+
encoding: 'utf8',
|
|
265
|
+
timeout: 120_000,
|
|
266
|
+
windowsHide: true,
|
|
267
|
+
})
|
|
268
|
+
if (r.status !== 0) throw new Error(`prompt probe 失败(${r.status}): ${String(r.stderr ?? '').slice(0, 800)}`)
|
|
269
|
+
return JSON.parse(String(r.stdout))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const WORK_PROMPT = lineId => [
|
|
273
|
+
'你是工艺闭环的作业员(worker)。严格按四步执行,不要做别的:',
|
|
274
|
+
'1) 调用 my_industrial_nodes 查看你绑定的数控节点(id/量程/单步);',
|
|
275
|
+
'2) 调用 daq_query:line_id="' + lineId + '",last_minutes=5,bucket_ms=15000,limit=200,记录温度均值与样本数;',
|
|
276
|
+
'3) 调用 recipe_trial:line_id="' + lineId + '",params 只包含你绑定的那个数控节点,value=56,hypothesis 写「基于数采集证据把温度设定由 60 调到 56,验证窗口内响应」;审批由人工处理,工具会返回结果,你不需要等待;',
|
|
277
|
+
'4) 调用 complete_task 提交:daq_query 的样本数与均值、recipe_trial 的完整回执原文与批次 id。',
|
|
278
|
+
'本任务只做这四步:禁止复测、禁止等待/睡眠、禁止 recipe_update/rollback、禁止使用 bash/终端。',
|
|
279
|
+
].join('\n')
|
|
280
|
+
|
|
281
|
+
const TOOLS = ['my_industrial_nodes', 'daq_query', 'recipe_trial', 'recipe_rollback', 'complete_task', 'report_progress']
|
|
282
|
+
|
|
283
|
+
const evidence = {
|
|
284
|
+
at: new Date().toISOString(),
|
|
285
|
+
env: {
|
|
286
|
+
base: BASE,
|
|
287
|
+
home: HOME,
|
|
288
|
+
version: '',
|
|
289
|
+
model: MODEL,
|
|
290
|
+
harness: 'omp(真实子进程)',
|
|
291
|
+
devices: 'mock(daq+dcw;无物理响应耦合)',
|
|
292
|
+
note: '真实平台 .output + 真实 omp + 本机 LM Studio Qwen3.5-9B(32k);作业身份 = worker',
|
|
293
|
+
},
|
|
294
|
+
scenario: {},
|
|
295
|
+
prompt: {},
|
|
296
|
+
task: {},
|
|
297
|
+
assertions: results,
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
try {
|
|
301
|
+
const h = await startInstance()
|
|
302
|
+
evidence.env.version = String(h?.version ?? '')
|
|
303
|
+
ok('R1', '生产构建隔离实例就绪(workshop ready)', h?.workshop === 'ready', `port=${PORT} version=${h?.version}`)
|
|
304
|
+
|
|
305
|
+
const reg = await api('POST', '/api/users/register', { name: '验收管理员', email: `accept-${Date.now()}@awshop.local`, password: 'Accept#2026' })
|
|
306
|
+
admin = reg?.data?.token
|
|
307
|
+
ok('R1b', 'admin 注册/登录', Boolean(admin), `status=${reg.status}`)
|
|
308
|
+
writeFileSync(join(HOME, 'admin.json'), JSON.stringify({ token: admin }))
|
|
309
|
+
|
|
310
|
+
// ── 产线:DAQ 测温 + DCW 温度设定 + 产品/配方 + 开跑 ──
|
|
311
|
+
const line = await scenarioLine('验收-整改-产线', 'auto', '多专家整改验收线:温度监测 + 点位写授权(模拟设备)')
|
|
312
|
+
const daqTemp = await makeDaq({
|
|
313
|
+
name: '腔体温度', templateRef: 'temp-tc', lineId: line.id, unit: 'C', decimals: 2, min: 0, max: 100,
|
|
314
|
+
semantics: '腔体温度测点;正常工艺窗口 50~70C',
|
|
315
|
+
})
|
|
316
|
+
const dcwSp = await makeDcw({
|
|
317
|
+
name: '温度设定', templateRef: 'temp-sp', lineId: line.id, unit: 'C', decimals: 2, min: 0, max: 100,
|
|
318
|
+
driverConfig: { key: 'accept-mx-temp-sp' }, semantics: '腔体温度设定点;单步 <=4C,窗口 50~70C',
|
|
319
|
+
})
|
|
320
|
+
await remapParam(line.id, dcwSp.id, 'temp_sp', '腔体温度设定值(C)')
|
|
321
|
+
const product = (await api('POST', '/api/workshop/dcw/products', {
|
|
322
|
+
name: '验收产品', lineId: line.id, description: '温度窗口 50~70C',
|
|
323
|
+
paramLimits: { temp_sp: { min: 50, max: 70 } },
|
|
324
|
+
})).data.product
|
|
325
|
+
const recipe = (await api('POST', '/api/workshop/dcw/recipes', {
|
|
326
|
+
name: '验收配方', productId: product.id, description: '验收配方;温度设定 50~70C,单步 4C',
|
|
327
|
+
opIntervalMs: 0,
|
|
328
|
+
params: [{ nodeId: dcwSp.id, value: 60, min: 50, max: 70, stepLimit: 4 }],
|
|
329
|
+
daqWindows: [{ nodeId: daqTemp.id, min: 50, max: 70 }],
|
|
330
|
+
})).data.recipe
|
|
331
|
+
const start = await api('POST', `/api/workshop/dcw/lines/${line.id}/start`, { recipeId: recipe.id })
|
|
332
|
+
ok('R1c', '产线开跑(活动批次建立,配方整批下发)', start.status === 200, `status=${start.status} line=${line.id} recipe=${recipe.id}`)
|
|
333
|
+
// 采集总控必须显式启动(否则节点不采样,daq_query 无数据)
|
|
334
|
+
const daqStart = await api('POST', '/api/workshop/daq/controller', { action: 'start' })
|
|
335
|
+
ok('R1d', '数采网关启动(controller action=start)', daqStart.status === 200, `status=${daqStart.status}`)
|
|
336
|
+
await sleep(12_000)
|
|
337
|
+
|
|
338
|
+
// ── AgentChannel:lead + worker ──
|
|
339
|
+
const ch = await makeChannel('验收-整改-频道', line.id, '作业频道:worker 绑定节点后按任务四步执行;手动模式所有下发需人工批准。', 'manual', TOOLS)
|
|
340
|
+
const channelId = ch.channelId
|
|
341
|
+
const worker = await addWorker(channelId, '验收-整改-作业员')
|
|
342
|
+
ok('R2', 'AgentChannel 创建成功(lead + worker 成员)', Boolean(ch.lead?.id && worker.id),
|
|
343
|
+
JSON.stringify({ channelId, lead: ch.lead?.id, worker: worker.id, toolsSaved: ch.toolsSaved }))
|
|
344
|
+
|
|
345
|
+
// ── worker 绑定节点:DAQ(观察,auto)+ DCW(点位写授权,manual) ──
|
|
346
|
+
const bDaq = await bindNode(worker.id, daqTemp.id, 'daq', 'auto')
|
|
347
|
+
const bDcw = await bindNode(worker.id, dcwSp.id, 'dcw', 'manual')
|
|
348
|
+
ok('R2b', 'worker 节点绑定落库(daq=auto / dcw=manual)',
|
|
349
|
+
bDaq.mode === 'auto' && bDcw.mode === 'manual' && bDaq.nodeId === daqTemp.id && bDcw.nodeId === dcwSp.id,
|
|
350
|
+
JSON.stringify({ daq: { id: bDaq.id, mode: bDaq.mode }, dcw: { id: bDcw.id, mode: bDcw.mode } }))
|
|
351
|
+
evidence.scenario = {
|
|
352
|
+
line: line.id, recipe: recipe.id, product: product.id,
|
|
353
|
+
daq: daqTemp.id, dcw: dcwSp.id, channel: channelId,
|
|
354
|
+
lead: ch.lead?.id, worker: worker.id,
|
|
355
|
+
bindings: { daq: bDaq.id, dcw: bDcw.id },
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ── R3 运行时提示词注入(运行时同一个 buildIndustrialContext / nodeSemanticCards) ──
|
|
359
|
+
const probe = promptProbe(worker.id)
|
|
360
|
+
const cardsText = String(probe.cards ?? '')
|
|
361
|
+
evidence.prompt = {
|
|
362
|
+
channelId: probe.channelId,
|
|
363
|
+
profileMode: probe.profileMode,
|
|
364
|
+
text: String(probe.text ?? '').slice(0, 8000),
|
|
365
|
+
cards: cardsText.slice(0, 8000),
|
|
366
|
+
stale: probe.stale,
|
|
367
|
+
error: probe.error,
|
|
368
|
+
}
|
|
369
|
+
ok('R3', '运行时提示词注入:执行模式卡(manual)+ 绑定节点语义卡(名称/量程/单步/手动确认)',
|
|
370
|
+
probe.profileMode === 'manual'
|
|
371
|
+
&& cardsText.includes('频道执行模式:manual')
|
|
372
|
+
&& cardsText.includes('温度设定') && cardsText.includes(dcwSp.id)
|
|
373
|
+
&& cardsText.includes('安全量程') && cardsText.includes('单步') && cardsText.includes('手动确认模式')
|
|
374
|
+
&& cardsText.includes('腔体温度') && cardsText.includes(daqTemp.id),
|
|
375
|
+
cardsText.slice(0, 600))
|
|
376
|
+
|
|
377
|
+
// ── R4 工具注入面按绑定面差异化 ──
|
|
378
|
+
const tok = agentTokenOf(worker.id)
|
|
379
|
+
const list = await api('GET', `/api/workshop/agent-tools/list?agentId=${encodeURIComponent(worker.id)}`, undefined, undefined, { 'x-aw-agent-token': tok })
|
|
380
|
+
const trialDesc = String((list?.data?.tools ?? []).find(t => t.name === 'recipe_trial')?.description ?? '')
|
|
381
|
+
ok('R4', '工具注入面携带该 worker 的绑定节点(recipe_trial 描述含 dcw id)',
|
|
382
|
+
trialDesc.includes(dcwSp.id), trialDesc.slice(-260))
|
|
383
|
+
|
|
384
|
+
// ── R5 worker 真实 omp 回合 ──
|
|
385
|
+
const task = await submitTask(channelId, '验收-整改-worker作业', WORK_PROMPT(line.id), worker.id)
|
|
386
|
+
const t0 = Date.now()
|
|
387
|
+
const run = await waitTask(task.id, {
|
|
388
|
+
timeoutMs: 18 * 60_000,
|
|
389
|
+
autoApprove: true,
|
|
390
|
+
onCard: (card) => {
|
|
391
|
+
console.log(` · HITL card ${card.id} 出现,自动批准`)
|
|
392
|
+
void approve(card.id, '验收:批准基于数采集证据的温度试验(→56C)').then(r => console.log(` · approve status=${r.status}`))
|
|
393
|
+
},
|
|
394
|
+
})
|
|
395
|
+
const elapsed = Math.round((Date.now() - t0) / 1000)
|
|
396
|
+
const deliverable = deliverableOf(run.task)
|
|
397
|
+
const calls = toolCallsOf(run.task)
|
|
398
|
+
evidence.task = {
|
|
399
|
+
id: task.id, state: run.task?.state, elapsedSec: elapsed, assignee: run.task?.assigneeId,
|
|
400
|
+
deliverable, toolCalls: calls,
|
|
401
|
+
cards: run.cards.map(c => ({ id: c.id, detail: String(c.detail ?? '').slice(0, 600) })),
|
|
402
|
+
}
|
|
403
|
+
ok('R5', 'worker 任务 COMPLETED(omp + Qwen3.5)', run.task?.state === 'COMPLETED', `state=${run.task?.state} elapsed=${elapsed}s`)
|
|
404
|
+
const completedExplicitly = calls.some(c => c.includes('complete_task'))
|
|
405
|
+
evidence.task.completedExplicitly = completedExplicitly
|
|
406
|
+
ok('R5b', '工具链覆盖 my_industrial_nodes/daq_query/recipe_trial(闭环结论见交付物)',
|
|
407
|
+
calls.some(c => c.includes('my_industrial_nodes')) && calls.some(c => c.includes('daq_query'))
|
|
408
|
+
&& calls.some(c => c.includes('recipe_trial'))
|
|
409
|
+
&& /recipe_trial/i.test(deliverable) && /样本数|均值/.test(deliverable),
|
|
410
|
+
`complete_task=${completedExplicitly}(false=平台按交付物隐式收口) | ${calls.join(' || ').slice(0, 700)}`)
|
|
411
|
+
|
|
412
|
+
// ── R6 HITL + ACK ──
|
|
413
|
+
const history = await approvalsHistory(worker.id)
|
|
414
|
+
const approved = history.filter(a => String(a.status ?? a.decision ?? '') === 'approved' || a.approved === true || a.decision === 'approved')
|
|
415
|
+
ok('R6', '手动模式挂起人工审批并获批(HITL)', run.cards.length >= 1 && (approved.length >= 1 || history.length >= 1),
|
|
416
|
+
JSON.stringify({ cards: run.cards.length, history: history.length, approved: approved.length }))
|
|
417
|
+
ok('R6b', '审批卡展示依据(hypothesis/理由)', run.cards.some(c => /hypothesis|依据|56/.test(String(c.detail ?? ''))),
|
|
418
|
+
run.cards.map(c => String(c.detail ?? '').slice(0, 200)).join(' | '))
|
|
419
|
+
ok('R6c', '下发获得设备证实(交付物含 ACK/证实)', /ACK|证实|verified/i.test(deliverable), deliverable.slice(0, 500))
|
|
420
|
+
|
|
421
|
+
// ── R7 效果核验 ──
|
|
422
|
+
const nodes = (await api('GET', `/api/workshop/dcw?lineId=${line.id}`))?.data?.nodes ?? []
|
|
423
|
+
const node = nodes.find(n => n.id === dcwSp.id)
|
|
424
|
+
ok('R7', '节点实际值变更为 56(设备侧生效)', Number(node?.value) === 56, `value=${node?.value} state=${node?.state}`)
|
|
425
|
+
const recipes = (await api('GET', `/api/workshop/dcw/recipes/${recipe.id}`))?.data
|
|
426
|
+
const recipeVersion = Number(recipes?.recipe?.version ?? recipes?.version ?? 1)
|
|
427
|
+
ok('R7b', 'trial 不写配方版本(版本仍为 1)', recipeVersion === 1, `version=${recipeVersion}`)
|
|
428
|
+
const journal = (await api('GET', `/api/workshop/dcw/journal?lineId=${line.id}&limit=500`))?.data?.anchors ?? []
|
|
429
|
+
ok('R7c', '账本新增写入锚点(可审计)', journal.length >= 2, `anchors=${journal.length}`)
|
|
430
|
+
// 数采链路:经权威查询端点(REST)取该测点最近 10 分钟的原始桶
|
|
431
|
+
const dq = await api('GET', `/api/workshop/daq/query?node_ids=${encodeURIComponent(daqTemp.id)}&last_minutes=10&bucket_ms=15000&limit=200`)
|
|
432
|
+
const series = dq?.data?.series ?? dq?.series ?? []
|
|
433
|
+
const pts = series.flatMap(s => s.points ?? s.data ?? [])
|
|
434
|
+
ok('R7d', 'TSDB 有该测点真实样本(数采链路入库,daq 查询端点可读)', dq.status === 200 && pts.length > 0,
|
|
435
|
+
`status=${dq.status} points=${pts.length} sample=${JSON.stringify(pts[0] ?? null).slice(0, 160)}`)
|
|
436
|
+
evidence.scenario.final = { nodeValue: node?.value, recipeVersion, journal: journal.length, dpsPoints: pts.length }
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
ok('R0', '验收执行未抛异常', false, err instanceof Error ? `${err.message}\n${err.stack ?? ''}` : String(err))
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
const pass = results.filter(r => r.pass).length
|
|
443
|
+
const fail = results.length - pass
|
|
444
|
+
evidence.summary = { total: results.length, pass, fail }
|
|
445
|
+
mkdirSync(EVIDENCE_DIR, { recursive: true })
|
|
446
|
+
writeFileSync(join(EVIDENCE_DIR, 'report.json'), `${JSON.stringify(evidence, null, 2)}\n`)
|
|
447
|
+
writeFileSync(join(EVIDENCE_DIR, 'prompt-injection.json'), `${JSON.stringify(evidence.prompt, null, 2)}\n`)
|
|
448
|
+
writeFileSync(join(EVIDENCE_DIR, 'task.json'), `${JSON.stringify(evidence.task, null, 2)}\n`)
|
|
449
|
+
console.log(`\n=== ${pass}/${results.length} PASS, ${fail} FAIL ===`)
|
|
450
|
+
console.log(`证据:${EVIDENCE_DIR}`)
|
|
451
|
+
stopOwnedInstance()
|
|
452
|
+
if (fail > 0) process.exitCode = 1
|
|
453
|
+
}
|