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
|
@@ -8,13 +8,19 @@ import { statSync } from 'node:fs'
|
|
|
8
8
|
import { resolveUser } from '@/server/api/workshop/caller'
|
|
9
9
|
import { defineApiHandler } from '@/server/utils/response'
|
|
10
10
|
import { listMesArtifacts } from '@/server/services/workshop/mes/mes-hook'
|
|
11
|
+
import { getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
12
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
13
|
+
import { requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
11
14
|
|
|
12
15
|
export default defineApiHandler(async (event) => {
|
|
13
|
-
resolveUser(event)
|
|
16
|
+
const user = resolveUser(event)
|
|
14
17
|
const q = getQuery(event)
|
|
15
18
|
const nodeId = String(q.node_id ?? '').trim()
|
|
16
19
|
const limit = Math.max(1, Math.min(Number(q.limit) || 50, 200))
|
|
17
20
|
if (!nodeId) return { artifacts: [], message: '缺少 node_id' }
|
|
21
|
+
const node = getDcwController().byId(nodeId)
|
|
22
|
+
if (!node) throw new AppError(404, ErrorCodes.NOT_FOUND, `控制节点不存在: ${nodeId}`)
|
|
23
|
+
requireLineForResource(user, node.lineId, 'MES 点位', 'readonly')
|
|
18
24
|
const artifacts = listMesArtifacts(nodeId, limit).map((a) => {
|
|
19
25
|
let mtime: string | null = null
|
|
20
26
|
try {
|
|
@@ -7,10 +7,15 @@ import { getQuery, getRouterParam } from 'h3'
|
|
|
7
7
|
import { resolveUser } from '@/server/api/workshop/caller'
|
|
8
8
|
import { defineApiHandler } from '@/server/utils/response'
|
|
9
9
|
import { getRecipeRollBackManager } from '@/server/services/workshop/dcw/recipe-rollback-manager'
|
|
10
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
11
|
+
import { requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
10
12
|
|
|
11
13
|
export default defineApiHandler(async (event) => {
|
|
12
|
-
resolveUser(event)
|
|
14
|
+
const user = resolveUser(event)
|
|
13
15
|
const id = getRouterParam(event, 'id') ?? ''
|
|
16
|
+
const record = getRecipeRollBackManager().recordById(id)
|
|
17
|
+
if (!record) throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${id}`)
|
|
18
|
+
requireLineForResource(user, record.lineId, '优化记录', 'readonly')
|
|
14
19
|
const q = getQuery(event)
|
|
15
20
|
const windowMs = q.windowMs ? Number(q.windowMs) : undefined
|
|
16
21
|
const result = await getRecipeRollBackManager().series(id, Number.isFinite(windowMs) ? windowMs : undefined)
|
|
@@ -6,12 +6,14 @@ import { resolveUser } from '@/server/api/workshop/caller'
|
|
|
6
6
|
import { defineApiHandler } from '@/server/utils/response'
|
|
7
7
|
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
8
8
|
import { getRecipeRollBackManager } from '@/server/services/workshop/dcw/recipe-rollback-manager'
|
|
9
|
+
import { requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
9
10
|
|
|
10
11
|
export default defineApiHandler(async (event) => {
|
|
11
|
-
resolveUser(event)
|
|
12
|
+
const user = resolveUser(event)
|
|
12
13
|
const id = getRouterParam(event, 'id') ?? ''
|
|
13
14
|
const record = getRecipeRollBackManager().recordById(id)
|
|
14
15
|
if (!record)
|
|
15
16
|
throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${id}`)
|
|
17
|
+
requireLineForResource(user, record.lineId, '优化记录', 'readonly')
|
|
16
18
|
return { record }
|
|
17
19
|
})
|
|
@@ -6,18 +6,21 @@ import { getQuery } from 'h3'
|
|
|
6
6
|
import { resolveUser } from '@/server/api/workshop/caller'
|
|
7
7
|
import { defineApiHandler } from '@/server/utils/response'
|
|
8
8
|
import { getRecipeRollBackManager } from '@/server/services/workshop/dcw/recipe-rollback-manager'
|
|
9
|
+
import { filterRowsByLine, requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
9
10
|
|
|
10
11
|
export default defineApiHandler(async (event) => {
|
|
11
|
-
resolveUser(event)
|
|
12
|
+
const user = resolveUser(event)
|
|
12
13
|
const q = getQuery(event)
|
|
13
14
|
const limit = Number(q.limit ?? 100)
|
|
15
|
+
const lineId = q.lineId ? String(q.lineId) : undefined
|
|
16
|
+
if (lineId) requireLineForResource(user, lineId, '产线', 'readonly')
|
|
14
17
|
const records = getRecipeRollBackManager().records({
|
|
15
|
-
lineId
|
|
18
|
+
lineId,
|
|
16
19
|
recipeId: q.recipeId ? String(q.recipeId) : undefined,
|
|
17
20
|
nodeId: q.nodeId ? String(q.nodeId) : undefined,
|
|
18
21
|
status: q.status ? String(q.status) : undefined,
|
|
19
22
|
agentId: q.agentId ? String(q.agentId) : undefined,
|
|
20
23
|
limit: Number.isFinite(limit) ? Math.min(limit, 500) : 100,
|
|
21
24
|
})
|
|
22
|
-
return { records }
|
|
25
|
+
return { records: filterRowsByLine(user, records, r => r.lineId) }
|
|
23
26
|
})
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/workshop/dcw/params/:id/read —— 工艺参数读取(读执行节点 PLC 值,物理量纲)。
|
|
3
|
-
* 被动观测免审批;返回 PLC 实时读数 + 当前设定值。
|
|
4
|
-
*/
|
|
5
|
-
import { getRouterParam } from 'h3'
|
|
6
|
-
import { resolveUser } from '@/server/api/workshop/caller'
|
|
7
|
-
import { defineApiHandler } from '@/server/utils/response'
|
|
8
|
-
import { bindDcwBroadcast, getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
9
|
-
import { broadcastSceneEvent } from '@/server/services/workshop/scene-events'
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/dcw/params/:id/read —— 工艺参数读取(读执行节点 PLC 值,物理量纲)。
|
|
3
|
+
* 被动观测免审批;返回 PLC 实时读数 + 当前设定值。
|
|
4
|
+
*/
|
|
5
|
+
import { getRouterParam } from 'h3'
|
|
6
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
7
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
8
|
+
import { bindDcwBroadcast, getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
9
|
+
import { broadcastSceneEvent } from '@/server/services/workshop/scene-events'
|
|
10
|
+
import { getDcwParamRepo } from '@/server/services/workshop/dcw/param-map.repo'
|
|
11
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
12
|
+
import { paramLineId, requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
13
|
+
|
|
14
|
+
export default defineApiHandler(async (event) => {
|
|
15
|
+
const user = resolveUser(event)
|
|
16
|
+
bindDcwBroadcast(broadcastSceneEvent)
|
|
17
|
+
const id = getRouterParam(event, 'id') ?? ''
|
|
18
|
+
if (!getDcwParamRepo().byId(id)) throw new AppError(404, ErrorCodes.NOT_FOUND, `工艺参数不存在: ${id}`)
|
|
19
|
+
requireLineForResource(user, paramLineId(id), '工艺参数', 'readonly')
|
|
20
|
+
const read = await getDcwController().readParam(id)
|
|
21
|
+
return { read }
|
|
22
|
+
})
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GET /api/workshop/dcw/recipes/:id/versions —— 配方参数版本历史(旧→新,尾行=当前版)。
|
|
3
|
-
* 每条:version/at/by(来源)/actorName(人话操作者)/description(变更原因)/params。
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/workshop/dcw/recipes/:id/versions —— 配方参数版本历史(旧→新,尾行=当前版)。
|
|
3
|
+
* 每条:version/at/by(来源)/actorName(人话操作者)/description(变更原因)/params。
|
|
4
|
+
* 2026-10-28:按配方所属产线校验只读授权。
|
|
5
|
+
*/
|
|
6
|
+
import { getRouterParam } from 'h3'
|
|
7
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
8
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
9
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
10
|
+
import { getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
11
|
+
import { recipeLineId, requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
12
|
+
|
|
13
|
+
export default defineApiHandler(async (event) => {
|
|
14
|
+
const user = resolveUser(event)
|
|
15
|
+
const id = getRouterParam(event, 'id') ?? ''
|
|
16
|
+
const recipe = getDcwController().listRecipes().find(r => r.id === id)
|
|
17
|
+
if (!recipe) throw new AppError(404, ErrorCodes.NOT_FOUND, `Recipe 不存在: ${id}`)
|
|
18
|
+
requireLineForResource(user, recipeLineId(id) ?? recipe.lineId, '配方', 'readonly')
|
|
19
|
+
return { versions: getDcwController().recipeVersions(id) }
|
|
20
|
+
})
|
|
@@ -1,25 +1,33 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DELETE /api/workshop/dcw/recipes/:id —— 删除配方。
|
|
3
|
-
*/
|
|
4
|
-
import { getRouterParam } from 'h3'
|
|
5
|
-
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
-
import { defineApiHandler } from '@/server/utils/response'
|
|
7
|
-
import { getDcwRecipeRepo } from '@/server/services/workshop/dcw/dcw-recipe.repo'
|
|
8
|
-
import { recordOps } from '@/server/services/workshop/ops/ops'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
/**
|
|
2
|
+
* DELETE /api/workshop/dcw/recipes/:id —— 删除配方。
|
|
3
|
+
*/
|
|
4
|
+
import { getRouterParam } from 'h3'
|
|
5
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
7
|
+
import { getDcwRecipeRepo } from '@/server/services/workshop/dcw/dcw-recipe.repo'
|
|
8
|
+
import { recordOps } from '@/server/services/workshop/ops/ops'
|
|
9
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
10
|
+
import { requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
11
|
+
|
|
12
|
+
export default defineApiHandler(async (event) => {
|
|
13
|
+
const user = resolveUser(event)
|
|
14
|
+
const id = getRouterParam(event, 'id') ?? ''
|
|
15
|
+
// 删除前取归属维度(remove 后不可读),产线日志按线/配方归档
|
|
16
|
+
const recipe = getDcwRecipeRepo().byId(id)
|
|
17
|
+
if (!recipe) throw new AppError(404, ErrorCodes.NOT_FOUND, `Recipe 不存在: ${id}`)
|
|
18
|
+
requireLineForResource(user, recipe.lineId, '配方', 'operate')
|
|
19
|
+
const activeRun = getDcwRecipeRepo().listRuns().find(r => r.recipeId === id && !r.endedAt)
|
|
20
|
+
if (activeRun) {
|
|
21
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `配方「${recipe.name}」仍在批次 ${activeRun.id.slice(0, 8)} 中执行,请先停线/关批次后再删除`)
|
|
22
|
+
}
|
|
23
|
+
getDcwRecipeRepo().remove(id)
|
|
24
|
+
recordOps({
|
|
25
|
+
actor: user.id, actorName: user.name, actorKind: 'user',
|
|
26
|
+
action: 'recipe.delete', kind: 'recipe', targetKind: 'recipe', targetId: id,
|
|
27
|
+
lineId: recipe?.lineId ?? '',
|
|
28
|
+
productId: recipe?.productId ?? '',
|
|
29
|
+
recipeId: id,
|
|
30
|
+
summary: `删除配方「${recipe?.name ?? id}」${recipe?.lineId ? `(产线 ${recipe.lineId})` : ''}`,
|
|
31
|
+
})
|
|
32
|
+
return { deleted: true }
|
|
33
|
+
})
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GET /api/workshop/dcw/recipes —— 配方 + 批次列表。
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/workshop/dcw/recipes —— 配方 + 批次列表。
|
|
3
|
+
* 2026-10-28:按调用者产线授权过滤(admin/特权见全集)。
|
|
4
|
+
*/
|
|
5
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
7
|
+
import { getDcwRecipeRepo } from '@/server/services/workshop/dcw/dcw-recipe.repo'
|
|
8
|
+
import { filterRowsByLine } from '@/server/services/workshop/line-scope'
|
|
9
|
+
|
|
10
|
+
export default defineApiHandler(async (event) => {
|
|
11
|
+
const user = resolveUser(event)
|
|
12
|
+
const repo = getDcwRecipeRepo()
|
|
13
|
+
return {
|
|
14
|
+
recipes: filterRowsByLine(user, repo.list(), r => r.lineId),
|
|
15
|
+
runs: filterRowsByLine(user, repo.listRuns(), r => r.lineId),
|
|
16
|
+
}
|
|
17
|
+
})
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/workshop/dcw/runs/:id/close —— 关闭批次(结束数据隔离窗口)。
|
|
3
|
-
*/
|
|
4
|
-
import { getRouterParam } from 'h3'
|
|
5
|
-
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
-
import { defineApiHandler } from '@/server/utils/response'
|
|
7
|
-
import { bindDcwBroadcast, getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
8
|
-
import { broadcastSceneEvent } from '@/server/services/workshop/scene-events'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/dcw/runs/:id/close —— 关闭批次(结束数据隔离窗口)。
|
|
3
|
+
*/
|
|
4
|
+
import { getRouterParam } from 'h3'
|
|
5
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
6
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
7
|
+
import { bindDcwBroadcast, getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
8
|
+
import { broadcastSceneEvent } from '@/server/services/workshop/scene-events'
|
|
9
|
+
import { getDcwRecipeRepo } from '@/server/services/workshop/dcw/dcw-recipe.repo'
|
|
10
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
11
|
+
import { requireLineForResource } from '@/server/services/workshop/line-scope'
|
|
12
|
+
|
|
13
|
+
export default defineApiHandler(async (event) => {
|
|
14
|
+
const user = resolveUser(event)
|
|
15
|
+
bindDcwBroadcast(broadcastSceneEvent)
|
|
16
|
+
const id = getRouterParam(event, 'id') ?? ''
|
|
17
|
+
const run = getDcwRecipeRepo().runById(id)
|
|
18
|
+
if (!run) throw new AppError(404, ErrorCodes.NOT_FOUND, `批次不存在: ${id}`)
|
|
19
|
+
requireLineForResource(user, run.lineId, '批次', 'operate')
|
|
20
|
+
return { run: getDcwController().closeRun(id) }
|
|
21
|
+
})
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/workshop/dcw/test-driver —— 连接测试(body: { driver, driverConfig })。
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/dcw/test-driver —— 连接测试(body: { driver, driverConfig })。
|
|
3
|
+
*
|
|
4
|
+
* 2026-10-28 安全修复:仅 admin/editor 可调用;allowPrivateHost 只认服务端开关。
|
|
5
|
+
*/
|
|
6
|
+
import { readBody } from 'h3'
|
|
7
|
+
import type { DcwDriverKind } from '#shared/dcw-protocol'
|
|
8
|
+
import { requireRole } from '@/server/api/workshop/caller'
|
|
9
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
10
|
+
import { bindDcwBroadcast, getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
|
|
11
|
+
import { broadcastSceneEvent } from '@/server/services/workshop/scene-events'
|
|
12
|
+
|
|
13
|
+
export default defineApiHandler(async (event) => {
|
|
14
|
+
requireRole(event, ['admin', 'editor'])
|
|
15
|
+
bindDcwBroadcast(broadcastSceneEvent)
|
|
16
|
+
const body = await readBody<{ driver?: DcwDriverKind, driverConfig?: Record<string, unknown> }>(event) ?? {}
|
|
17
|
+
const cfg: Record<string, unknown> = { ...(body.driverConfig ?? {}) }
|
|
18
|
+
delete cfg.allowPrivateHost
|
|
19
|
+
if (process.env.AW_TEST_DRIVER_ALLOW_PRIVATE === '1') cfg.allowPrivateHost = 'true'
|
|
20
|
+
return { test: await getDcwController().testDriver(body.driver ?? 'mock', cfg) }
|
|
21
|
+
})
|
|
@@ -9,7 +9,7 @@ import { PEER_SEND_BUDGET_BYTES, hub, streams } from './shared'
|
|
|
9
9
|
import { ensureStream } from './streams'
|
|
10
10
|
import { flushDbBuffer } from './db-buffer'
|
|
11
11
|
import { getWorkshopManager } from '../../../plugins/workshop'
|
|
12
|
-
import { registerScenePeer, setPeerVisibleLines } from '../../../services/workshop/scene-events'
|
|
12
|
+
import { registerScenePeer, setPeerIdentity, setPeerVisibleLines } from '../../../services/workshop/scene-events'
|
|
13
13
|
import { visibleLineIds } from '../../../services/workshop/permissions'
|
|
14
14
|
|
|
15
15
|
export function ensureHubBound(manager: AgentChannelManager): void {
|
|
@@ -87,6 +87,7 @@ export function resolveChannelIdFromUrl(peer: WsPeer): string | undefined {
|
|
|
87
87
|
/** 场景事件注册(鉴权后):按用户产线可见集挂 per-peer 过滤,未经鉴权的 peer 不注册 */
|
|
88
88
|
export function attachScenePeer(peer: WsPeer, user: { id: string, role: string }): void {
|
|
89
89
|
setPeerVisibleLines(peer, visibleLineIds(user))
|
|
90
|
+
setPeerIdentity(peer, user)
|
|
90
91
|
registerScenePeer(peer)
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数据目录单实例守卫(S16,2026-10-28)。
|
|
3
|
+
*
|
|
4
|
+
* `scripts/start.mjs`/`dev-guard.mjs` 已有 <configRoot>/.runtime/aw.lock,但直接
|
|
5
|
+
* `node .output/server/index.mjs` 的启动路径绕过它 —— 两个进程共享同一份 JSON 仓储/
|
|
6
|
+
* writeLocks 时会互相覆盖、绕过 60s/保持窗。本插件在配置根再取一把数据锁
|
|
7
|
+
* (<configRoot>/.runtime/data.lock),覆盖所有启动方式:
|
|
8
|
+
* - 已存在且 PID 存活 → fail-fast(退出码 1);
|
|
9
|
+
* - PID 已死(崩溃残留) → 接管重写;
|
|
10
|
+
* - 进程退出/信号 → 释放。
|
|
11
|
+
* 显式豁免:AW_SKIP_DATA_LOCK=1(仅测试/受控多实例编排,默认禁止)。
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
14
|
+
import { join, resolve } from 'node:path'
|
|
15
|
+
|
|
16
|
+
const SKIP = process.env.AW_SKIP_DATA_LOCK === '1'
|
|
17
|
+
const ROOT = resolve(process.env.AW_HOME ?? process.cwd())
|
|
18
|
+
const DIR = join(ROOT, '.runtime')
|
|
19
|
+
const LOCK = join(DIR, 'data.lock')
|
|
20
|
+
|
|
21
|
+
interface LockFile { pid?: number, at?: string }
|
|
22
|
+
|
|
23
|
+
function pidAlive(pid: number): boolean {
|
|
24
|
+
if (!Number.isInteger(pid) || pid <= 0) return false
|
|
25
|
+
try {
|
|
26
|
+
process.kill(pid, 0)
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return (err as NodeJS.ErrnoException)?.code === 'EPERM'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readLock(): LockFile | null {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(readFileSync(LOCK, 'utf8')) as LockFile
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function release(): void {
|
|
44
|
+
try {
|
|
45
|
+
const cur = readLock()
|
|
46
|
+
if (cur?.pid === process.pid && existsSync(LOCK)) rmSync(LOCK, { force: true })
|
|
47
|
+
}
|
|
48
|
+
catch { /* 退出路径尽力而为 */ }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default async function instanceGuardPlugin(): Promise<void> {
|
|
52
|
+
if (SKIP) {
|
|
53
|
+
console.warn('[instance-guard] AW_SKIP_DATA_LOCK=1:已跳过数据目录单实例锁(仅限测试/受控编排)')
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
mkdirSync(DIR, { recursive: true })
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error('[instance-guard] 无法创建 .runtime 目录:', err instanceof Error ? err.message : err)
|
|
61
|
+
process.exit(1)
|
|
62
|
+
}
|
|
63
|
+
const existing = readLock()
|
|
64
|
+
if (existing?.pid && existing.pid !== process.pid && pidAlive(existing.pid)) {
|
|
65
|
+
console.error(`[instance-guard] 数据目录已被进程 ${existing.pid} 占用:${ROOT}。同一数据目录只允许一个写者;请先停止该实例,或设置 AW_HOME 指向独立目录。`)
|
|
66
|
+
process.exit(1)
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
writeFileSync(LOCK, JSON.stringify({ pid: process.pid, at: new Date().toISOString() }), { flag: 'w' })
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
console.error('[instance-guard] 无法写入数据锁:', err instanceof Error ? err.message : err)
|
|
73
|
+
process.exit(1)
|
|
74
|
+
}
|
|
75
|
+
process.once('exit', release)
|
|
76
|
+
for (const sig of ['SIGINT', 'SIGTERM'] as const) {
|
|
77
|
+
process.once(sig, () => {
|
|
78
|
+
release()
|
|
79
|
+
process.exit(0)
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
}
|
package/server/plugins/daq.ts
CHANGED
|
@@ -4,25 +4,43 @@
|
|
|
4
4
|
* 启动时:探测配置地址(MQTT/Timescale)→ 不通且策略允许则 docker compose 自动拉起
|
|
5
5
|
* → 依判定结果装配真实/降级后端 → 降级则停采并警告;后台 30s 自动重连,
|
|
6
6
|
* 恢复后重建真实后端 + 重挂消费者 + 恢复采集。
|
|
7
|
+
*
|
|
8
|
+
* 2026-10-28(S10):启动屏障 —— 后端装配完成前不 resolve `__daqInfraReady`,
|
|
9
|
+
* workshop 插件的 resumeAll 必须等待它,避免采样先落到占位 SQLite/进程内队列;
|
|
10
|
+
* 后端初始化失败时显式置 degraded 并停采(不再"端口通=健康")。
|
|
7
11
|
*/
|
|
8
12
|
import { useRuntimeConfig } from '#imports'
|
|
9
|
-
import { daqUrls, ensureDaqInfrastructure, scheduleAutoReconnect, type DaqInfraConfig } from '../services/workshop/daq/infra'
|
|
13
|
+
import { daqInfraStatus, daqUrls, ensureDaqInfrastructure, markDaqInfraFailure, scheduleAutoReconnect, type DaqInfraConfig } from '../services/workshop/daq/infra'
|
|
10
14
|
import { rebuildTsdb } from '../services/workshop/daq/storage'
|
|
11
15
|
import { rebuildObjectStore } from '../services/workshop/daq/objectstore'
|
|
12
16
|
import { startDaqObjectGc } from '../services/workshop/daq/objectstore/gc'
|
|
13
17
|
import { rebuildDaqQueue } from '../services/workshop/daq/bus'
|
|
14
18
|
import { getDaqController } from '../services/workshop/daq/daq-controller'
|
|
15
19
|
|
|
20
|
+
interface DaqBootState {
|
|
21
|
+
__daqInfraReady?: Promise<void>
|
|
22
|
+
__daqInfraStatus?: () => ReturnType<typeof daqInfraStatus>
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
/** 按最新 infra 状态装配后端 + 控制器(启动/重连共用) */
|
|
17
26
|
async function applyInfra(cfg: DaqInfraConfig): Promise<void> {
|
|
18
27
|
const status = await ensureDaqInfrastructure(cfg, process.cwd())
|
|
19
28
|
const urls = daqUrls(cfg)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
try {
|
|
30
|
+
await rebuildTsdb(status.tsdbOnline, urls.tsdbUrl)
|
|
31
|
+
await rebuildObjectStore(status.objectStoreOnline, urls.objectStoreUrl)
|
|
32
|
+
await rebuildDaqQueue(status.mqttOnline, urls.mqttUrl)
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
// 端口可达 ≠ 后端可用(密码错/库缺失/扩展未装)。装配失败一律降级并停采,
|
|
36
|
+
// 由 30s 重连继续尝试;绝不让采样写进占位后端后"看起来正常"。
|
|
37
|
+
markDaqInfraFailure(err)
|
|
38
|
+
getDaqController().stopAll()
|
|
39
|
+
return
|
|
40
|
+
}
|
|
23
41
|
const ctrl = getDaqController()
|
|
24
42
|
await ctrl.reattachQueue()
|
|
25
|
-
if (
|
|
43
|
+
if (daqInfraStatus().degraded) {
|
|
26
44
|
ctrl.stopAll() // 在线数采停用(降级可见)
|
|
27
45
|
}
|
|
28
46
|
else {
|
|
@@ -55,22 +73,36 @@ export default async function daqPlugin() {
|
|
|
55
73
|
objectstore: raw?.objectstore
|
|
56
74
|
? {
|
|
57
75
|
host: raw.objectstore.host ?? '127.0.0.1',
|
|
58
|
-
port:
|
|
76
|
+
port: raw.objectstore.port ?? 9000,
|
|
59
77
|
accessKey: raw.objectstore.accessKey ?? 'awshop',
|
|
60
78
|
secretKey: raw.objectstore.secretKey ?? 'awshop-secret',
|
|
61
79
|
bucket: raw.objectstore.bucket ?? 'daq',
|
|
62
80
|
}
|
|
63
81
|
: undefined,
|
|
64
82
|
}
|
|
83
|
+
// 启动屏障:先挂 promise,再执行装配;失败也 resolve(状态里 degraded=true),由消费方决定是否停采
|
|
84
|
+
const g = globalThis as unknown as DaqBootState
|
|
85
|
+
let resolveReady!: () => void
|
|
86
|
+
g.__daqInfraReady = new Promise<void>((resolve) => {
|
|
87
|
+
resolveReady = resolve
|
|
88
|
+
})
|
|
89
|
+
g.__daqInfraStatus = daqInfraStatus
|
|
65
90
|
try {
|
|
66
91
|
await applyInfra(cfg)
|
|
67
92
|
}
|
|
68
93
|
catch (err) {
|
|
69
|
-
|
|
94
|
+
markDaqInfraFailure(err)
|
|
95
|
+
try {
|
|
96
|
+
getDaqController().stopAll()
|
|
97
|
+
}
|
|
98
|
+
catch { /* 控制器未就绪 */ }
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
resolveReady()
|
|
70
102
|
}
|
|
71
103
|
// 后台自动重连:恢复后重走装配路径
|
|
72
104
|
scheduleAutoReconnect(() => {
|
|
73
|
-
void applyInfra(cfg).catch(
|
|
105
|
+
void applyInfra(cfg).catch(markDaqInfraFailure)
|
|
74
106
|
})
|
|
75
107
|
// P0-2 对象存储 GC:帧行出清后像素文件孤儿回收(90s 首轮 + 24h 周期;disk 后端)
|
|
76
108
|
startDaqObjectGc()
|
|
@@ -232,6 +232,18 @@ export default function workshopPlugin(nitroApp: {
|
|
|
232
232
|
])
|
|
233
233
|
const { broadcastSceneEvent } = await import('../services/workshop/scene-events')
|
|
234
234
|
bindDaqHost(broadcastSceneEvent)
|
|
235
|
+
// S10 启动屏障:等 daq 插件把后端装配完(成功或明确降级),再决定是否开采。
|
|
236
|
+
// 此前直接 resumeAll 会让采样先写进占位 SQLite/进程内队列,切库后不迁移。
|
|
237
|
+
const g = globalThis as unknown as {
|
|
238
|
+
__daqInfraReady?: Promise<void>
|
|
239
|
+
__daqInfraStatus?: () => { degraded: boolean, warning?: string }
|
|
240
|
+
}
|
|
241
|
+
if (g.__daqInfraReady) await g.__daqInfraReady
|
|
242
|
+
const infra = g.__daqInfraStatus?.()
|
|
243
|
+
if (infra?.degraded) {
|
|
244
|
+
console.warn(`[workshop] DAQ 基础设施降级,跳过 resumeAll:${infra.warning ?? '后端不可用'}`)
|
|
245
|
+
return
|
|
246
|
+
}
|
|
235
247
|
const st = getDaqController().resumeAll()
|
|
236
248
|
console.log(`[workshop] DAQ 采集补挂完成(running=${st.running},宿主端口已装配)`)
|
|
237
249
|
}
|
|
@@ -16,6 +16,29 @@ import { join } from 'node:path'
|
|
|
16
16
|
|
|
17
17
|
const SHELL_META = /[\r\n;&|`<>$]/
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* 平台自身凭据:不得随 process.env 继承给 harness 子进程。
|
|
21
|
+
* 引擎需要的 provider key 与 AW_ 身份变量由各 impl 的显式 env 传入(cleanEnv 或 bridgeEnv),
|
|
22
|
+
* 这里只剥离"平台会话/管理员口令/隧道令牌"这类与引擎无关的秘密。
|
|
23
|
+
*/
|
|
24
|
+
const PLATFORM_SECRET_ENV = [
|
|
25
|
+
'NUXT_SESSION_PASSWORD',
|
|
26
|
+
'AW_ADMIN_PASSWORD',
|
|
27
|
+
'AW_E2E_ADMIN_PASSWORD',
|
|
28
|
+
'AW_E2E_PASSWORD',
|
|
29
|
+
'AW_E2E_TOKEN',
|
|
30
|
+
'AW_E2E_ADMIN_TOKEN',
|
|
31
|
+
'SCHED_E2E_PASSWORD',
|
|
32
|
+
'AW_TUI_PASSWORD',
|
|
33
|
+
'ADMIN_TOKEN',
|
|
34
|
+
'CLOUDFLARE_TUNNEL_TOKEN',
|
|
35
|
+
] as const
|
|
36
|
+
|
|
37
|
+
function scrubPlatformSecrets(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
38
|
+
const deny = new Set<string>(PLATFORM_SECRET_ENV)
|
|
39
|
+
return Object.fromEntries(Object.entries(env).filter(([k]) => !deny.has(k)))
|
|
40
|
+
}
|
|
41
|
+
|
|
19
42
|
/** 拒绝 shell 元字符(命令只能是纯可执行路径) */
|
|
20
43
|
export function assertPlainExecutable(command: string): string {
|
|
21
44
|
if (!command || SHELL_META.test(command)) {
|
|
@@ -87,7 +110,7 @@ export function spawnLineProcess(command: string, args: string[], options: LineS
|
|
|
87
110
|
const { file, needsCmd } = resolveExecutable(command)
|
|
88
111
|
const env = options.cleanEnv
|
|
89
112
|
? { ...options.env }
|
|
90
|
-
: { ...process.env, ...options.env }
|
|
113
|
+
: scrubPlatformSecrets({ ...process.env, ...options.env })
|
|
91
114
|
if (needsCmd) {
|
|
92
115
|
// Windows .cmd shim:固定包装器 'cmd.exe' + /d /s /c。
|
|
93
116
|
// 可执行文件路径无条件引号包裹:无空格路径裸奔时,/s 模式的 cmd 会吞掉
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent 对外 DTO —— HTTP 响应不得回显 token 与敏感 config。
|
|
3
|
+
*
|
|
4
|
+
* 背景(2026-10-28 审计):`instanceToAgentInfo` 直出 `token` 与完整 `config`,
|
|
5
|
+
* `/channels/:id/agents` 对"本 channel 任意成员(含 agent token)"放行 →
|
|
6
|
+
* worker Agent 可读取 lead 的 token,再以 lead 身份调用 agent-tools/invoke,
|
|
7
|
+
* 完整继承 lead 的工业绑定与 lead 专属权限。
|
|
8
|
+
*
|
|
9
|
+
* 约定:
|
|
10
|
+
* - token 永不进列表/详情;只在 rotate-token 一次性返回。
|
|
11
|
+
* - config 仅 channel 属主/admin 可见(UI 的成员编辑/专长展示需要),
|
|
12
|
+
* 且剔除启动类敏感键(command/args/cwd/env)。
|
|
13
|
+
* - 其余调用方只拿 summary(id/name/role/harness/enabled/templateId)。
|
|
14
|
+
*/
|
|
15
|
+
import type { AgentInfo } from './agent-interface'
|
|
16
|
+
|
|
17
|
+
const SENSITIVE_CONFIG_KEYS = ['command', 'args', 'cwd', 'env'] as const
|
|
18
|
+
|
|
19
|
+
export interface ChannelAgentSummary {
|
|
20
|
+
id: string
|
|
21
|
+
channelId: string
|
|
22
|
+
name: string
|
|
23
|
+
harness: string
|
|
24
|
+
role: string
|
|
25
|
+
enabled: number
|
|
26
|
+
templateId: string | null
|
|
27
|
+
config?: Record<string, unknown>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function safeConfig(config: Record<string, unknown> | undefined | null): Record<string, unknown> {
|
|
31
|
+
if (!config || typeof config !== 'object') return {}
|
|
32
|
+
const deny = new Set<string>(SENSITIVE_CONFIG_KEYS)
|
|
33
|
+
return Object.fromEntries(Object.entries(config).filter(([k]) => !deny.has(k)))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 名册投影(token 永远不出现) */
|
|
37
|
+
export function channelAgentSummary(agent: AgentInfo, opts: { includeConfig?: boolean } = {}): ChannelAgentSummary {
|
|
38
|
+
const summary: ChannelAgentSummary = {
|
|
39
|
+
id: agent.id,
|
|
40
|
+
channelId: agent.channelId,
|
|
41
|
+
name: agent.name,
|
|
42
|
+
harness: agent.harness,
|
|
43
|
+
role: agent.role,
|
|
44
|
+
enabled: agent.enabled ?? 1,
|
|
45
|
+
templateId: agent.templateId ?? null,
|
|
46
|
+
}
|
|
47
|
+
if (opts.includeConfig) summary.config = safeConfig(agent.config)
|
|
48
|
+
return summary
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** 批量投影 */
|
|
52
|
+
export function channelAgentSummaries(agents: AgentInfo[], opts: { includeConfig?: boolean } = {}): ChannelAgentSummary[] {
|
|
53
|
+
return agents.map(a => channelAgentSummary(a, opts))
|
|
54
|
+
}
|