agentworkshop 0.7.71 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.AgentWorkShop/prompts/host-tools.json +332 -0
- package/.output/.AgentWorkShop/prompts/host-tools.json +332 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/BH8RvpVy.js +1 -0
- package/.output/public/_nuxt/Byf4IxU2.js +14 -0
- package/.output/public/_nuxt/CxVhG0Xx.js +1 -0
- package/.output/public/_nuxt/D0mzKkZr.js +1 -0
- package/.output/public/_nuxt/DIFkTkdS.js +1 -0
- package/.output/public/_nuxt/DgrK8UCQ.js +0 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/7a79a7e4-d691-4cf5-ae3a-3b01814479fb.json +1 -0
- package/.output/public/_nuxt/{default.BzOcvmSE.css → default.BEXGWZFQ.css} +1 -1
- package/.output/public/_nuxt/{entry.CL2i0F8o.css → entry.C7koBPom.css} +1 -1
- package/.output/public/_nuxt/ontology.QMGeh66l.css +1 -0
- package/.output/server/chunks/_/access.mjs +1 -1
- package/.output/server/chunks/_/binding-authz.mjs +1 -1
- package/.output/server/chunks/_/catalog-view.mjs +1 -1
- package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
- package/.output/server/chunks/_/chart-repo.mjs +1 -1
- package/.output/server/chunks/_/dashboard-repo.mjs +1 -1
- 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/_/entity.mjs +1 -1
- package/.output/server/chunks/_/features.mjs +5 -5
- package/.output/server/chunks/_/golden.mjs +3 -3
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/index.mjs +1 -1
- package/.output/server/chunks/_/mes-console.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +5362 -2240
- 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/_/scene-layout.repo.mjs +1 -1
- package/.output/server/chunks/_/spc.mjs +2 -2
- package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
- package/.output/server/chunks/build/api-BEW_ebY_.mjs +64 -0
- package/.output/server/chunks/build/api-BEW_ebY_.mjs.map +1 -0
- package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
- package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
- package/.output/server/chunks/build/{default-BeB88U7y.mjs → default-CJkOcmrm.mjs} +14 -8
- package/.output/server/chunks/build/{default-BeB88U7y.mjs.map → default-CJkOcmrm.mjs.map} +1 -1
- package/.output/server/chunks/build/ontology-C3HS5pMo.mjs +977 -0
- package/.output/server/chunks/build/ontology-C3HS5pMo.mjs.map +1 -0
- package/.output/server/chunks/build/types-D6J7slEa.mjs +6 -2
- 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/approvals/_id/decide.post.mjs +17 -4
- package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index4.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/cancel.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/logs.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/retry.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/models/_id/predict.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/models/_id/promote.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/models/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index2.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/members/join.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/tools/reset.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +7 -7
- package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +2 -2
- package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/export/_id_.get.mjs +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 +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 +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 +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +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 +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 +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 +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 +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 +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index7.get.mjs +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/lines/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs +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 +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +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/mark-good.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.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 +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +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 +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/commonality.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/features/run.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index6.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/runs/_id/labels.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/runs.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 +62 -0
- package/.output/server/chunks/routes/api/workshop/index.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index10.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index11.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index12.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.post.mjs +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/index6.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/datasets.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/preview.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +54 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +51 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +67 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +49 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +35 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +49 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +35 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.mjs +70 -0
- package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +64 -0
- package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +44 -0
- package/.output/server/chunks/routes/api/workshop/ontology/index.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +36 -0
- package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +38 -0
- package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +40 -0
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +63 -0
- package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs.map +1 -0
- 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/experiments.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/teams/_id/deploy.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tools/_name_.get.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 +2 -2
- package/.output/server/chunks/routes/renderer.mjs +2 -2
- package/.output/server/chunks/virtual/entry.mjs +234 -3
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +27 -6
- package/README.md +25 -4
- package/app/components/AppSidebar.vue +1 -0
- package/app/pages/ontology/api.ts +18 -0
- package/app/pages/ontology/index.vue +779 -0
- package/app/pages/ontology/types.ts +122 -0
- package/config.yml +1 -1
- package/docs/cli.en.md +2 -2
- package/docs/cli.md +2 -2
- package/docs/plugins.en.md +1 -1
- package/docs/plugins.md +1 -1
- package/docs/sdk.en.md +1 -1
- package/docs/sdk.md +1 -1
- package/i18n/locales/en.ts +58 -0
- package/i18n/locales/zh-CN.ts +58 -0
- package/mcp/aw-mcp-server.mjs +35 -1
- package/package.json +1 -1
- package/scripts/docs-shots.mjs +36 -0
- package/scripts/e2e-model-loop-live.mjs +731 -0
- package/scripts/e2e-ontology-live.mjs +774 -0
- package/scripts/e2e-ontology.mjs +328 -0
- package/scripts/ontology-idd-rag-e2e.mjs +449 -0
- package/server/api/workshop/agent-tools/approvals/[id]/decide.post.ts +16 -0
- package/server/api/workshop/ontology/drafts/[draftId]/compile.ts +39 -0
- package/server/api/workshop/ontology/drafts/[draftId]/evidence.ts +33 -0
- package/server/api/workshop/ontology/drafts/[draftId]/publish.ts +44 -0
- package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/approval-decision.ts +28 -0
- package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/approval.ts +17 -0
- package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/transition.ts +32 -0
- package/server/api/workshop/ontology/drafts/[draftId]/validate.ts +16 -0
- package/server/api/workshop/ontology/drafts/[draftId].ts +52 -0
- package/server/api/workshop/ontology/drafts/index.ts +20 -0
- package/server/api/workshop/ontology/export/[ontologyId].ts +50 -0
- package/server/api/workshop/ontology/index.ts +38 -0
- package/server/api/workshop/ontology/scene.ts +21 -0
- package/server/api/workshop/ontology/traces/[ontologyId].ts +19 -0
- package/server/api/workshop/ontology/versions/[ontologyId]/compare.ts +21 -0
- package/server/api/workshop/ontology/versions/[ontologyId].ts +42 -0
- package/server/services/workshop/agents/hitl-decision/dispatcher.ts +15 -0
- package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +13 -1
- package/server/services/workshop/agents/industrial/grant-guard.ts +59 -0
- package/server/services/workshop/agents/industrial/index.ts +38 -32
- package/server/services/workshop/agents/industrial/ontology-tools.ts +320 -0
- package/server/services/workshop/agents/industrial/optimizer-tools.ts +79 -0
- package/server/services/workshop/agents/industrial/tool-verify.ts +32 -2
- package/server/services/workshop/agents/tool-reference-spec.ts +1 -1
- package/server/services/workshop/aml/twin/physics-spec.ts +6 -22
- package/server/services/workshop/daq/storage/index.ts +6 -5
- package/server/services/workshop/daq/storage/sqlite.adapter.ts +25 -13
- package/server/services/workshop/db/database/open.ts +2 -0
- package/server/services/workshop/db/database/schema.ts +155 -1
- package/server/services/workshop/ontology/compiler.ts +474 -0
- package/server/services/workshop/ontology/contracts.ts +441 -0
- package/server/services/workshop/ontology/guards.ts +139 -0
- package/server/services/workshop/ontology/index.ts +10 -0
- package/server/services/workshop/ontology/ontology.service.ts +892 -0
- package/server/services/workshop/ontology/repo.ts +449 -0
- package/server/services/workshop/ontology/semantic-binding.service.ts +226 -0
- package/server/services/workshop/ontology/validator.ts +218 -0
- package/server/services/workshop/optimization/binding.repo.ts +7 -0
- package/server/services/workshop/optimization/contracts.ts +14 -0
- package/server/services/workshop/optimization/dispatch.service.ts +16 -0
- package/server/services/workshop/optimization/profile-adopt.service.ts +256 -0
- package/server/services/workshop/optimization/profile.repo.ts +19 -3
- package/server/services/workshop/optimization/python/__pycache__/problems.cpython-312.pyc +0 -0
- package/shared/dimensions.ts +124 -0
- package/.output/public/_nuxt/B7s2qeyT.js +0 -14
- package/.output/public/_nuxt/LHIav-Kv.js +0 -1
- package/.output/public/_nuxt/RuMLNeQE.js +0 -1
- package/.output/public/_nuxt/builds/meta/0ae8cb0f-6ce5-4096-9692-9b1fc197b30d.json +0 -1
- /package/.output/public/_nuxt/{62J4vljm2.js → 62J4vljm.js} +0 -0
- /package/.output/public/_nuxt/{BO0BJx3w.js → BO0BJx3w2.js} +0 -0
- /package/.output/public/_nuxt/{C-MY-JQE2.js → C-MY-JQE.js} +0 -0
- /package/.output/public/_nuxt/{D5kCimyw.js → D5kCimyw2.js} +0 -0
- /package/.output/public/_nuxt/{DGrrucbG2.js → DGrrucbG.js} +0 -0
- /package/.output/public/_nuxt/{Y4sMSPrS.js → Y4sMSPrS2.js} +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本体文档校验(零 DB 纯函数,可单测)。
|
|
3
|
+
*
|
|
4
|
+
* 只做结构/语义自洽判定;存在性、归属、读写能力等「活体」判定在
|
|
5
|
+
* semantic-binding.service(需要查 daq/dcw/recipe 真实对象)。
|
|
6
|
+
*
|
|
7
|
+
* fail-closed 原则:每条问题都带可行动 hint,禁止静默降级。
|
|
8
|
+
*/
|
|
9
|
+
import type { CompileIssue, EvidenceLevel, OntologyDraftDoc, OntologyEntity, OntologyRule } from './contracts'
|
|
10
|
+
import {
|
|
11
|
+
ONTOLOGY_STATES,
|
|
12
|
+
RULE_ERROR_CODES,
|
|
13
|
+
entityUnitIssue,
|
|
14
|
+
evidenceLevelRank,
|
|
15
|
+
maxEvidenceLevel,
|
|
16
|
+
unitsCompatible,
|
|
17
|
+
} from './contracts'
|
|
18
|
+
|
|
19
|
+
export interface DraftStats {
|
|
20
|
+
entities: number
|
|
21
|
+
relations: number
|
|
22
|
+
rules: number
|
|
23
|
+
bindings: number
|
|
24
|
+
byState: Record<string, number>
|
|
25
|
+
byEvidence: Record<string, number>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DraftValidationReport {
|
|
29
|
+
ok: boolean
|
|
30
|
+
issues: CompileIssue[]
|
|
31
|
+
stats: DraftStats
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function issue(code: string, path: string, message: string, severity: 'error' | 'warning' = 'error', hint?: string, ruleId?: string): CompileIssue {
|
|
35
|
+
return { code, path, message, severity, hint, ruleId }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 规则 DSL 里出现的全部变量引用 */
|
|
39
|
+
export function ruleVariableRefs(rule: OntologyRule): string[] {
|
|
40
|
+
const dsl = rule.dsl
|
|
41
|
+
switch (dsl.type) {
|
|
42
|
+
case 'bound': return [dsl.variableKey]
|
|
43
|
+
case 'rate': return [dsl.variableKey]
|
|
44
|
+
case 'linear_coupling': return [dsl.variableKey, dsl.ofKey]
|
|
45
|
+
case 'nonlinear': return [dsl.variableKey]
|
|
46
|
+
case 'state_condition': return [dsl.when.variableKey, dsl.forbid.variableKey]
|
|
47
|
+
case 'interlock': return dsl.variableKey ? [dsl.variableKey] : []
|
|
48
|
+
case 'informal': return []
|
|
49
|
+
default: return []
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 规则证据能支持的最强级别 */
|
|
54
|
+
export function ruleEvidenceLevel(rule: OntologyRule): EvidenceLevel | '' {
|
|
55
|
+
return maxEvidenceLevel(rule.evidence.map(e => e.level))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function validateDraftDoc(doc: OntologyDraftDoc): DraftValidationReport {
|
|
59
|
+
const issues: CompileIssue[] = []
|
|
60
|
+
const entityByKey = new Map<string, OntologyEntity>()
|
|
61
|
+
|
|
62
|
+
// ---- 实体 ----
|
|
63
|
+
const seenKeys = new Set<string>()
|
|
64
|
+
doc.entities.forEach((entity, index) => {
|
|
65
|
+
if (seenKeys.has(entity.key)) {
|
|
66
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, `entities[${index}]`, `实体 key「${entity.key}」重复`, 'error', '实体 key 必须在单份本体文档内唯一'))
|
|
67
|
+
}
|
|
68
|
+
seenKeys.add(entity.key)
|
|
69
|
+
entityByKey.set(entity.key, entity)
|
|
70
|
+
if (entity.unit) {
|
|
71
|
+
const unitIssue = entityUnitIssue(entity)
|
|
72
|
+
if (unitIssue) issues.push(unitIssue)
|
|
73
|
+
}
|
|
74
|
+
if (entity.kind === 'process_variable' || entity.kind === 'quality_variable') {
|
|
75
|
+
if (!entity.role) {
|
|
76
|
+
issues.push(issue(RULE_ERROR_CODES.ROLE_UNRESOLVED, `entities[${entity.key}]`,
|
|
77
|
+
`变量实体「${entity.key}」缺少 role`, 'warning',
|
|
78
|
+
'缺 role 时无法参与 bound/rate 规则编译(编译器会拒绝);建议补 control/target/disturbance/feature/state/guard/observation'))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// ---- 关系 ----
|
|
84
|
+
const relationIds = new Set<string>()
|
|
85
|
+
const relationTriples = new Set<string>()
|
|
86
|
+
doc.relations.forEach((rel, index) => {
|
|
87
|
+
const path = `relations[${index}]`
|
|
88
|
+
if (relationIds.has(rel.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系 id「${rel.id}」重复`))
|
|
89
|
+
relationIds.add(rel.id)
|
|
90
|
+
const triple = `${rel.srcKey}|${rel.dstKey}|${rel.kind}`
|
|
91
|
+
if (relationTriples.has(triple)) {
|
|
92
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系重复(${rel.srcKey} -${rel.kind}-> ${rel.dstKey})`))
|
|
93
|
+
}
|
|
94
|
+
relationTriples.add(triple)
|
|
95
|
+
if (rel.srcKey === rel.dstKey) {
|
|
96
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系 ${rel.id} 自引用(src 与 dst 相同)`, 'warning'))
|
|
97
|
+
}
|
|
98
|
+
if (!entityByKey.has(rel.srcKey)) {
|
|
99
|
+
issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `关系 ${rel.id} 的 srcKey「${rel.srcKey}」不存在`, 'error', '先在 entities 里定义该实体'))
|
|
100
|
+
}
|
|
101
|
+
if (!entityByKey.has(rel.dstKey)) {
|
|
102
|
+
issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `关系 ${rel.id} 的 dstKey「${rel.dstKey}」不存在`, 'error', '先在 entities 里定义该实体'))
|
|
103
|
+
}
|
|
104
|
+
const tier = rel.properties.evidenceTier
|
|
105
|
+
const declaredMax = maxEvidenceLevel(rel.evidence.map(e => e.level))
|
|
106
|
+
if (rel.evidence.length > 0 && evidenceLevelRank(tier) > evidenceLevelRank(declaredMax)) {
|
|
107
|
+
issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
|
|
108
|
+
`关系 ${rel.id} 声明证据档 ${tier} 高于其证据最高级别 ${declaredMax || '无'}`,
|
|
109
|
+
'error', '补足对应级别证据,或下调 evidenceTier'))
|
|
110
|
+
}
|
|
111
|
+
if ((rel.properties.gainPerUnit !== undefined || rel.properties.lagMs !== undefined) && tier !== 'validated_control') {
|
|
112
|
+
issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
|
|
113
|
+
`关系 ${rel.id} 携带增益/时滞,但证据档为 ${tier}`,
|
|
114
|
+
'error', '增益与时滞只能来自受控验证(validated_control:run+crosscheck+outcome);否则请留空,仅作候选影响'))
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// ---- 规则 ----
|
|
119
|
+
const ruleIds = new Set<string>()
|
|
120
|
+
const ruleKeys = new Set<string>()
|
|
121
|
+
doc.rules.forEach((rule, index) => {
|
|
122
|
+
const path = `rules[${index}]`
|
|
123
|
+
if (ruleIds.has(rule.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `规则 id「${rule.id}」重复`))
|
|
124
|
+
ruleIds.add(rule.id)
|
|
125
|
+
if (ruleKeys.has(rule.key)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `规则 key「${rule.key}」重复`))
|
|
126
|
+
ruleKeys.add(rule.key)
|
|
127
|
+
if (rule.kind !== rule.dsl.type) {
|
|
128
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path,
|
|
129
|
+
`规则 ${rule.id} 的 kind(${rule.kind}) 与 dsl.type(${rule.dsl.type}) 不一致`,
|
|
130
|
+
'error', 'kind 决定编译形态,必须与 DSL 形态一致'))
|
|
131
|
+
}
|
|
132
|
+
for (const ref of ruleVariableRefs(rule)) {
|
|
133
|
+
if (!entityByKey.has(ref)) {
|
|
134
|
+
issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path,
|
|
135
|
+
`规则 ${rule.id} 引用的实体「${ref}」不存在`, 'error', '先定义实体,或改用语义绑定后的平台变量', rule.id))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const level = ruleEvidenceLevel(rule)
|
|
139
|
+
// 硬约束只约束「数值强制」形态(bound/rate/nonlinear);state_condition 与 interlock
|
|
140
|
+
// 分别落运行时守卫 / PLC 解释层,不改变数值可行域,因此不要求 validated_control。
|
|
141
|
+
const numericHard = rule.constraintLevel === 'hard' && (rule.dsl.type === 'bound' || rule.dsl.type === 'rate' || rule.dsl.type === 'nonlinear')
|
|
142
|
+
if (numericHard && level !== 'validated_control') {
|
|
143
|
+
issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
|
|
144
|
+
`规则 ${rule.id} 要求硬约束,但证据最高级别为 ${level || '无'}`,
|
|
145
|
+
'error', '硬约束只接受 validated_control(run+crosscheck+outcome);否则降为 soft 或改为 guard', rule.id))
|
|
146
|
+
}
|
|
147
|
+
if (rule.dsl.type === 'bound' && rule.dsl.min !== undefined && rule.dsl.max !== undefined && rule.dsl.min > rule.dsl.max) {
|
|
148
|
+
issues.push(issue(RULE_ERROR_CODES.RULE_CONFLICT, path,
|
|
149
|
+
`规则 ${rule.id} 的界区间为空(min ${rule.dsl.min} > max ${rule.dsl.max})`, 'error', '检查上下限是否写反', rule.id))
|
|
150
|
+
}
|
|
151
|
+
if (rule.dsl.type === 'nonlinear') {
|
|
152
|
+
// 简单阈值形态可由运行时守卫执行;复杂表达式需后端支持
|
|
153
|
+
const simple = /^\s*[a-z][a-z0-9_.]*\s*(<=|>=|<|>|==|!=)\s*-?\d+(?:\.\d+)?\s*$/.test(rule.dsl.expression)
|
|
154
|
+
if (!simple) {
|
|
155
|
+
issues.push(issue(RULE_ERROR_CODES.UNSUPPORTED_FORM, path,
|
|
156
|
+
`规则 ${rule.id} 的非线性表达式无法由运行时守卫执行`,
|
|
157
|
+
'warning', '建议改写为「变量 比较 阈值」形式,或落到 PhysicsSpec 由求解器/孪生后端支持', rule.id))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
// ---- 语义绑定(草稿期) ----
|
|
163
|
+
const bindingIds = new Set<string>()
|
|
164
|
+
const bindingTriples = new Set<string>()
|
|
165
|
+
doc.bindings.forEach((binding, index) => {
|
|
166
|
+
const path = `bindings[${index}]`
|
|
167
|
+
if (bindingIds.has(binding.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定 id「${binding.id}」重复`))
|
|
168
|
+
bindingIds.add(binding.id)
|
|
169
|
+
const triple = `${binding.entityKey}|${binding.platformKind}|${binding.platformId}`
|
|
170
|
+
if (bindingTriples.has(triple)) {
|
|
171
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定重复(实体 ${binding.entityKey} → ${binding.platformKind}:${binding.platformId})`))
|
|
172
|
+
}
|
|
173
|
+
bindingTriples.add(triple)
|
|
174
|
+
const entity = entityByKey.get(binding.entityKey)
|
|
175
|
+
if (!entity) {
|
|
176
|
+
issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `绑定 ${binding.id} 的实体「${binding.entityKey}」不存在`))
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
if (entity.unit && binding.unitDeclared && !unitsCompatible(entity.unit, binding.unitDeclared)) {
|
|
180
|
+
issues.push(issue(RULE_ERROR_CODES.UNIT_MISMATCH, path,
|
|
181
|
+
`绑定 ${binding.id} 的声明单位「${binding.unitDeclared}」与实体「${entity.key}」单位「${entity.unit}」量纲不相容`))
|
|
182
|
+
}
|
|
183
|
+
if (binding.unitDeclared && binding.unitTarget && !unitsCompatible(binding.unitDeclared, binding.unitTarget)) {
|
|
184
|
+
issues.push(issue(RULE_ERROR_CODES.UNIT_MISMATCH, path,
|
|
185
|
+
`绑定 ${binding.id} 的单位「${binding.unitDeclared}」与目标单位「${binding.unitTarget}」量纲不相容`))
|
|
186
|
+
}
|
|
187
|
+
if (!Number.isFinite(binding.scale) || binding.scale === 0) {
|
|
188
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定 ${binding.id} 的 scale 必须为非零有限数(禁止兜底)`))
|
|
189
|
+
}
|
|
190
|
+
if (binding.platformKind === 'daq_node' && binding.direction !== 'read') {
|
|
191
|
+
issues.push(issue(RULE_ERROR_CODES.INVALID, path,
|
|
192
|
+
`绑定 ${binding.id} 把数采节点声明为 ${binding.direction}`, 'warning',
|
|
193
|
+
'平台数采节点通常是只读通道;写入应绑定 dcw_node 或 recipe_param(活体校验会拒绝)'))
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const byState: Record<string, number> = {}
|
|
198
|
+
for (const state of ONTOLOGY_STATES) byState[state] = 0
|
|
199
|
+
for (const rule of doc.rules) byState[rule.status] = (byState[rule.status] ?? 0) + 1
|
|
200
|
+
const byEvidence: Record<string, number> = { candidate_influence: 0, observed_correlation: 0, validated_control: 0 }
|
|
201
|
+
for (const rule of doc.rules) {
|
|
202
|
+
const level = ruleEvidenceLevel(rule)
|
|
203
|
+
if (level) byEvidence[level] = (byEvidence[level] ?? 0) + 1
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
ok: !issues.some(i => i.severity === 'error'),
|
|
208
|
+
issues,
|
|
209
|
+
stats: {
|
|
210
|
+
entities: doc.entities.length,
|
|
211
|
+
relations: doc.relations.length,
|
|
212
|
+
rules: doc.rules.length,
|
|
213
|
+
bindings: doc.bindings.length,
|
|
214
|
+
byState,
|
|
215
|
+
byEvidence,
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -111,6 +111,13 @@ export function createBindingRepo(db: DatabaseSync) {
|
|
|
111
111
|
return row?.revision ?? 0
|
|
112
112
|
},
|
|
113
113
|
|
|
114
|
+
/** 模型采纳重绑:绑定升到新 Profile 版本并 bump revision(在飞求解 BINDING_STALE 收敛)。 */
|
|
115
|
+
rebindVersion(id: string, toVersion: number): number {
|
|
116
|
+
const r = db.prepare('UPDATE optimizer_bindings SET profile_version = ?, revision = revision + 1, valid_from = ?, updated_at = ? WHERE id = ?')
|
|
117
|
+
.run(toVersion, new Date().toISOString(), new Date().toISOString(), id)
|
|
118
|
+
return Number(r.changes)
|
|
119
|
+
},
|
|
120
|
+
|
|
114
121
|
removeByAgent(channelAgentId: string): number {
|
|
115
122
|
const r = db.prepare('DELETE FROM optimizer_bindings WHERE channel_agent_id = ?').run(channelAgentId)
|
|
116
123
|
return Number(r.changes)
|
|
@@ -72,9 +72,23 @@ export interface OptimizationProfile {
|
|
|
72
72
|
ownerUserId?: string
|
|
73
73
|
/** 发布时冻结的问题结构 hash */
|
|
74
74
|
problemIrHash?: string
|
|
75
|
+
/**
|
|
76
|
+
* 本体引用摘要(发布时冻结):**进 profileContentHash,绝不进 problemIrHash**。
|
|
77
|
+
* 漂移比对走独立校验(ONTOLOGY_PACK_DRIFTED),避免本体演化把旧 Profile
|
|
78
|
+
* 全部打成 PROBLEM_IR_CHANGED(与 D1/D12 同因)。
|
|
79
|
+
*/
|
|
80
|
+
ontologyRefs?: OntologyRefSummary[]
|
|
75
81
|
createdAt?: string
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
export interface OntologyRefSummary {
|
|
85
|
+
ontologyId: string
|
|
86
|
+
ontologyVersion: number
|
|
87
|
+
contentHash?: string
|
|
88
|
+
rulePackHash?: string
|
|
89
|
+
guardCount?: number
|
|
90
|
+
}
|
|
91
|
+
|
|
78
92
|
export function assertProfileSolverCompatible(profile: Pick<OptimizationProfile, 'solverRef' | 'modelRef' | 'problemTemplateRef'>): void {
|
|
79
93
|
assertSolverSupportsArtifact(profile.solverRef, profile.modelRef.artifactKind, `profile model=${profile.modelRef.modelId}`)
|
|
80
94
|
if (profile.solverRef === 'osqp_mpc@1' && profile.problemTemplateRef !== 'linear_mpc_quadratic@1') {
|
|
@@ -37,6 +37,7 @@ import { getDcwLineRepo } from '../dcw/dcw-line.repo'
|
|
|
37
37
|
import { assertRecipeOpInterval } from '../dcw/recipe-op-anchor'
|
|
38
38
|
import { getToolApprovals } from '../agents/tool-approvals'
|
|
39
39
|
import { amlActivityForLine } from '../agents/industrial/aml-activity'
|
|
40
|
+
import { assertOntologyUnchanged, evaluateOntologyGuardsForNodes } from '../ontology/ontology.service'
|
|
40
41
|
import type { RecipeProposePayload } from '../agents/industrial/recipe-propose-tools'
|
|
41
42
|
|
|
42
43
|
export function isOptimizerDispatchCard(nodeId: string): boolean {
|
|
@@ -342,6 +343,21 @@ export async function createDispatchCard(initiator: ResolvedUser, recommendation
|
|
|
342
343
|
}
|
|
343
344
|
})
|
|
344
345
|
const { recipe } = loadRec(recommendationId)
|
|
346
|
+
// 本体运行时守卫(ONT):已发布本体的 block 级守卫对本次下发意图求值。
|
|
347
|
+
// 只增拒不放行;无本体/无守卫时零开销。批准时刻 D13 仍全量重验。
|
|
348
|
+
const ontologyGuard = evaluateOntologyGuardsForNodes(spec.lineId, paramRows.map(p => ({ nodeId: p.nodeId, from: p.from, to: p.to })))
|
|
349
|
+
if (ontologyGuard.blocked) {
|
|
350
|
+
const violation = ontologyGuard.violations[0]!
|
|
351
|
+
throw new AppError(409, 'ONTOLOGY_GUARD_BLOCKED',
|
|
352
|
+
`本体运行时守卫阻断下发:${violation.message}(规则 ${violation.ruleId};本体包 ${ontologyGuard.packHash.slice(0, 12)})`)
|
|
353
|
+
}
|
|
354
|
+
// Profile 冻结的本体引用漂移:独立校验(不进 IR hash,不变更 D13 八项语义)
|
|
355
|
+
const dispatchRun = db().prepare('SELECT profile_id AS profileId, profile_version AS profileVersion FROM optimizer_runs WHERE id = ?')
|
|
356
|
+
.get(rec.runId) as { profileId?: string, profileVersion?: number } | undefined
|
|
357
|
+
if (dispatchRun?.profileId) {
|
|
358
|
+
const dispatchProfileRow = getProfileRepo().get(dispatchRun.profileId, Number(dispatchRun.profileVersion ?? 1))
|
|
359
|
+
if (dispatchProfileRow) assertOntologyUnchanged(parseProfileRow(dispatchProfileRow).ontologyRefs)
|
|
360
|
+
}
|
|
345
361
|
// 闸序预检(建卡时刻;批准时刻 D13 全量重验)
|
|
346
362
|
const gate = await assertDispatchApprovable(recommendationId, { modelFirstMove, packages: [{ params: paramRows }] })
|
|
347
363
|
if (!gate.ok) throw new AppError(gate.code.startsWith('DISPATCH_GATE') || gate.code === 'DISPATCH_STEP_EXCEEDED' ? 403 : 409, gate.code, gate.comment)
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile 模型采纳服务 —— Agent 迭代闭环的"采纳"环节(OW-adopt)。
|
|
3
|
+
*
|
|
4
|
+
* 闭环语义:Agent 训练出新模型(aml_job_submit→done)后,可以用
|
|
5
|
+
* `optimizer_profile_propose` 工具发起「采纳提议」:复制当前已发布 Profile
|
|
6
|
+
* 的全部求解配置、换上新模型工件、生成新草稿版本,并挂一张 HITL 卡。
|
|
7
|
+
* 人类批准 → **发布新版本 + 自动重绑**所有绑定在旧版本的 Agent(绑定 revision+1,
|
|
8
|
+
* 在飞求解按 BINDING_STALE 收敛,下一次 solve 即用新模型);拒绝 → 零写,意见回流。
|
|
9
|
+
*
|
|
10
|
+
* 治理不变量:
|
|
11
|
+
* - 提议 = 草稿 + 卡,本身不改运行行为(旧版本继续求解);
|
|
12
|
+
* - 发布只发生在人类批准之后(单一咽喉,dispatcher/decide 双入口同路由);
|
|
13
|
+
* - 模型工件/求解器/模板兼容性在提议时校验(D21 矩阵,不兼容 422);
|
|
14
|
+
* - 全链审计(actor 三态,publish/adopt/rebind 各一条)。
|
|
15
|
+
*/
|
|
16
|
+
import { AppError } from '../../../utils/errors'
|
|
17
|
+
import { getAmlRuntime } from '../aml/runtime'
|
|
18
|
+
import { recordOps } from '../ops/ops'
|
|
19
|
+
import { getProfileRepo, parseProfileRow } from './profile.repo'
|
|
20
|
+
import { getBindingRepo } from './binding.repo'
|
|
21
|
+
import { assertProfileSolverCompatible, type OptimizationProfile } from './contracts'
|
|
22
|
+
import type { ProblemTemplateRef, SolverRef } from '../process-model/contracts'
|
|
23
|
+
import { securityRecipeDispatchTimeoutMs } from '../settings'
|
|
24
|
+
import { createLogger } from '../logger'
|
|
25
|
+
|
|
26
|
+
import { getToolApprovals } from '../agents/tool-approvals'
|
|
27
|
+
|
|
28
|
+
const log = createLogger('optimizer.profile-adopt')
|
|
29
|
+
|
|
30
|
+
export const PROFILE_ADOPT_PREFIX = 'optimizer-profile:'
|
|
31
|
+
|
|
32
|
+
export function isProfileAdoptCard(nodeId: string): boolean {
|
|
33
|
+
return nodeId.startsWith(PROFILE_ADOPT_PREFIX)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ProposeAdoptionInput {
|
|
37
|
+
/** 发起 Agent 的 channel 实例 id(HITL 卡挂在其频道) */
|
|
38
|
+
agentInstanceId: string
|
|
39
|
+
/** 人类发起时为用户 id;Agent 发起传 agentId(actorKind='agent') */
|
|
40
|
+
initiatorId: string
|
|
41
|
+
initiatorKind?: 'user' | 'agent'
|
|
42
|
+
profileId: string
|
|
43
|
+
modelId: string
|
|
44
|
+
/** 可选切换问题模板/求解器(不兼容 → 422,D21 矩阵) */
|
|
45
|
+
templateRef?: ProblemTemplateRef
|
|
46
|
+
solverRef?: SolverRef
|
|
47
|
+
/** 提议理由(必填;审批卡展示) */
|
|
48
|
+
reason: string
|
|
49
|
+
/** 依赖注入(单测 stub 用) */
|
|
50
|
+
deps?: {
|
|
51
|
+
requestApproval?: (agentId: string, nodeId: string, kind: 'dcw', detail: string, opts?: { title?: string, timeoutMs?: number, payload?: unknown }) => Promise<{ approved: boolean, comment: string, choice: number | null }>
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ProposeAdoptionResult {
|
|
56
|
+
cardId: string
|
|
57
|
+
profileId: string
|
|
58
|
+
version: number
|
|
59
|
+
priorVersion: number
|
|
60
|
+
modelId: string
|
|
61
|
+
decision: { approved: boolean, comment: string, choice: number | null }
|
|
62
|
+
published: boolean
|
|
63
|
+
rebindCount: number
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** 提议采纳:建草稿新版本 + 挂 HITL 卡 + 等待裁决(approved 时已完成发布与重绑)。 */
|
|
67
|
+
export async function proposeProfileAdoption(input: ProposeAdoptionInput): Promise<ProposeAdoptionResult> {
|
|
68
|
+
const repo = getProfileRepo()
|
|
69
|
+
const published = repo.latestPublished(input.profileId)
|
|
70
|
+
if (!published) {
|
|
71
|
+
throw new AppError(404, 'PROFILE_NOT_PUBLISHED', `Profile ${input.profileId} 没有已发布版本;采纳以已发布版本为基线`)
|
|
72
|
+
}
|
|
73
|
+
const model = getAmlRuntime().repo.model.get(input.modelId)
|
|
74
|
+
if (!model) throw new AppError(404, 'MODEL_NOT_FOUND', `模型 ${input.modelId} 不存在(先经 AML 训练登记)`)
|
|
75
|
+
|
|
76
|
+
const prior = parseProfileRow(published)
|
|
77
|
+
const version = published.version + 1
|
|
78
|
+
const nextProfile: OptimizationProfile = {
|
|
79
|
+
...prior,
|
|
80
|
+
version,
|
|
81
|
+
status: 'draft',
|
|
82
|
+
modelRef: {
|
|
83
|
+
modelId: input.modelId,
|
|
84
|
+
artifactKind: (model.artifactKind || 'onnx_one_step@1') as OptimizationProfile['modelRef']['artifactKind'],
|
|
85
|
+
modelInterface: (model.modelInterface || 'one_step') as OptimizationProfile['modelRef']['modelInterface'],
|
|
86
|
+
artifactHash: model.artifactHash || '',
|
|
87
|
+
stage: 'candidate',
|
|
88
|
+
},
|
|
89
|
+
...(input.templateRef ? { problemTemplateRef: input.templateRef } : {}),
|
|
90
|
+
...(input.solverRef ? { solverRef: input.solverRef } : {}),
|
|
91
|
+
}
|
|
92
|
+
// D21 分派矩阵:工件×模板×求解器不兼容在此显式拒绝(不产生草稿)
|
|
93
|
+
assertProfileSolverCompatible(nextProfile)
|
|
94
|
+
repo.insert(nextProfile, input.initiatorId)
|
|
95
|
+
|
|
96
|
+
const cardId = `${PROFILE_ADOPT_PREFIX}${input.profileId}@${version}`
|
|
97
|
+
const detail = [
|
|
98
|
+
`模型采纳提议:${input.profileId} v${published.version} → v${version}`,
|
|
99
|
+
`新模型:${input.modelId}(${nextProfile.modelRef.artifactKind},hash ${String(nextProfile.modelRef.artifactHash).slice(0, 12)}…)`,
|
|
100
|
+
nextProfile.problemTemplateRef !== prior.problemTemplateRef || nextProfile.solverRef !== prior.solverRef
|
|
101
|
+
? `求解配置变更:模板 ${prior.problemTemplateRef}→${nextProfile.problemTemplateRef},求解器 ${prior.solverRef}→${nextProfile.solverRef}`
|
|
102
|
+
: `求解配置不变(模板 ${nextProfile.problemTemplateRef} / ${nextProfile.solverRef})`,
|
|
103
|
+
`理由:${input.reason}`,
|
|
104
|
+
`批准 = 冻结发布 v${version} 并把绑定在 v${published.version} 的 Agent 自动重绑(在飞求解 BINDING_STALE 收敛);拒绝 = 零写。`,
|
|
105
|
+
].join('\n')
|
|
106
|
+
|
|
107
|
+
recordOps({
|
|
108
|
+
actor: input.initiatorId,
|
|
109
|
+
actorName: input.initiatorId,
|
|
110
|
+
actorKind: input.initiatorKind ?? 'agent',
|
|
111
|
+
action: 'optimizer.profile.adopt_propose',
|
|
112
|
+
kind: 'system',
|
|
113
|
+
targetKind: 'optimizer_profile',
|
|
114
|
+
targetId: `${input.profileId}@${version}`,
|
|
115
|
+
summary: `提议采纳模型 ${input.modelId} → ${input.profileId}@${version}(卡 ${cardId})`,
|
|
116
|
+
detail: { profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId, reason: input.reason },
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const requestApproval = input.deps?.requestApproval
|
|
120
|
+
?? ((agentId: string, nodeId: string, kind: 'dcw', detail_: string, opts?: { title?: string, timeoutMs?: number, payload?: unknown }) =>
|
|
121
|
+
getToolApprovals().request(agentId, nodeId, kind, detail_, opts))
|
|
122
|
+
|
|
123
|
+
const decision = await requestApproval(input.agentInstanceId, cardId, 'dcw', detail, {
|
|
124
|
+
title: `模型采纳:${input.profileId} → v${version}`,
|
|
125
|
+
timeoutMs: securityRecipeDispatchTimeoutMs(),
|
|
126
|
+
payload: { schemaVersion: 1, profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId },
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
if (!decision.approved) {
|
|
130
|
+
return { cardId, profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId, decision: { approved: false, comment: decision.comment, choice: decision.choice ?? null }, published: false, rebindCount: 0 }
|
|
131
|
+
}
|
|
132
|
+
// 批准路径的发布/重绑在单一咽喉(decideProfileAdoption)已完成;此处防御式复核
|
|
133
|
+
const publishedRow = repo.get(input.profileId, version)
|
|
134
|
+
const rebindCount = countBindingsOn(input.profileId, version)
|
|
135
|
+
return {
|
|
136
|
+
cardId,
|
|
137
|
+
profileId: input.profileId,
|
|
138
|
+
version,
|
|
139
|
+
priorVersion: published.version,
|
|
140
|
+
modelId: input.modelId,
|
|
141
|
+
decision: { approved: true, comment: decision.comment, choice: decision.choice ?? null },
|
|
142
|
+
published: publishedRow?.status === 'published',
|
|
143
|
+
rebindCount,
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function countBindingsOn(profileId: string, version: number): number {
|
|
148
|
+
return getBindingRepo().listAll(500).filter(b => b.profileId === profileId && b.profileVersionNumber === version).length
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface DecideAdoptionInput {
|
|
152
|
+
/** 审批单 id(ap-…;listPending 的主键) */
|
|
153
|
+
cardId: string
|
|
154
|
+
/** 卡的 nodeId(optimizer-profile:<id>@<v>);缺省时经审批单反查 */
|
|
155
|
+
nodeId?: string
|
|
156
|
+
approved: boolean
|
|
157
|
+
comment: string
|
|
158
|
+
actingUser: { id: string, name?: string }
|
|
159
|
+
via: 'hitl/respond' | 'decide-endpoint'
|
|
160
|
+
/** 依赖注入(单测 stub);缺省走真实 ToolApprovalService(卡必须在册) */
|
|
161
|
+
deps?: {
|
|
162
|
+
decideApproval?: (id: string, approved: boolean, comment: string, by: string, name: string) => void
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** 卡落定(真实面:审批必须在册;stub 面:直接回调)。失败不击穿咽喉主流程。 */
|
|
167
|
+
function settle(deps: DecideAdoptionInput['deps'], cardId: string, approved: boolean, comment: string, by: string, name: string): void {
|
|
168
|
+
try {
|
|
169
|
+
const decide = deps?.decideApproval ?? ((id: string, ok: boolean, msg: string, by2: string, name2: string) => getToolApprovals().decide(id, ok, msg, by2, name2))
|
|
170
|
+
decide(cardId, approved, comment, by, name)
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
log.warn(`[profile-adopt] 卡落定失败(不影响裁决结果):${err instanceof Error ? err.message : String(err)}`)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface DecideAdoptionResult {
|
|
178
|
+
handled: boolean
|
|
179
|
+
approved: boolean
|
|
180
|
+
comment: string
|
|
181
|
+
code?: string
|
|
182
|
+
published?: { profileId: string, version: number, rebindCount: number }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** 单一咽喉:optimizer-profile:* 卡的裁决 → 发布 + 重绑 + 审计(业务拒绝在咽喉内落定)。 */
|
|
186
|
+
export async function decideProfileAdoption(input: DecideAdoptionInput): Promise<DecideAdoptionResult> {
|
|
187
|
+
// nodeId 解析:分支显式传入优先;否则经审批单反查(卡 id ≠ nodeId,两个命名空间)
|
|
188
|
+
const nodeId = input.nodeId
|
|
189
|
+
?? getToolApprovals().listPending().find(a => a.id === input.cardId)?.nodeId
|
|
190
|
+
?? input.cardId
|
|
191
|
+
if (!isProfileAdoptCard(nodeId)) return { handled: false, approved: input.approved, comment: input.comment }
|
|
192
|
+
const parsed = nodeId.slice(PROFILE_ADOPT_PREFIX.length).split('@')
|
|
193
|
+
const profileId = parsed[0] ?? ''
|
|
194
|
+
const version = Number(parsed[1])
|
|
195
|
+
if (!profileId || !Number.isInteger(version)) {
|
|
196
|
+
throw new AppError(422, 'PROFILE_ADOPT_CARD_INVALID', `采纳卡 nodeId 形状非法:${nodeId}`)
|
|
197
|
+
}
|
|
198
|
+
const repo = getProfileRepo()
|
|
199
|
+
const row = repo.get(profileId, version)
|
|
200
|
+
if (!row) {
|
|
201
|
+
settle(input.deps, input.cardId, false, `Profile ${profileId}@${version} 已不存在;按拒收敛`, input.actingUser.id, input.actingUser.name ?? '')
|
|
202
|
+
return { handled: true, approved: false, comment: '目标 Profile 版本不存在', code: 'PROFILE_NOT_FOUND' }
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (!input.approved) {
|
|
206
|
+
// 拒绝:草稿保留(可修订后重新 propose,新卡重走),零写
|
|
207
|
+
settle(input.deps, input.cardId, false, input.comment || '采纳提议被拒绝', input.actingUser.id, input.actingUser.name ?? '')
|
|
208
|
+
recordOps({
|
|
209
|
+
actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
|
|
210
|
+
action: 'optimizer.profile.adopt_reject', kind: 'system',
|
|
211
|
+
targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
|
|
212
|
+
summary: `拒绝模型采纳 ${profileId}@${version}(草稿保留,零写)`,
|
|
213
|
+
detail: { profileId, version, comment: input.comment, via: input.via },
|
|
214
|
+
})
|
|
215
|
+
return { handled: true, approved: false, comment: input.comment || '采纳提议被拒绝', code: 'PROFILE_ADOPT_REJECTED' }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 批准:发布冻结 + 自动重绑(旧 published 版本 → 新版本;revision+1 使在飞求解 BINDING_STALE 收敛)
|
|
219
|
+
const priorVersion = version - 1
|
|
220
|
+
try {
|
|
221
|
+
repo.publish(profileId, version)
|
|
222
|
+
const rebindCount = rebindBindings(profileId, priorVersion, version)
|
|
223
|
+
recordOps({
|
|
224
|
+
actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
|
|
225
|
+
action: 'optimizer.profile.adopt', kind: 'system',
|
|
226
|
+
targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
|
|
227
|
+
summary: `批准并发布 ${profileId}@${version}(重绑 ${rebindCount} 个绑定;来自采纳卡)`,
|
|
228
|
+
detail: { profileId, version, priorVersion, rebindCount, via: input.via, comment: input.comment },
|
|
229
|
+
})
|
|
230
|
+
settle(input.deps, input.cardId, true, input.comment || `已发布 v${version},重绑 ${rebindCount} 个绑定`, input.actingUser.id, input.actingUser.name ?? '')
|
|
231
|
+
return { handled: true, approved: true, comment: input.comment, published: { profileId, version, rebindCount } }
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
235
|
+
settle(input.deps, input.cardId, false, `发布失败,按拒收敛:${message}`, input.actingUser.id, input.actingUser.name ?? '')
|
|
236
|
+
recordOps({
|
|
237
|
+
actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
|
|
238
|
+
action: 'optimizer.profile.adopt_reject', kind: 'system', level: 'error',
|
|
239
|
+
targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
|
|
240
|
+
summary: `采纳发布失败按拒收敛 ${profileId}@${version}:${message}`,
|
|
241
|
+
detail: { profileId, version, error: message, via: input.via },
|
|
242
|
+
})
|
|
243
|
+
return { handled: true, approved: false, comment: `发布失败:${message}`, code: 'PROFILE_ADOPT_PUBLISH_FAILED' }
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function rebindBindings(profileId: string, fromVersion: number, toVersion: number): number {
|
|
248
|
+
const repo = getBindingRepo()
|
|
249
|
+
let count = 0
|
|
250
|
+
for (const b of repo.listAll(500)) {
|
|
251
|
+
if (b.profileId !== profileId || b.profileVersionNumber !== fromVersion) continue
|
|
252
|
+
const moved = repo.rebindVersion(b.id, toVersion)
|
|
253
|
+
if (moved > 0) count += 1
|
|
254
|
+
}
|
|
255
|
+
return count
|
|
256
|
+
}
|
|
@@ -28,6 +28,8 @@ export interface ProfileRow {
|
|
|
28
28
|
problemIrHash: string
|
|
29
29
|
/** 发布不可变校验:内容 hash(不含 status/createdAt/problemIrHash) */
|
|
30
30
|
contentHash: string
|
|
31
|
+
/** 本体引用冻结(JSON 数组;缺省 '[]' = 无本体约束域) */
|
|
32
|
+
ontologyRefsJson: string
|
|
31
33
|
createdAt: string
|
|
32
34
|
updatedAt: string
|
|
33
35
|
}
|
|
@@ -38,6 +40,7 @@ const COLS = `id, version, name, model_ref AS modelRef, model_artifact_hash AS m
|
|
|
38
40
|
process_spec_ref AS processSpecRef,
|
|
39
41
|
solver_ref AS solverRef, solver_version AS solverVersion, condition_ids_json AS conditionIdsJson,
|
|
40
42
|
status, owner_user_id AS ownerUserId, problem_ir_hash AS problemIrHash, content_hash AS contentHash,
|
|
43
|
+
ontology_refs_json AS ontologyRefsJson,
|
|
41
44
|
created_at AS createdAt, updated_at AS updatedAt`
|
|
42
45
|
|
|
43
46
|
export function profileContentHash(profile: OptimizationProfile): string {
|
|
@@ -61,12 +64,13 @@ export function createProfileRepo(db: DatabaseSync) {
|
|
|
61
64
|
db.prepare(`INSERT INTO optimizer_profiles
|
|
62
65
|
(id, version, name, model_ref, model_artifact_hash, model_artifact_kind, model_interface,
|
|
63
66
|
problem_template_ref, problem_config_json, process_spec_ref, solver_ref, solver_version, condition_ids_json,
|
|
64
|
-
status, owner_user_id, problem_ir_hash, content_hash, created_at, updated_at)
|
|
65
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
67
|
+
status, owner_user_id, problem_ir_hash, content_hash, ontology_refs_json, created_at, updated_at)
|
|
68
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
66
69
|
.run(profile.id, profile.version, profile.name ?? '', profile.modelRef.modelId, profile.modelRef.artifactHash,
|
|
67
70
|
profile.modelRef.artifactKind, profile.modelRef.modelInterface, profile.problemTemplateRef,
|
|
68
71
|
JSON.stringify(profile.problemConfig ?? {}), profile.processSpecRef ?? '', profile.solverRef, profile.solverVersion,
|
|
69
|
-
JSON.stringify(profile.conditionIds ?? []), profile.status, ownerUserId, profile.problemIrHash ?? '', contentHash,
|
|
72
|
+
JSON.stringify(profile.conditionIds ?? []), profile.status, ownerUserId, profile.problemIrHash ?? '', contentHash,
|
|
73
|
+
JSON.stringify(profile.ontologyRefs ?? []), now, now)
|
|
70
74
|
return this.get(profile.id, profile.version)!
|
|
71
75
|
},
|
|
72
76
|
|
|
@@ -92,6 +96,11 @@ export function createProfileRepo(db: DatabaseSync) {
|
|
|
92
96
|
return (r.v ?? 0) + 1
|
|
93
97
|
},
|
|
94
98
|
|
|
99
|
+
/** 最近已发布版本(采纳服务以它为基线;无则 undefined) */
|
|
100
|
+
latestPublished(id: string): ProfileRow | undefined {
|
|
101
|
+
return db.prepare(`SELECT ${COLS} FROM optimizer_profiles WHERE id = ? AND status = 'published' ORDER BY version DESC LIMIT 1`).get(id) as unknown as ProfileRow | undefined
|
|
102
|
+
},
|
|
103
|
+
|
|
95
104
|
/** 发布:冻结 problemIrHash;published 行禁止原地修改(服务层拒绝 UPDATE)。 */
|
|
96
105
|
publish(id: string, version: number, problemIrHash?: string): ProfileRow {
|
|
97
106
|
const row = this.get(id, version)
|
|
@@ -153,6 +162,13 @@ export function parseProfileRow(row: ProfileRow): OptimizationProfile {
|
|
|
153
162
|
status: row.status,
|
|
154
163
|
ownerUserId: row.ownerUserId,
|
|
155
164
|
problemIrHash: row.problemIrHash || undefined,
|
|
165
|
+
ontologyRefs: (() => {
|
|
166
|
+
try {
|
|
167
|
+
const parsed = JSON.parse(row.ontologyRefsJson || '[]') as OptimizationProfile['ontologyRefs']
|
|
168
|
+
return parsed && parsed.length > 0 ? parsed : undefined
|
|
169
|
+
}
|
|
170
|
+
catch { return undefined }
|
|
171
|
+
})(),
|
|
156
172
|
createdAt: row.createdAt,
|
|
157
173
|
}
|
|
158
174
|
}
|