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
|
@@ -1,190 +1,204 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RecipeRollBackManagerRollback —— 分级回退(全部经 controller.write 单点)
|
|
3
|
-
* (拆分层,承 RecipeRollBackManagerJudge;方法体与原文件逐行一致)
|
|
4
|
-
*/
|
|
5
|
-
import { RecipeRollBackManagerJudge } from './judge'
|
|
6
|
-
import type { DcwWriteMeta, OptimizationRecord } from '../../../../../shared/dcw-protocol'
|
|
7
|
-
import { AppError, ErrorCodes } from '../../../../utils/errors'
|
|
8
|
-
import { COOLDOWN_MS } from './helpers'
|
|
9
|
-
import { getDcwNodeRepo } from '../dcw-node.repo'
|
|
10
|
-
import { getDcwRecipeRepo } from '../dcw-recipe.repo'
|
|
11
|
-
import { recordOps } from '../../ops/ops'
|
|
12
|
-
|
|
13
|
-
export abstract class RecipeRollBackManagerRollback extends RecipeRollBackManagerJudge {
|
|
14
|
-
/** 回退一条优化记录:目标 = 该记录的 from 值(设定前基线) */
|
|
15
|
-
async rollbackRecord(recordId: string, actor: string, by: 'agent' | 'user' | 'system', approvalId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
|
|
16
|
-
const record = this.repo.byId(recordId)
|
|
17
|
-
if (!record)
|
|
18
|
-
throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${recordId}`)
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
protected
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
1
|
+
/**
|
|
2
|
+
* RecipeRollBackManagerRollback —— 分级回退(全部经 controller.write 单点)
|
|
3
|
+
* (拆分层,承 RecipeRollBackManagerJudge;方法体与原文件逐行一致)
|
|
4
|
+
*/
|
|
5
|
+
import { RecipeRollBackManagerJudge } from './judge'
|
|
6
|
+
import type { DcwWriteMeta, OptimizationRecord } from '../../../../../shared/dcw-protocol'
|
|
7
|
+
import { AppError, ErrorCodes } from '../../../../utils/errors'
|
|
8
|
+
import { COOLDOWN_MS } from './helpers'
|
|
9
|
+
import { getDcwNodeRepo } from '../dcw-node.repo'
|
|
10
|
+
import { getDcwRecipeRepo } from '../dcw-recipe.repo'
|
|
11
|
+
import { recordOps } from '../../ops/ops'
|
|
12
|
+
|
|
13
|
+
export abstract class RecipeRollBackManagerRollback extends RecipeRollBackManagerJudge {
|
|
14
|
+
/** 回退一条优化记录:目标 = 该记录的 from 值(设定前基线) */
|
|
15
|
+
async rollbackRecord(recordId: string, actor: string, by: 'agent' | 'user' | 'system', approvalId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
|
|
16
|
+
const record = this.repo.byId(recordId)
|
|
17
|
+
if (!record)
|
|
18
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${recordId}`)
|
|
19
|
+
// 2026-10-28:回退写自身会生成 open 记录(from=回退前的问题值),再回退它会写回问题值。
|
|
20
|
+
if (record.rollbackOf) {
|
|
21
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId} 是一次回退产生的记录,不允许再次作为回退目标(会把回退前的问题值写回)。请对节点/批次重新发起调控。`)
|
|
22
|
+
}
|
|
23
|
+
const from = record.params[0]?.from
|
|
24
|
+
if (from == null)
|
|
25
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId} 无基线值(首写无 prevValue),无法回退`)
|
|
26
|
+
if (by === 'agent')
|
|
27
|
+
this.checkRollbackAllowed(record.nodeId)
|
|
28
|
+
return this.executeRollbackWrite(record, from, actor, approvalId, undefined, by, opts?.actorName)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** 节点级单步回退:目标 = 最近稳定锚的 prevValue(撤销栈栈顶) */
|
|
32
|
+
async rollbackNode(nodeId: string, actor: string, by: 'agent' | 'user' | 'system', toAnchorId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
|
|
33
|
+
const node = getDcwNodeRepo().byId(nodeId)
|
|
34
|
+
if (!node)
|
|
35
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `控制节点不存在: ${nodeId}`)
|
|
36
|
+
// 2026-10-28:回退目标必须来自"正常写"的稳定锚。若最新锚本身就是回退写
|
|
37
|
+
// (prev=坏值,new=恢复值),直接取 prevValue 会把坏值再写回去。
|
|
38
|
+
const anchor = toAnchorId
|
|
39
|
+
? this.repo.anchorById(toAnchorId)
|
|
40
|
+
: this.repo.listAnchors({ nodeId, limit: 200 }).find(a => a.source !== 'rollback' && a.prevValue != null && a.prevValue !== a.newValue)
|
|
41
|
+
if (!anchor)
|
|
42
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `节点「${node.name}」无可回退锚(账本无 prevValue≠newValue 的正常写历史)`)
|
|
43
|
+
if (anchor.nodeId !== nodeId) {
|
|
44
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `目标锚 ${anchor.id} 属于节点 ${anchor.nodeId},不能用于节点 ${nodeId} 的回退`)
|
|
45
|
+
}
|
|
46
|
+
if (anchor.prevValue == null)
|
|
47
|
+
throw new AppError(409, ErrorCodes.CONFLICT, '目标锚无基线值(首写锚),无法回退')
|
|
48
|
+
if (typeof node.value === 'number' && anchor.prevValue === node.value && by !== 'agent') {
|
|
49
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `节点「${node.name}」当前值已是回退目标 ${anchor.prevValue}${node.unit || ''},无需回退`)
|
|
50
|
+
}
|
|
51
|
+
if (by === 'agent')
|
|
52
|
+
this.checkRollbackAllowed(nodeId)
|
|
53
|
+
return this.executeRollbackWrite(
|
|
54
|
+
{
|
|
55
|
+
id: `node:${nodeId}`,
|
|
56
|
+
nodeId,
|
|
57
|
+
nodeName: node.name,
|
|
58
|
+
lineId: node.lineId,
|
|
59
|
+
params: [{ nodeId, templateRef: node.templateRef, from: anchor.prevValue, to: anchor.newValue }],
|
|
60
|
+
} as unknown as OptimizationRecord,
|
|
61
|
+
anchor.prevValue,
|
|
62
|
+
actor,
|
|
63
|
+
undefined,
|
|
64
|
+
toAnchorId,
|
|
65
|
+
by,
|
|
66
|
+
opts?.actorName,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** 批次级回退:恢复该 run 涉及节点在 run.startedAt 之前的值(撤销这次实验) */
|
|
71
|
+
async rollbackRun(runId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
|
|
72
|
+
const run = getDcwRecipeRepo().runById(runId)
|
|
73
|
+
if (!run)
|
|
74
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `批次不存在: ${runId}`)
|
|
75
|
+
const startedMs = Date.parse(run.startedAt)
|
|
76
|
+
const nodeIds = [...new Set(run.results.map(r => r.nodeId).filter((v): v is string => !!v))]
|
|
77
|
+
const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
|
|
78
|
+
for (const nodeId of nodeIds) {
|
|
79
|
+
const anchor = this.repo.lastStableBefore(nodeId, startedMs)
|
|
80
|
+
if (!anchor || anchor.prevValue == null) {
|
|
81
|
+
outcomes.push({ nodeId, ok: false, message: '无批次前基线锚,跳过' })
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
await this.writeViaController(nodeId, anchor.prevValue, { source: 'rollback', actor, hypothesis: `批次 ${runId} 撤销:恢复 ${anchor.prevValue}` })
|
|
86
|
+
outcomes.push({ nodeId, ok: true, message: `已恢复 ${anchor.prevValue}` })
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
outcomes.push({ nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return outcomes
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 基准恢复:重新下发 lastGood 批次冻结的参数集 */
|
|
96
|
+
async rollbackRecipeGood(recipeId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
|
|
97
|
+
const recipe = getDcwRecipeRepo().byId(recipeId)
|
|
98
|
+
if (!recipe)
|
|
99
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `Recipe 不存在: ${recipeId}`)
|
|
100
|
+
if (!recipe.lastGoodRunId)
|
|
101
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `配方「${recipe.name}」未标记已知良好批次(先 mark-good)`)
|
|
102
|
+
const run = getDcwRecipeRepo().runById(recipe.lastGoodRunId)
|
|
103
|
+
const snapshot = run?.paramsSnapshot
|
|
104
|
+
if (!snapshot || snapshot.length === 0)
|
|
105
|
+
throw new AppError(409, ErrorCodes.CONFLICT, '良好批次无参数快照(建批早于版本化),无法基准恢复')
|
|
106
|
+
const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
|
|
107
|
+
for (const p of snapshot) {
|
|
108
|
+
try {
|
|
109
|
+
await this.writeViaController(p.nodeId, p.value, { source: 'rollback', actor, hypothesis: `基准恢复 ${recipe.name}(良好批次 ${recipe.lastGoodRunId})` })
|
|
110
|
+
outcomes.push({ nodeId: p.nodeId, ok: true, message: `已恢复 ${p.value}` })
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
outcomes.push({ nodeId: p.nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return outcomes
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** 判定回退的执行入口:关闭原记录(rolled-back)+ 反向下发产生新回退记录。
|
|
120
|
+
* 状态语义:'rolled-back' 只在回读校验通过后落定;下发期间先置 'judged'(防 afterWrite 误 supersede),
|
|
121
|
+
* 下发失败则如实停在 'judged' 并把失败原因写进 judge.reason。 */
|
|
122
|
+
protected async executeRollbackWrite(
|
|
123
|
+
record: Pick<OptimizationRecord, 'id' | 'nodeId' | 'nodeName' | 'lineId' | 'params'>,
|
|
124
|
+
target: number,
|
|
125
|
+
actor: string,
|
|
126
|
+
approvalId?: string,
|
|
127
|
+
toAnchorId?: string,
|
|
128
|
+
by: 'agent' | 'user' | 'system' = 'system',
|
|
129
|
+
actorName?: string,
|
|
130
|
+
): Promise<OptimizationRecord> {
|
|
131
|
+
// 先关原记录(防回退写自身的 afterWrite 把它当 open supersede)
|
|
132
|
+
const orig = this.repo.byId(record.id)
|
|
133
|
+
const wasOpen = orig?.status === 'open'
|
|
134
|
+
if (orig && wasOpen) {
|
|
135
|
+
orig.judge ??= { by: 'system', actor, verdict: 'rollback', reason: '执行回退', at: new Date().toISOString() }
|
|
136
|
+
this.closeRecord(orig, 'judged')
|
|
137
|
+
orig.status = 'judged'
|
|
138
|
+
this.repo.updateRecord(orig.id, { status: 'judged', judge: orig.judge, closedAt: orig.closedAt, closedBy: orig.closedBy, windowAgg: orig.windowAgg })
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
await this.writeViaController(record.nodeId, target, {
|
|
142
|
+
source: 'rollback',
|
|
143
|
+
actor,
|
|
144
|
+
hypothesis: `回退 ${record.id}:恢复 ${target}`,
|
|
145
|
+
rollbackOf: record.id.startsWith('node:') ? undefined : record.id,
|
|
146
|
+
}, approvalId, toAnchorId)
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
if (orig && wasOpen) {
|
|
150
|
+
const reason = err instanceof Error ? err.message : String(err)
|
|
151
|
+
orig.judge = { ...orig.judge!, reason: `${orig.judge!.reason};回退下发失败:${reason}`, at: orig.judge!.at }
|
|
152
|
+
this.repo.updateRecord(orig.id, { judge: orig.judge })
|
|
153
|
+
}
|
|
154
|
+
throw err
|
|
155
|
+
}
|
|
156
|
+
if (orig && wasOpen) {
|
|
157
|
+
orig.status = 'rolled-back'
|
|
158
|
+
this.repo.updateRecord(orig.id, { status: 'rolled-back' })
|
|
159
|
+
this.emit('rolled-back', orig)
|
|
160
|
+
recordOps({
|
|
161
|
+
actor,
|
|
162
|
+
actorName: actorName ?? actor,
|
|
163
|
+
actorKind: by === 'agent' ? 'agent' : by === 'user' ? 'user' : 'system',
|
|
164
|
+
action: 'optimization.rollback',
|
|
165
|
+
kind: 'rollback',
|
|
166
|
+
targetKind: 'optimization',
|
|
167
|
+
targetId: record.id,
|
|
168
|
+
summary: `回退完成:「${record.nodeName ?? record.nodeId}」已恢复 ${target}${record.id.startsWith('node:') ? '' : `(记录 ${record.id})`}`,
|
|
169
|
+
lineId: record.lineId ?? '',
|
|
170
|
+
recipeId: (record as { recipeId?: string }).recipeId ?? '',
|
|
171
|
+
detail: { recordId: record.id, target },
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
const fresh = this.repo.listRecords({ nodeId: record.nodeId, limit: 1 })[0]
|
|
175
|
+
return fresh!
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
protected async writeViaController(nodeId: string, eng: number, meta: DcwWriteMeta & { rollbackOf?: string }, approvalId?: string, toAnchorId?: string): Promise<void> {
|
|
179
|
+
const { getDcwController } = await import('../dcw-controller')
|
|
180
|
+
const outcome = await getDcwController().write(nodeId, eng, null, meta)
|
|
181
|
+
if (outcome.ok === false)
|
|
182
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `回退下发未通过回读校验: ${outcome.message}`)
|
|
183
|
+
if (toAnchorId || approvalId) {
|
|
184
|
+
const anchor = toAnchorId ? this.repo.anchorById(toAnchorId) : undefined
|
|
185
|
+
if (anchor && approvalId)
|
|
186
|
+
anchor.approvalId = approvalId
|
|
187
|
+
this.repo.flushNow()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Agent 回退护栏:冷却(用户/系统兜底不受链限) */
|
|
192
|
+
protected checkRollbackAllowed(nodeId: string): void {
|
|
193
|
+
const rb = this.repo.lastRollbackAnchor(nodeId)
|
|
194
|
+
if (rb) {
|
|
195
|
+
const elapsed = Date.now() - Date.parse(rb.at)
|
|
196
|
+
if (elapsed < COOLDOWN_MS())
|
|
197
|
+
throw new AppError(409, ErrorCodes.CONFLICT, `回退冷却中:节点 ${Math.ceil((COOLDOWN_MS() - elapsed) / 1000)}s 内禁止再次回退`)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ================================================================
|
|
202
|
+
// 系统兜底评估(挂 sweep() 节拍;F1)
|
|
203
|
+
// ================================================================
|
|
204
|
+
}
|
|
@@ -1,77 +1,97 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RecipeRollBackManagerSweep —— 系统兜底评估(按 sweep 节拍)
|
|
3
|
-
* (拆分层,承 RecipeRollBackManagerRollback;方法体与原文件逐行一致)
|
|
4
|
-
*/
|
|
5
|
-
import { RecipeRollBackManagerRollback } from './rollback'
|
|
6
|
-
import type { OptimizationRecord } from '../../../../../shared/dcw-protocol'
|
|
7
|
-
import { BREACH_THRESHOLD, MAX_AUTO_ROLLBACKS, MIN_WINDOW_MS, RECHECK_MS } from './helpers'
|
|
8
|
-
import { recordOps } from '../../ops/ops'
|
|
9
|
-
|
|
10
|
-
export abstract class RecipeRollBackManagerSweep extends RecipeRollBackManagerRollback {
|
|
11
|
-
evaluateOpenRecords(now: number): void {
|
|
12
|
-
// 走 open 索引(O(open))而非 listRecords 的「全量倒序 + limit 500」:
|
|
13
|
-
// 后者在 open 记录 >500 时会**静默漏评估**,且每次 sweep 都对全量 records 做一次拷贝。
|
|
14
|
-
for (const record of this.repo.listOpenRecords()) {
|
|
15
|
-
if (record.policy === 'observe_only')
|
|
16
|
-
continue
|
|
17
|
-
const setMs = Date.parse(record.setAt)
|
|
18
|
-
if (now - setMs < MIN_WINDOW_MS())
|
|
19
|
-
continue
|
|
20
|
-
if (record.evaluatedAt && now - Date.parse(record.evaluatedAt) < RECHECK_MS)
|
|
21
|
-
continue
|
|
22
|
-
record.evaluatedAt = new Date(now).toISOString()
|
|
23
|
-
void this.evaluateOnce(record)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
protected async evaluateOnce(record: OptimizationRecord): Promise<void> {
|
|
28
|
-
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
record.judge = {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
1
|
+
/**
|
|
2
|
+
* RecipeRollBackManagerSweep —— 系统兜底评估(按 sweep 节拍)
|
|
3
|
+
* (拆分层,承 RecipeRollBackManagerRollback;方法体与原文件逐行一致)
|
|
4
|
+
*/
|
|
5
|
+
import { RecipeRollBackManagerRollback } from './rollback'
|
|
6
|
+
import type { OptimizationRecord } from '../../../../../shared/dcw-protocol'
|
|
7
|
+
import { BREACH_THRESHOLD, MAX_AUTO_ROLLBACKS, MIN_WINDOW_MS, RECHECK_MS } from './helpers'
|
|
8
|
+
import { recordOps } from '../../ops/ops'
|
|
9
|
+
|
|
10
|
+
export abstract class RecipeRollBackManagerSweep extends RecipeRollBackManagerRollback {
|
|
11
|
+
evaluateOpenRecords(now: number): void {
|
|
12
|
+
// 走 open 索引(O(open))而非 listRecords 的「全量倒序 + limit 500」:
|
|
13
|
+
// 后者在 open 记录 >500 时会**静默漏评估**,且每次 sweep 都对全量 records 做一次拷贝。
|
|
14
|
+
for (const record of this.repo.listOpenRecords()) {
|
|
15
|
+
if (record.policy === 'observe_only')
|
|
16
|
+
continue
|
|
17
|
+
const setMs = Date.parse(record.setAt)
|
|
18
|
+
if (now - setMs < MIN_WINDOW_MS())
|
|
19
|
+
continue
|
|
20
|
+
if (record.evaluatedAt && now - Date.parse(record.evaluatedAt) < RECHECK_MS)
|
|
21
|
+
continue
|
|
22
|
+
record.evaluatedAt = new Date(now).toISOString()
|
|
23
|
+
void this.evaluateOnce(record)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected async evaluateOnce(record: OptimizationRecord): Promise<void> {
|
|
28
|
+
try {
|
|
29
|
+
// 2026-10-28:回退写产生的记录不再参与自动兜底 —— 否则"回退的回退"会写回问题值。
|
|
30
|
+
if (record.rollbackOf) return
|
|
31
|
+
const from = Date.parse(record.setAt)
|
|
32
|
+
const agg = await this.captureMetrics(record.nodeId, record.lineId, record.recipeId, from, Date.now())
|
|
33
|
+
// B-P1-1(2026-10-28 审查):captureMetrics 是跨 await 的长查询 —— 期间世界已变。
|
|
34
|
+
// 判定/执行前必须重验"这条记录还是不是当前该行动的那条",否则会:
|
|
35
|
+
// ① 覆盖人工已下的 uncertain/判词(推翻人的裁决);
|
|
36
|
+
// ② 记录已被关闭/被执行(重复物理写);
|
|
37
|
+
// ③ 同节点已有更新的写意图接管(按旧值回退,把最新意图冲掉)。
|
|
38
|
+
// 三者任一发生都只补记聚合(windowAgg)并返回,绝不产生任何写入。
|
|
39
|
+
const latest = this.repo.byId(record.id)
|
|
40
|
+
if (!latest || latest.status !== 'open' || latest.judge) {
|
|
41
|
+
if (latest?.status === 'open') {
|
|
42
|
+
this.repo.updateRecord(latest.id, { evaluatedAt: latest.evaluatedAt, windowAgg: latest.windowAgg ?? agg })
|
|
43
|
+
}
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
const current = this.repo.openRecordOf(record.nodeId)
|
|
47
|
+
if (!current || current.id !== record.id) {
|
|
48
|
+
this.repo.updateRecord(latest.id, { evaluatedAt: latest.evaluatedAt, windowAgg: latest.windowAgg ?? agg })
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
const totalBreaches = agg.channels.reduce((sum, c) => sum + Math.max(0, c.breaches), 0)
|
|
52
|
+
if (totalBreaches < BREACH_THRESHOLD) {
|
|
53
|
+
this.repo.updateRecord(record.id, { evaluatedAt: record.evaluatedAt, windowAgg: record.windowAgg ?? agg })
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
const reason = `观察窗内数采越配方监控窗累计 ${totalBreaches} 采样(阈值 ${BREACH_THRESHOLD}),系统兜底判定回退`
|
|
57
|
+
if (record.policy === 'auto_rollback' && this.repo.chainRollbackCount(record.nodeId) < MAX_AUTO_ROLLBACKS) {
|
|
58
|
+
record.judge = { by: 'system', actor: 'system', verdict: 'rollback', reason, at: new Date().toISOString() }
|
|
59
|
+
this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
|
|
60
|
+
this.emit('judged', record)
|
|
61
|
+
recordOps({
|
|
62
|
+
actor: 'system',
|
|
63
|
+
actorName: 'system',
|
|
64
|
+
actorKind: 'system',
|
|
65
|
+
action: 'optimization.judge',
|
|
66
|
+
kind: 'rollback',
|
|
67
|
+
targetKind: 'optimization',
|
|
68
|
+
targetId: record.id,
|
|
69
|
+
summary: `系统兜底判定回退:窗口内累计越限 ${totalBreaches} 采样,自动恢复基线`,
|
|
70
|
+
lineId: record.lineId ?? '',
|
|
71
|
+
recipeId: record.recipeId ?? '',
|
|
72
|
+
detail: { breaches: totalBreaches, policy: record.policy },
|
|
73
|
+
})
|
|
74
|
+
await this.rollbackRecord(record.id, 'system', 'system')
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// approve_rollback 或自动回退链达上限:提议人工确认(判定入册,执行等 REST/工具)
|
|
78
|
+
record.judge = {
|
|
79
|
+
by: 'system',
|
|
80
|
+
actor: 'system',
|
|
81
|
+
verdict: 'rollback',
|
|
82
|
+
reason: `${reason};${record.policy === 'approve_rollback' ? '等待人工确认' : '自动回退链达上限,升级人工'}`,
|
|
83
|
+
at: new Date().toISOString(),
|
|
84
|
+
}
|
|
85
|
+
this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
|
|
86
|
+
this.emit('judged', record)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error('[recipe-rollback] 兜底评估失败:', record.id, err)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ================================================================
|
|
95
|
+
// 数据面:窗口聚合 / 台账 / 序列(全部复用 lineQuery 参数化查询)
|
|
96
|
+
// ================================================================
|
|
97
|
+
}
|