agentworkshop 0.8.8 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.AgentWorkShop/prompts/host-tools.json +68 -0
- package/.output/.AgentWorkShop/prompts/host-tools.json +68 -0
- package/.output/.AgentWorkShop/schema.json +2 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{Cdi9qfTr.js → CDO7Zey1.js} +2 -2
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/247a0d5c-de27-46a4-8f76-3e64affe9473.json +1 -0
- package/.output/server/chunks/_/access.mjs +1 -1
- package/.output/server/chunks/_/data-export.mjs +5 -5
- package/.output/server/chunks/_/data-query.mjs +2 -2
- package/.output/server/chunks/_/eda-run.repo.mjs +3 -3
- package/.output/server/chunks/_/features.mjs +5 -5
- package/.output/server/chunks/_/golden.mjs +2 -2
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/index.mjs +2 -2
- package/.output/server/chunks/_/mes-secrets.repo.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +2836 -1334
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/spc.mjs +2 -2
- package/.output/server/chunks/build/_id_-CsCtnbwe.mjs +1 -1
- package/.output/server/chunks/build/_id_-P1W47Gqq.mjs +1 -1
- package/.output/server/chunks/build/_wsId_-DpOErFj6.mjs +1 -1
- package/.output/server/chunks/build/agents-D7CdEUTv.mjs +1 -1
- package/.output/server/chunks/build/aml-DRAFRcGU.mjs +1 -1
- package/.output/server/chunks/build/analysis-J9axLuRt.mjs +1 -1
- package/.output/server/chunks/build/api-B4Om0mEc.mjs +1 -1
- package/.output/server/chunks/build/api-BEW_ebY_.mjs +1 -1
- package/.output/server/chunks/build/api-BsAgXWxi.mjs +1 -1
- package/.output/server/chunks/build/board-CJUc032b.mjs +1 -1
- package/.output/server/chunks/build/channel-templates-ggsBacZF.mjs +1 -1
- package/.output/server/chunks/build/constants-HPHJvjne.mjs +1 -1
- package/.output/server/chunks/build/daq-B_dRMDw4.mjs +1 -1
- package/.output/server/chunks/build/data-D8uX1dnm.mjs +1 -1
- package/.output/server/chunks/build/dcw-D_HD_H_2.mjs +1 -1
- package/.output/server/chunks/build/default-CNWS6NUw.mjs +1 -1
- package/.output/server/chunks/build/es-Bxu10NJ2.mjs +1 -1
- package/.output/server/chunks/build/logs-BnYSMRXM.mjs +1 -1
- package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs +1 -1
- package/.output/server/chunks/build/ontology-ohICfVVb.mjs +1 -1
- package/.output/server/chunks/build/operations-4zOVhW7o.mjs +1 -1
- package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +1 -1
- package/.output/server/chunks/build/pages-DEv4ProW.mjs +1 -1
- package/.output/server/chunks/build/permissions-DgXQZSyx.mjs +1 -1
- package/.output/server/chunks/build/pipeline-CkavMBhk.mjs +1 -1
- package/.output/server/chunks/build/plugins-LRjaSEZy.mjs +1 -1
- package/.output/server/chunks/build/schedules-Hz2DJUE2.mjs +1 -1
- package/.output/server/chunks/build/settings-DXLJPq7d.mjs +1 -1
- package/.output/server/chunks/build/studio-hSqH9TYS.mjs +1 -1
- package/.output/server/chunks/build/teams-BbwYJyzv.mjs +1 -1
- package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs +1 -1
- package/.output/server/chunks/build/tools-CnYi9cou.mjs +1 -1
- package/.output/server/chunks/build/town-BV-hbwb5.mjs +1 -1
- package/.output/server/chunks/build/town-CcoQKjMj.mjs +1 -1
- package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
- package/.output/server/chunks/build/types-DWqIeMRP.mjs +1 -1
- package/.output/server/chunks/build/useAgentHarnessOptions-Dq0l0Z6d.mjs +1 -1
- package/.output/server/chunks/build/useAgentTemplateActions-BFOHb5-L.mjs +1 -1
- package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs +1 -1
- package/.output/server/chunks/build/useAgentTemplateForm-CuJPOPcK.mjs +1 -1
- package/.output/server/chunks/build/useAgentTemplatesCatalog-B2bIhZLA.mjs +1 -1
- package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs +1 -1
- package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs +1 -1
- package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs +1 -1
- package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs +1 -1
- package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs +1 -1
- package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs +1 -1
- package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs +1 -1
- package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs +1 -1
- package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs +1 -1
- package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs +1 -1
- package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailNode-BGMRUIXN.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
- package/.output/server/chunks/build/useDaqFilters-zAAVlzJQ.mjs +1 -1
- package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs +1 -1
- package/.output/server/chunks/build/useDaqOptimizations-BE_9Z2s_.mjs +1 -1
- package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
- package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs +1 -1
- package/.output/server/chunks/build/useDashboardData-Cw8lrPo5.mjs +1 -1
- package/.output/server/chunks/build/useDcwAddNode-KnocMk1m.mjs +1 -1
- package/.output/server/chunks/build/useDcwCards-C53IiOcg.mjs +1 -1
- package/.output/server/chunks/build/useDcwDetailScope-D6qXrfZu.mjs +1 -1
- package/.output/server/chunks/build/useDcwDetailTemplates-DPOXu1o_.mjs +1 -1
- package/.output/server/chunks/build/useDcwFilter-DNQ6Ivwd.mjs +1 -1
- package/.output/server/chunks/build/useDcwLedger-BhbUBCbi.mjs +1 -1
- package/.output/server/chunks/build/useDcwLineMutations-KA7VnggO.mjs +1 -1
- package/.output/server/chunks/build/useDcwLineRun-3zx_UCxi.mjs +1 -1
- package/.output/server/chunks/build/useDcwParamApprovals-DzyY6Tmi.mjs +1 -1
- package/.output/server/chunks/build/useDcwProducts-B05ymt3k.mjs +1 -1
- package/.output/server/chunks/build/useDcwQuery-vWpgpSmJ.mjs +1 -1
- package/.output/server/chunks/build/useDcwQuickActions-DUkLy34S.mjs +1 -1
- package/.output/server/chunks/build/useDcwRecipes-BAb4Yg3d.mjs +1 -1
- package/.output/server/chunks/build/useDcwTemplates-D2aoejps.mjs +1 -1
- package/.output/server/chunks/build/useDcwWrites-7w8txksD.mjs +1 -1
- package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs +1 -1
- package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs +1 -1
- package/.output/server/chunks/build/useLogsManual-D0dvgCsP.mjs +1 -1
- package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs +1 -1
- package/.output/server/chunks/build/useLogsScope-DEUyq-My.mjs +1 -1
- package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs +1 -1
- package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs +1 -1
- package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs +1 -1
- package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs +1 -1
- package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs +1 -1
- package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs +1 -1
- package/.output/server/chunks/build/useTeamActions-BDjU06LP.mjs +1 -1
- package/.output/server/chunks/build/useTeamAddMemberDialog-J3oFn3FI.mjs +1 -1
- package/.output/server/chunks/build/useTeamCreateDialog-fbn4ixYu.mjs +1 -1
- package/.output/server/chunks/build/useTeamDeployDialog-BNezMD2k.mjs +1 -1
- package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs +1 -1
- package/.output/server/chunks/build/useTeamPluginDialog-BZznrOVe.mjs +1 -1
- package/.output/server/chunks/build/useTeamsCatalog-DuZFP3oG.mjs +1 -1
- package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs +1 -1
- package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs +1 -1
- package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs +1 -1
- package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs +1 -1
- package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs +1 -1
- package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs +1 -1
- package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs +1 -1
- package/.output/server/chunks/build/useWorkspaceAuth-Dlvj9csD.mjs +1 -1
- package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs +1 -1
- package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs +1 -1
- package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs +1 -1
- package/.output/server/chunks/build/users-DjiVC_tS.mjs +1 -1
- package/.output/server/chunks/build/workshop-1gKeDASV.mjs +1 -1
- package/.output/server/chunks/routes/api/health.get.mjs +1 -1
- package/.output/server/chunks/routes/api/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
- package/.output/server/chunks/routes/api/metrics.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/i18n.get.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/backup/list.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/backup/run.post.mjs +3 -3
- package/.output/server/chunks/routes/api/system/config-groups/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/system/config-groups/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/system/config.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/system/monitor.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +1 -1
- package/.output/server/chunks/routes/api/system/timezone.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.put.mjs +1 -1
- package/.output/server/chunks/routes/api/users/change-password.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/login.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/register.post.mjs +1 -1
- package/.output/server/chunks/routes/api/users/setup-status.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/_...path_.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +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 +2 -2
- 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/agents/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.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/entities/prune.post.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.get.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/character/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index.get.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.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/caller.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/channel-templates/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/rotate-token.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.get.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/chat/messages/_messageId/read.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/chat/permissions.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/execution-mode.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.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.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.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.get.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.get.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/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index7.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/_userId/approve.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/members/_userId_.delete.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/members/leave.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.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/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.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/export-file.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/index.post.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/query.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/storage/retention.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/storage/rollup.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/storage.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 +2 -2
- 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/charts/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/charts/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/charts/_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/dashboards/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/dashboards/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/dashboards/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/features/jobs.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/golden/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/golden/deviation.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/golden/single.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index2.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/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index4.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index5.post.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/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index7.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index8.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/index8.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/ocap/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/ocap/_id_.patch.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/spc/_id/recompute.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/spc/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/spc/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.patch.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.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
- 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/index10.post.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/index13.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index14.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index15.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index16.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index2.post.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.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index5.get.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/index7.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index9.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/datasets.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/points.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/preview.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/mes/secrets/_ref_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/notifications/read.post.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/bindings/_id_.delete.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/plugins/index.get.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 +370 -20
- package/.output/server/chunks/routes/api/workshop/process-model/experiments.mjs.map +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/runtime.get.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/scene/layouts.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/schedules/_id/run.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/schedules/_id/runs.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/schedules/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/schedules/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/schedules/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/reassign.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/reopen.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/supersede.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id/update.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks.get.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.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.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/teams/_id/members/_agentId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.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/users/me.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/users/register.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/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +2 -2
- package/.output/server/chunks/virtual/entry.mjs +5 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/index.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +3 -3
- package/README.md +3 -3
- package/config.yml +1 -1
- package/docs/aml.md +112 -112
- package/docs/cli.en.md +4 -4
- package/docs/cli.md +3 -3
- 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 +2 -0
- package/i18n/locales/zh-CN.ts +2 -0
- package/package.json +1 -1
- package/scripts/_audit/demo-shot-studio.mjs +37 -0
- package/scripts/_audit/demo-shots.mjs +38 -0
- package/scripts/_audit/gen-demo-report.py +69 -0
- package/scripts/_audit/mqtt-pub.mjs +13 -0
- package/scripts/_audit/mqtt-topic-probe.mjs +15 -0
- package/scripts/_audit/proto-b3-device-4021.mjs +90 -0
- package/scripts/_audit/proto-doc-device-4120.mjs +53 -0
- package/scripts/acceptance-scientific-loop.ts +240 -0
- package/scripts/generate-identifiability-fixtures.ts +98 -0
- package/server/api/workshop/process-model/experiments.ts +28 -2
- package/server/plugins-builtin/diag-bridge/host/plugin.mjs +759 -753
- package/server/plugins-builtin/rag-bridge/index.mjs +490 -484
- package/server/repositories/user.repository.ts +24 -1
- package/server/services/user.service.ts +8 -6
- package/server/services/workshop/agents/host-tool-bridge/catalog.ts +2 -0
- package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +4 -1
- package/server/services/workshop/agents/host-tool-bridge/tools/messaging.ts +5 -1
- package/server/services/workshop/agents/industrial/aml-dataset-tools.ts +3 -0
- package/server/services/workshop/agents/industrial/bench-approval-only.ts +335 -58
- package/server/services/workshop/agents/industrial/dcw-tools.ts +7 -1
- package/server/services/workshop/agents/industrial/identifiability-tools.ts +247 -0
- package/server/services/workshop/agents/industrial/index.ts +1 -0
- package/server/services/workshop/agents/industrial/manual-approval.ts +3 -1
- package/server/services/workshop/agents/industrial/ops-tools.ts +58 -15
- package/server/services/workshop/agents/industrial/optimization-tools.ts +49 -19
- package/server/services/workshop/agents/plugin-governance.ts +22 -2
- package/server/services/workshop/aml/action-coverage.ts +253 -0
- package/server/services/workshop/aml/causal-claim.ts +68 -0
- package/server/services/workshop/aml/dataset-builder.ts +19 -0
- package/server/services/workshop/aml/gates.ts +45 -1
- package/server/services/workshop/aml/identifiability.ts +335 -0
- package/server/services/workshop/aml/intervention-ledger.ts +289 -0
- package/server/services/workshop/aml/ontology-learning.ts +143 -0
- package/server/services/workshop/aml/twin/cross-check-service.ts +114 -0
- package/server/services/workshop/aml/twin/cross-check.ts +176 -0
- package/server/services/workshop/daq/daq-controller/contracts.ts +3 -0
- package/server/services/workshop/daq/daq-controller/crud.ts +12 -2
- package/server/services/workshop/daq/daq-controller/push.ts +22 -0
- package/server/services/workshop/daq/drivers/mqtt.ts +28 -0
- package/server/services/workshop/daq/drivers/shared.ts +6 -0
- package/server/services/workshop/db/database/open.ts +2 -0
- package/server/services/workshop/db/database/rows.ts +4 -1
- package/server/services/workshop/db/database/schema.ts +38 -2
- package/server/services/workshop/db/message.repo.ts +10 -3
- package/server/services/workshop/dcw/dcw-controller/write-audit.ts +21 -1
- package/server/services/workshop/process-model/experiment-runner.ts +437 -0
- package/server/services/workshop/process-model/experiment.ts +31 -10
- package/server/services/workshop/process-model/plan-safety.ts +69 -0
- package/server/services/workshop/runtime/agent-runtime/lifecycle.ts +34 -11
- package/server/services/workshop/runtime/agent-runtime/state.ts +6 -1
- package/server/services/workshop/settings.ts +4 -1
- package/server/services/workshop/types/a2a.ts +16 -1
- package/shared/config/schema.json +2 -0
- package/shared/dcw-protocol/closed-loop.ts +2 -0
- package/.output/public/_nuxt/builds/meta/1231252d-2864-43c0-83b2-4e70d3b86dea.json +0 -1
|
@@ -7,7 +7,7 @@ import type { DatabaseSync } from 'node:sqlite'
|
|
|
7
7
|
import type { MessageRow } from './database'
|
|
8
8
|
|
|
9
9
|
const COLS
|
|
10
|
-
= 'id, channel_id AS channelId, task_id AS taskId, from_agent_id AS fromAgentId, to_agent_id AS toAgentId, role, parts_json AS partsJson, metadata_json AS metadataJson, state, created_at AS createdAt, consumed_at AS consumedAt'
|
|
10
|
+
= 'id, channel_id AS channelId, task_id AS taskId, from_agent_id AS fromAgentId, to_agent_id AS toAgentId, role, parts_json AS partsJson, metadata_json AS metadataJson, state, attempts, created_at AS createdAt, consumed_at AS consumedAt'
|
|
11
11
|
|
|
12
12
|
export interface MessageCreateInput {
|
|
13
13
|
/** 落库 id;缺省生成。A2A 入队时传发送方 messageId,保证 API 返回 id 与历史 id 一致 */
|
|
@@ -43,10 +43,16 @@ export function createMessageRepo(db: DatabaseSync) {
|
|
|
43
43
|
`UPDATE messages SET state = 'consumed', consumed_at = ? WHERE id = ?`,
|
|
44
44
|
)
|
|
45
45
|
const resetConsumingStmt = db.prepare(
|
|
46
|
-
|
|
46
|
+
// P3-4:崩溃恢复重投不复活 dead(重投上限是持久判定,重启不洗白)
|
|
47
|
+
`UPDATE messages SET state = 'pending' WHERE state = 'consuming' AND attempts < 3`,
|
|
47
48
|
)
|
|
48
49
|
const requeueStmt = db.prepare(
|
|
49
|
-
|
|
50
|
+
// P3-4(2026-11-01):重投计数上限 —— attempts+1,达 3 次不再回 pending(→ dead)。
|
|
51
|
+
// steer 对忙碌 Agent 的重投之前无上限:坏消息(解析必炸/超长)会在
|
|
52
|
+
// "认领→steer 失败→回 pending"里无限循环,每 250ms 吃掉一个调度拍。
|
|
53
|
+
`UPDATE messages SET attempts = attempts + 1,
|
|
54
|
+
state = CASE WHEN attempts + 1 >= 3 THEN 'dead' ELSE 'pending' END
|
|
55
|
+
WHERE id = ? AND state = 'consuming'`,
|
|
50
56
|
)
|
|
51
57
|
const consumePendingByTaskStmt = db.prepare(
|
|
52
58
|
`UPDATE messages SET state = 'consumed', consumed_at = ? WHERE task_id = ? AND state = 'pending'`,
|
|
@@ -78,6 +84,7 @@ export function createMessageRepo(db: DatabaseSync) {
|
|
|
78
84
|
partsJson: JSON.stringify(input.parts),
|
|
79
85
|
metadataJson: JSON.stringify(input.metadata ?? {}),
|
|
80
86
|
state: 'pending',
|
|
87
|
+
attempts: 0,
|
|
81
88
|
createdAt: now,
|
|
82
89
|
consumedAt: null,
|
|
83
90
|
}
|
|
@@ -9,6 +9,7 @@ import { emitDcwWrite } from '@/server/services/workshop/plugins/host.mjs'
|
|
|
9
9
|
import { getActiveLineRun } from '../line-run'
|
|
10
10
|
import { opsActorKindOf } from './helpers'
|
|
11
11
|
import { recordOps } from '../../ops/ops'
|
|
12
|
+
import { recordIntervention } from '../../aml/intervention-ledger'
|
|
12
13
|
|
|
13
14
|
/** 同节点写入去重节流表(eng+10s 窗内视为同一次下发的重试回执) */
|
|
14
15
|
export const opsWriteMemo = new Map<string, { eng: number, at: number }>()
|
|
@@ -18,7 +19,7 @@ export function recordDcwWriteOps(args: {
|
|
|
18
19
|
node: { name: string, unit?: string, lineId: string }
|
|
19
20
|
eng: number
|
|
20
21
|
prevValue: number | null
|
|
21
|
-
outcome: { ok: boolean, message: string }
|
|
22
|
+
outcome: { ok: boolean, message: string, ack?: string, readback?: number | null }
|
|
22
23
|
src: DcwWriteSource
|
|
23
24
|
meta?: DcwWriteMeta
|
|
24
25
|
recipeRunId: string | null
|
|
@@ -46,4 +47,23 @@ export function recordDcwWriteOps(args: {
|
|
|
46
47
|
})
|
|
47
48
|
// 插件钩子:写控 ACK 观察(与运维入册同点同去重节流)
|
|
48
49
|
emitDcwWrite({ nodeId: args.id, name: args.node.name, eng: args.eng, prevValue: args.prevValue, ok: args.outcome.ok, source: args.src, lineId: args.node.lineId ?? '', at: new Date().toISOString() })
|
|
50
|
+
// v34 干预台账(科学探索计划 P2):全路径单点入册(与运维日志同点同去重节流)。
|
|
51
|
+
// 只记已受理下发;拒绝路径沿上方 recordOps 的 dcw.write.rejected 审计,不入台账。
|
|
52
|
+
// recordIntervention 内部自吞异常(台账失败绝不改变写结果语义)。
|
|
53
|
+
recordIntervention({
|
|
54
|
+
nodeId: args.id,
|
|
55
|
+
nodeName: args.node.name,
|
|
56
|
+
lineId: args.node.lineId ?? '',
|
|
57
|
+
fromValue: args.prevValue,
|
|
58
|
+
toValue: args.eng,
|
|
59
|
+
actualValue: args.outcome.readback != null && Number.isFinite(Number(args.outcome.readback)) ? Number(args.outcome.readback) : null,
|
|
60
|
+
ack: args.outcome.ack ?? '',
|
|
61
|
+
path: args.src,
|
|
62
|
+
actor: args.meta?.actor ?? 'user',
|
|
63
|
+
actorName: args.meta?.actorName ?? '',
|
|
64
|
+
channelId: args.meta?.channelId ?? '',
|
|
65
|
+
approvalId: args.meta?.approvalId ?? null,
|
|
66
|
+
recipeRunId: args.recipeRunId,
|
|
67
|
+
hypothesis: args.meta?.hypothesis ?? '',
|
|
68
|
+
})
|
|
49
69
|
}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 参数试验计划执行器(科学探索计划 P4,docs/plans/2026-11-02-scientific-exploration-plan.md):
|
|
3
|
+
* 把 process_model_experiments 从"仅仿真线可建"升级为**治理分档**:
|
|
4
|
+
* - simulated=true → tier=sim_auto:建计划即可执行(既有行为不变);
|
|
5
|
+
* - 真实线 → tier=real_hitl:建计划落 awaiting_approval,须单卡 HITL 批准(卡上带成本核算)
|
|
6
|
+
* 后转 planned 才能执行。
|
|
7
|
+
* 执行语义(正交化由机制保证,不靠 Agent 自觉):
|
|
8
|
+
* - 步序 = repeats × levels,默认 seeded 随机化(randomizedOrder=false 时按原序);
|
|
9
|
+
* - 每步:写控制(走 DcwController.write 咽喉,source=agent → 步长/60s 间隔/保持窗照常生效)
|
|
10
|
+
* → 等 settleMs → 等 observeMs → 下一步;
|
|
11
|
+
* - 预算:步数上限 + 总时长上限,超限即 FAILED 并写明原因(不静默续跑);
|
|
12
|
+
* - abortOnAlarm:每步前查告警,命中即 FAILED(剩余步不执行);
|
|
13
|
+
* - 台账:写咽喉已自动落 intervention_events(hypothesis 前缀 [pexp:<id>] 建立关联),
|
|
14
|
+
* 计划结束时按台账汇总 verdict 分布进计划状态。
|
|
15
|
+
* 副作用全部经注入(测试可替换),默认实现走真实控制器/数采/告警仓储。
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from 'node:crypto'
|
|
18
|
+
import { AppError } from '../../../utils/errors'
|
|
19
|
+
import { getDcwLineRepo } from '../dcw/dcw-line.repo'
|
|
20
|
+
import { getDcwController } from '../dcw/dcw-controller'
|
|
21
|
+
import { getRecipeRollBackManager } from '../dcw/recipe-rollback-manager'
|
|
22
|
+
import { getDaqController } from '../daq/daq-controller'
|
|
23
|
+
import { getAmlRuntime } from '../aml/runtime'
|
|
24
|
+
import { getExperimentPlan, updateExperimentStatus, type ExperimentPlanRow } from './experiment'
|
|
25
|
+
import { assessIdentifiability, dominantPeriod } from '../aml/identifiability'
|
|
26
|
+
import { attachAssessment, listInterventions, verdictCodeOf, verdictDetailOf } from '../aml/intervention-ledger'
|
|
27
|
+
import { backfillInterventionEvidence } from '../aml/ontology-learning'
|
|
28
|
+
import { assertPlanNodesSafe } from './plan-safety'
|
|
29
|
+
|
|
30
|
+
export interface ExperimentPlanBody {
|
|
31
|
+
version: 1
|
|
32
|
+
lineId: string
|
|
33
|
+
simSceneId: string | null
|
|
34
|
+
specId: string | null
|
|
35
|
+
levels: Record<string, number[]>
|
|
36
|
+
repeats: number
|
|
37
|
+
settleMs: number
|
|
38
|
+
observeMs: number
|
|
39
|
+
randomizedOrder: boolean
|
|
40
|
+
abortOnAlarm: boolean
|
|
41
|
+
design: string
|
|
42
|
+
tier?: 'sim_auto' | 'real_hitl'
|
|
43
|
+
/** 主控制量 → 观测目标节点(执行时读回);缺省取 spec 或首个控制量,无目标则跳过判读 */
|
|
44
|
+
targets?: Record<string, string>
|
|
45
|
+
/** 创建时核算的成本(人读 + 机读) */
|
|
46
|
+
cost?: ExperimentCost
|
|
47
|
+
/** 真实线批准凭据(approveExperimentPlan 写入) */
|
|
48
|
+
approvalId?: string
|
|
49
|
+
approvedBy?: string
|
|
50
|
+
approvedAt?: string
|
|
51
|
+
/** 人工取消凭据(运行中每步前被感知) */
|
|
52
|
+
cancelledBy?: string
|
|
53
|
+
cancelledAt?: string
|
|
54
|
+
note?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ExperimentCost {
|
|
58
|
+
/** 各控制量中最大的水平数(展示用) */
|
|
59
|
+
levelsPerControl: number
|
|
60
|
+
/** 全部控制量水平数之和(步数基数) */
|
|
61
|
+
levelsTotal: number
|
|
62
|
+
controls: number
|
|
63
|
+
repeats: number
|
|
64
|
+
steps: number
|
|
65
|
+
perStepMs: number
|
|
66
|
+
totalDurationMs: number
|
|
67
|
+
/** 建议的单步响应窗(ms):已知主导周期时为 3×周期,否则 = settleMs */
|
|
68
|
+
suggestedWindowMs: number | null
|
|
69
|
+
dominantPeriodMs: number | null
|
|
70
|
+
summary: string
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ExperimentStep {
|
|
74
|
+
index: number
|
|
75
|
+
controlId: string
|
|
76
|
+
level: number
|
|
77
|
+
repeat: number
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 真/仿真产线分档(不 throw:调用方按 tier 决定是否挂 HITL) */
|
|
81
|
+
export function resolveExperimentTier(lineId: string): { lineId: string, lineName: string, simulated: boolean, tier: 'sim_auto' | 'real_hitl', simSceneId?: string } {
|
|
82
|
+
const line = getDcwLineRepo().byId(lineId)
|
|
83
|
+
if (!line) throw new AppError(404, 'LINE_NOT_FOUND', `产线 ${lineId} 不存在`)
|
|
84
|
+
const simulated = line.simulated === true
|
|
85
|
+
return { lineId: line.id, lineName: line.name, simulated, tier: simulated ? 'sim_auto' : 'real_hitl', simSceneId: line.simSceneId }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** 真实线下 60s 节点最小间隔(与 write() 的在线写联锁同口径) */
|
|
89
|
+
const REAL_MIN_STEP_MS = 60_000
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 成本核算(创建时就算给用户看):步数 × 每步驻留。真实线每步至少 60s(写间隔联锁),
|
|
93
|
+
* 仿真线不受此限。已知主导周期时,建议窗 = 3×周期,单步驻留取 max(settle, 建议窗, 60s)。
|
|
94
|
+
*/
|
|
95
|
+
export function estimateExperimentCost(plan: Pick<ExperimentPlanBody, 'levels' | 'repeats' | 'settleMs' | 'observeMs' | 'tier'>, opts: { dominantPeriodMs?: number | null } = {}): ExperimentCost {
|
|
96
|
+
const controls = Object.keys(plan.levels).length
|
|
97
|
+
const levelsPerControl = Math.max(0, ...Object.values(plan.levels).map(v => v.length))
|
|
98
|
+
// 步数 = 各控制量水平数之和 × 轮数(不是 max×控制量数 —— 控制量水平数可以不同)
|
|
99
|
+
const levelsTotal = Object.values(plan.levels).reduce((a, v) => a + v.length, 0)
|
|
100
|
+
const repeats = plan.repeats
|
|
101
|
+
const steps = levelsTotal * repeats
|
|
102
|
+
const period = opts.dominantPeriodMs ?? null
|
|
103
|
+
const suggestedWindowMs = period != null && period > 0 ? Math.round(3 * period) : null
|
|
104
|
+
const minStep = plan.tier === 'real_hitl' ? REAL_MIN_STEP_MS : 0
|
|
105
|
+
const holdMs = Math.max(plan.settleMs, suggestedWindowMs ?? 0, minStep)
|
|
106
|
+
const perStepMs = holdMs + plan.observeMs
|
|
107
|
+
const totalDurationMs = steps * perStepMs
|
|
108
|
+
const summary = `${controls} 个控制量共 ${levelsTotal} 个水平 × ${repeats} 轮 = ${steps} 步;每步 ${Math.round(perStepMs / 1000)}s(驻留 ${Math.round(holdMs / 1000)}s${
|
|
109
|
+
suggestedWindowMs != null ? `,含 3×主导周期 ${(suggestedWindowMs / 1000).toFixed(1)}s` : ''
|
|
110
|
+
}${minStep ? ',真实线 60s 写间隔下限' : ''} + 观测 ${Math.round(plan.observeMs / 1000)}s);预计总时长 ≈ ${(totalDurationMs / 3600_000).toFixed(2)} 小时`
|
|
111
|
+
return { levelsPerControl, levelsTotal, controls, repeats, steps, perStepMs, totalDurationMs, suggestedWindowMs, dominantPeriodMs: period, summary }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function seededShuffle<T>(items: T[], seed: number): T[] {
|
|
115
|
+
let a = seed >>> 0
|
|
116
|
+
const rnd = () => {
|
|
117
|
+
a |= 0
|
|
118
|
+
a = (a + 0x6D2B79F5) | 0
|
|
119
|
+
let t = Math.imul(a ^ (a >>> 15), 1 | a)
|
|
120
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
|
|
121
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
|
122
|
+
}
|
|
123
|
+
const out = [...items]
|
|
124
|
+
for (let i = out.length - 1; i > 0; i--) {
|
|
125
|
+
const j = Math.floor(rnd() * (i + 1))
|
|
126
|
+
const tmp = out[i]!
|
|
127
|
+
out[i] = out[j]!
|
|
128
|
+
out[j] = tmp
|
|
129
|
+
}
|
|
130
|
+
return out
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 生成执行步序:按 repeats × (control,level) 展开,randomizedOrder 时用计划 id 派生种子洗牌
|
|
135
|
+
* (同一计划可复现;跨控制量也打散,避免"先把一个 MV 走完再走另一个"带来的时间混杂)。
|
|
136
|
+
*/
|
|
137
|
+
export function buildExperimentSteps(plan: ExperimentPlanBody, planId: string): ExperimentStep[] {
|
|
138
|
+
const base: Array<{ controlId: string, level: number, repeat: number }> = []
|
|
139
|
+
for (let r = 0; r < plan.repeats; r++) {
|
|
140
|
+
for (const [controlId, levels] of Object.entries(plan.levels)) {
|
|
141
|
+
for (const level of levels) base.push({ controlId, level, repeat: r })
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const seed = createHash('sha256').update(planId).digest().readUInt32BE(0)
|
|
145
|
+
const ordered = plan.randomizedOrder ? seededShuffle(base, seed) : base
|
|
146
|
+
return ordered.map((s, index) => ({ index, ...s }))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function parsePlan(row: ExperimentPlanRow): ExperimentPlanBody {
|
|
150
|
+
return JSON.parse(row.planJson) as ExperimentPlanBody
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 人工取消计划(运行中/待批准/已计划均可)。
|
|
155
|
+
* 执行器每步前读状态,感知到 cancelled 即停;已执行步的台账/证据保留。
|
|
156
|
+
*/
|
|
157
|
+
export function cancelExperimentPlan(id: string, actor: string): ExperimentPlanRow {
|
|
158
|
+
const row = getExperimentPlan(id)
|
|
159
|
+
if (!row) throw new AppError(404, 'EXPERIMENT_PLAN_NOT_FOUND', `试验计划 ${id} 不存在`)
|
|
160
|
+
if (row.status === 'done' || row.status === 'failed' || row.status === 'cancelled') {
|
|
161
|
+
throw new AppError(409, 'EXPERIMENT_STATUS_INVALID', `计划 ${id} 已是终态 ${row.status},无需取消`)
|
|
162
|
+
}
|
|
163
|
+
const plan = parsePlan(row)
|
|
164
|
+
const next: ExperimentPlanBody = { ...plan, cancelledBy: actor, cancelledAt: new Date().toISOString() }
|
|
165
|
+
getAmlRuntime().db.prepare('UPDATE process_model_experiments SET plan_json = ?, status = \'cancelled\', updated_at = ? WHERE id = ?')
|
|
166
|
+
.run(JSON.stringify(next), new Date().toISOString(), id)
|
|
167
|
+
return getExperimentPlan(id)!
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** 真实线批准:awaiting_approval → planned(记录批准凭据;幂等) */
|
|
171
|
+
export function approveExperimentPlan(id: string, approvalId: string, approvedBy: string): ExperimentPlanRow {
|
|
172
|
+
const row = getExperimentPlan(id)
|
|
173
|
+
if (!row) throw new AppError(404, 'EXPERIMENT_PLAN_NOT_FOUND', `试验计划 ${id} 不存在`)
|
|
174
|
+
const plan = parsePlan(row)
|
|
175
|
+
if (row.status === 'planned' && plan.approvalId) return row
|
|
176
|
+
if (row.status !== 'awaiting_approval') {
|
|
177
|
+
throw new AppError(409, 'EXPERIMENT_STATUS_INVALID', `计划 ${id} 当前状态 ${row.status},只有 awaiting_approval 可批准`)
|
|
178
|
+
}
|
|
179
|
+
const next: ExperimentPlanBody = { ...plan, approvalId, approvedBy, approvedAt: new Date().toISOString() }
|
|
180
|
+
const db = getAmlRuntime().db
|
|
181
|
+
db.prepare('UPDATE process_model_experiments SET plan_json = ?, status = \'planned\', updated_at = ? WHERE id = ?')
|
|
182
|
+
.run(JSON.stringify(next), new Date().toISOString(), id)
|
|
183
|
+
return getExperimentPlan(id)!
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ---------- 执行 ----------
|
|
187
|
+
|
|
188
|
+
export interface ExperimentRunnerDeps {
|
|
189
|
+
/** 写控制(默认走 DcwController.write 咽喉;测试注入) */
|
|
190
|
+
write?: (controlId: string, level: number, meta: { hypothesis: string, planId: string, stepIndex: number }) => Promise<{ ok: boolean, message?: string, recordId?: string }>
|
|
191
|
+
/** 关闭单步调控记录(默认 judge=rollback 关闭不执行回退;测试注入) */
|
|
192
|
+
closeRecord?: (recordId: string, reason: string) => void
|
|
193
|
+
/** 读目标窗均值(默认 daq samples;测试注入) */
|
|
194
|
+
readTargetMean?: (targetNodeId: string, fromMs: number, toMs: number) => Promise<number | null>
|
|
195
|
+
/** 读目标窗序列(默认 daq samples;判定用;缺省跳过引擎判读) */
|
|
196
|
+
readTargetSeries?: (targetNodeId: string, fromMs: number, toMs: number) => Promise<number[]>
|
|
197
|
+
/** 告警检查(默认查 audit_log 最近一条 level=error 的 alarm 行;测试注入) */
|
|
198
|
+
alarmActive?: (lineId: string, sinceMs: number) => Promise<boolean>
|
|
199
|
+
sleep?: (ms: number) => Promise<void>
|
|
200
|
+
/** 时钟(测试可推进) */
|
|
201
|
+
now?: () => number
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface ExperimentRunResult {
|
|
205
|
+
planId: string
|
|
206
|
+
status: 'done' | 'failed' | 'cancelled'
|
|
207
|
+
executedSteps: number
|
|
208
|
+
totalSteps: number
|
|
209
|
+
failedReason?: string
|
|
210
|
+
verdicts: Record<string, number>
|
|
211
|
+
startedAt: string
|
|
212
|
+
finishedAt: string
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function defaultWrite(): NonNullable<ExperimentRunnerDeps['write']> {
|
|
216
|
+
return async (controlId, level, meta) => {
|
|
217
|
+
try {
|
|
218
|
+
const outcome = await getDcwController().write(controlId, level, null, {
|
|
219
|
+
source: 'agent',
|
|
220
|
+
actor: `plan:${meta.planId}`,
|
|
221
|
+
actorName: `试验计划 ${meta.planId}`,
|
|
222
|
+
hypothesis: meta.hypothesis,
|
|
223
|
+
})
|
|
224
|
+
return { ok: outcome.ok !== false, message: outcome.message, recordId: outcome.recordId }
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
return { ok: false, message: err instanceof Error ? err.message : String(err) }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* 关闭单步的调控闭环记录(默认实现):不关闭会让下一步被"单一开放记录"守卫拒绝
|
|
234
|
+
* (beforeWrite: 正在优化试验中)。judge('rollback') 按设计只落判定、记录仍 open,
|
|
235
|
+
* 因此用 keep + takeover:关闭记录但**跳过好锚晋升**(试验步是探索,不是产能优化,
|
|
236
|
+
* 不应污染 keep 锚点链)。
|
|
237
|
+
*/
|
|
238
|
+
function defaultCloseRecord(): NonNullable<ExperimentRunnerDeps['closeRecord']> {
|
|
239
|
+
return (recordId, reason) => {
|
|
240
|
+
try {
|
|
241
|
+
getRecipeRollBackManager().judge(recordId, 'keep', reason, 'system', 'experiment-plan', { takeover: true })
|
|
242
|
+
}
|
|
243
|
+
catch { /* 已关闭/记录不存在:不影响执行 */ }
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const sleepReal = (ms: number) => new Promise<void>(r => setTimeout(r, ms))
|
|
248
|
+
|
|
249
|
+
export async function runExperimentPlan(id: string, deps: ExperimentRunnerDeps = {}): Promise<ExperimentRunResult> {
|
|
250
|
+
const row = getExperimentPlan(id)
|
|
251
|
+
if (!row) throw new AppError(404, 'EXPERIMENT_PLAN_NOT_FOUND', `试验计划 ${id} 不存在`)
|
|
252
|
+
const plan = parsePlan(row)
|
|
253
|
+
const tier = plan.tier ?? (resolveExperimentTier(plan.lineId).tier)
|
|
254
|
+
if (row.status === 'running') {
|
|
255
|
+
// 僵死 running 恢复:进程崩溃/重启会把状态永久停在 running(不可重跑也不可取消)。
|
|
256
|
+
// 超过预算上限 + 5min 无更新即判僵死 → 置 failed 并提示可重新创建计划。
|
|
257
|
+
const budgetRaw = JSON.parse(row.budgetJson || '{}') as { maxDurationMs?: number }
|
|
258
|
+
const staleMs = (budgetRaw.maxDurationMs ?? 4 * 3600_000) + 5 * 60_000
|
|
259
|
+
const age = Date.now() - Date.parse(row.updatedAt)
|
|
260
|
+
if (Number.isFinite(age) && age > staleMs) {
|
|
261
|
+
updateExperimentStatus(id, 'failed')
|
|
262
|
+
throw new AppError(409, 'EXPERIMENT_RUN_STALE', `计划 ${id} 上一次执行僵死(超过 ${Math.round(staleMs / 60000)} min 无更新),已置 failed;请重新创建计划(旧计划的台账行仍可查)`)
|
|
263
|
+
}
|
|
264
|
+
throw new AppError(409, 'EXPERIMENT_ALREADY_RUNNING', `计划 ${id} 正在执行`)
|
|
265
|
+
}
|
|
266
|
+
if (row.status !== 'planned') {
|
|
267
|
+
throw new AppError(409, 'EXPERIMENT_STATUS_INVALID', `计划 ${id} 当前状态 ${row.status},只有 planned 可执行${tier === 'real_hitl' ? '(真实线须先 HITL 批准)' : ''}`)
|
|
268
|
+
}
|
|
269
|
+
// 真实线执行前复核批准凭据(防"建完直接跑"绕过 HITL)
|
|
270
|
+
if (tier === 'real_hitl' && !plan.approvalId) {
|
|
271
|
+
throw new AppError(409, 'EXPERIMENT_APPROVAL_REQUIRED', `计划 ${id} 为真实产线计划,缺少 HITL 批准凭据,拒绝执行`)
|
|
272
|
+
}
|
|
273
|
+
// 执行前复核(防御深度):批准到执行之间产线/节点可能变更(换线、停用、量程调整)。
|
|
274
|
+
// 只对真实线强校验;仿真线计划允许过程模型 MV 逻辑名(不落设备,写入时由 write() 兜底)。
|
|
275
|
+
if (tier === 'real_hitl') assertPlanNodesSafe(plan)
|
|
276
|
+
const budget = JSON.parse(row.budgetJson) as { maxRuns?: number, maxDurationMs?: number }
|
|
277
|
+
const steps = buildExperimentSteps(plan, id)
|
|
278
|
+
if (budget.maxRuns && steps.length > budget.maxRuns) {
|
|
279
|
+
updateExperimentStatus(id, 'failed')
|
|
280
|
+
return {
|
|
281
|
+
planId: id, status: 'failed', executedSteps: 0, totalSteps: steps.length,
|
|
282
|
+
failedReason: `步数 ${steps.length} 超预算 maxRuns=${budget.maxRuns}(创建即拒绝执行)`,
|
|
283
|
+
verdicts: {}, startedAt: new Date().toISOString(), finishedAt: new Date().toISOString(),
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const write = deps.write ?? defaultWrite()
|
|
288
|
+
const closeRecord = deps.closeRecord ?? defaultCloseRecord()
|
|
289
|
+
const readTarget = deps.readTargetMean ?? (async (nodeId, fromMs, toMs) => {
|
|
290
|
+
try {
|
|
291
|
+
const pts = await getDaqController().samples(nodeId, { fromMs, toMs, bucketMs: 1000, limit: 600 }) as Array<{ value?: number, avg?: number }>
|
|
292
|
+
const vals = pts.map(p => Number(p.value ?? p.avg)).filter(Number.isFinite)
|
|
293
|
+
return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return null
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
const alarmActive = deps.alarmActive ?? (async (lineId, sinceMs) => {
|
|
300
|
+
try {
|
|
301
|
+
const hit = getAmlRuntime().db.prepare(`SELECT id FROM audit_log WHERE line_id = ? AND level = 'error' AND created_at >= ? LIMIT 1`)
|
|
302
|
+
.get(lineId, new Date(sinceMs).toISOString()) as { id?: string } | undefined
|
|
303
|
+
return !!hit
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
return false
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
const readSeries = deps.readTargetSeries ?? (async (nodeId, fromMs, toMs) => {
|
|
310
|
+
try {
|
|
311
|
+
const pts = await getDaqController().samples(nodeId, { fromMs, toMs, bucketMs: 1000, limit: Math.max(60, Math.ceil((toMs - fromMs) / 1000) + 10) }) as Array<{ value?: number, avg?: number }>
|
|
312
|
+
return pts.map(p => Number(p.value ?? p.avg)).filter(Number.isFinite)
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return []
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
const sleep = deps.sleep ?? sleepReal
|
|
319
|
+
const now = deps.now ?? (() => Date.now())
|
|
320
|
+
|
|
321
|
+
updateExperimentStatus(id, 'running')
|
|
322
|
+
const startedAt = new Date(now()).toISOString()
|
|
323
|
+
const started = now()
|
|
324
|
+
// 计划级主导周期估计:用一段长历史(≥30min 与 6×settle 的较大者)估一次,
|
|
325
|
+
// 逐步判定统一使用 —— 短窗局部自相关会把局部纹波当周期(事故形态)。
|
|
326
|
+
let expectedPeriodMs: number | undefined
|
|
327
|
+
const firstTarget = plan.targets ? Object.values(plan.targets)[0] : undefined
|
|
328
|
+
if (firstTarget) {
|
|
329
|
+
try {
|
|
330
|
+
const longMs = Math.max(30 * 60_000, plan.settleMs * 6)
|
|
331
|
+
const longSeries = await readSeries(firstTarget, now() - longMs, now())
|
|
332
|
+
if (longSeries.length >= 64) {
|
|
333
|
+
const p = dominantPeriod(longSeries)
|
|
334
|
+
// 长历史必须覆盖 ≥3 个周期才采信该估计
|
|
335
|
+
if (p.lagBeats != null && longSeries.length / p.lagBeats >= 3) expectedPeriodMs = p.lagBeats * 1000
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
catch { /* 估计失败退回逐步检测 */ }
|
|
339
|
+
}
|
|
340
|
+
let executed = 0
|
|
341
|
+
let failedReason: string | undefined
|
|
342
|
+
|
|
343
|
+
// 真实线每步驻留不得低于写联锁的 60s 节点间隔(否则第 2 步必被 429 打回,白跑)
|
|
344
|
+
const holdMs = tier === 'real_hitl' ? Math.max(plan.settleMs, REAL_MIN_STEP_MS) : plan.settleMs
|
|
345
|
+
for (const step of steps) {
|
|
346
|
+
// 取消:每步前读一次计划状态(REST cancel 是异步人工操作,必须能被及时感知)
|
|
347
|
+
const live = getExperimentPlan(id)
|
|
348
|
+
if (live?.status === 'cancelled') {
|
|
349
|
+
failedReason = `计划被人工取消(已执行 ${executed}/${steps.length} 步)`
|
|
350
|
+
break
|
|
351
|
+
}
|
|
352
|
+
// 预算:总时长超限即停(不静默续跑)
|
|
353
|
+
if (budget.maxDurationMs && now() - started > budget.maxDurationMs) {
|
|
354
|
+
failedReason = `超出预算 maxDurationMs=${budget.maxDurationMs}ms(已执行 ${executed}/${steps.length} 步)`
|
|
355
|
+
break
|
|
356
|
+
}
|
|
357
|
+
if (plan.abortOnAlarm && await alarmActive(plan.lineId, started)) {
|
|
358
|
+
failedReason = `告警中止(abortOnAlarm):第 ${executed + 1} 步前检测到产线告警,剩余 ${steps.length - executed} 步未执行`
|
|
359
|
+
break
|
|
360
|
+
}
|
|
361
|
+
const hypothesis = `[pexp:${id}] 试验步 ${step.index + 1}/${steps.length}:${step.controlId}=${step.level}(第 ${step.repeat + 1} 轮)`
|
|
362
|
+
const res = await write(step.controlId, step.level, { hypothesis, planId: id, stepIndex: step.index })
|
|
363
|
+
if (!res.ok) {
|
|
364
|
+
failedReason = `第 ${step.index + 1} 步写入被拒:${res.message ?? '未知原因'}`
|
|
365
|
+
break
|
|
366
|
+
}
|
|
367
|
+
executed++
|
|
368
|
+
const writeAt = now()
|
|
369
|
+
await sleep(holdMs)
|
|
370
|
+
// 观测窗 + 引擎判读:有目标映射时,写前窗/写后窗各取一次序列交给可辨识性引擎,
|
|
371
|
+
// 判定回填本步干预台账(与 optimization_explore 同口径);无目标则只驻留。
|
|
372
|
+
const target = plan.targets?.[step.controlId]
|
|
373
|
+
if (target) {
|
|
374
|
+
const pre = await readSeries(target, writeAt - holdMs, writeAt)
|
|
375
|
+
await sleep(plan.observeMs)
|
|
376
|
+
const post = await readSeries(target, writeAt, now())
|
|
377
|
+
await readTarget(target, writeAt, now())
|
|
378
|
+
if (pre.length >= 8 && post.length >= 8) {
|
|
379
|
+
try {
|
|
380
|
+
const v = assessIdentifiability({ pre, post, beatMs: 1000, ...(expectedPeriodMs != null ? { expectedPeriodMs } : {}) })
|
|
381
|
+
// 写咽喉落行时若无 targetNodeId 会标 unassessed(尚无判定)—— 两者都视为"待判定"
|
|
382
|
+
const row = listInterventions({ nodeId: step.controlId, limit: 50 })
|
|
383
|
+
.find(r => r.hypothesis.startsWith(`[pexp:${id}]`) && (r.verdict === 'pending' || r.verdict === 'unassessed'))
|
|
384
|
+
if (row) {
|
|
385
|
+
attachAssessment(row.id, {
|
|
386
|
+
verdict: verdictCodeOf(v),
|
|
387
|
+
effect: v.effect,
|
|
388
|
+
ciLow: v.ciLow,
|
|
389
|
+
ciHigh: v.ciHigh,
|
|
390
|
+
mde: v.mde,
|
|
391
|
+
targetNodeId: target,
|
|
392
|
+
detail: verdictDetailOf(v),
|
|
393
|
+
})
|
|
394
|
+
// P6:判定回灌本体证据(有已发布本体才落;幂等)
|
|
395
|
+
const updated = listInterventions({ nodeId: step.controlId, limit: 1 })[0]
|
|
396
|
+
if (updated) {
|
|
397
|
+
try {
|
|
398
|
+
backfillInterventionEvidence(updated)
|
|
399
|
+
}
|
|
400
|
+
catch { /* 证据登记失败不影响执行 */ }
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
catch { /* 判读失败按未判定处理 */ }
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
await sleep(plan.observeMs)
|
|
409
|
+
}
|
|
410
|
+
// 关闭本步调控记录(否则下一步会被"单一开放记录"守卫拒绝)
|
|
411
|
+
if (res.recordId) closeRecord(res.recordId, `试验计划 ${id} 第 ${step.index + 1} 步执行完成,由计划执行器关闭(关闭记录不晋升锚点)`)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 台账汇总:按 hypothesis 前缀 [pexp:<id>] 找本次计划的干预行
|
|
415
|
+
const verdicts: Record<string, number> = {}
|
|
416
|
+
try {
|
|
417
|
+
const involved = new Set(Object.keys(plan.levels))
|
|
418
|
+
const rows = listInterventions({ lineId: plan.lineId, limit: 200 })
|
|
419
|
+
.filter(r => involved.has(r.nodeId) && r.hypothesis.startsWith(`[pexp:${id}]`))
|
|
420
|
+
for (const r of rows) verdicts[r.verdict] = (verdicts[r.verdict] ?? 0) + 1
|
|
421
|
+
}
|
|
422
|
+
catch { /* 台账不可读不影响执行结果 */ }
|
|
423
|
+
|
|
424
|
+
const cancelled = failedReason?.includes('人工取消') ?? false
|
|
425
|
+
const status: ExperimentRunResult['status'] = cancelled ? 'cancelled' : (failedReason ? 'failed' : 'done')
|
|
426
|
+
updateExperimentStatus(id, status)
|
|
427
|
+
return {
|
|
428
|
+
planId: id,
|
|
429
|
+
status,
|
|
430
|
+
executedSteps: executed,
|
|
431
|
+
totalSteps: steps.length,
|
|
432
|
+
...(failedReason ? { failedReason } : {}),
|
|
433
|
+
verdicts,
|
|
434
|
+
startedAt,
|
|
435
|
+
finishedAt: new Date(now()).toISOString(),
|
|
436
|
+
}
|
|
437
|
+
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* -
|
|
4
|
-
* -
|
|
2
|
+
* 参数试验计划(G2.11 / C9 / A9;P4 治理分档 2026-11-02):
|
|
3
|
+
* - simulated=true → tier=sim_auto,建计划即可执行(既有行为不变);
|
|
4
|
+
* - 真实线 → tier=real_hitl,创建后落 awaiting_approval,须 approveExperimentPlan
|
|
5
|
+
* 单卡 HITL 批准(卡上带成本核算)后才能由 runExperimentPlan 执行;
|
|
6
|
+
* - 计划只落 process_model_experiments;动作明细仍走既有 DCW 写咽喉/台账
|
|
5
7
|
* (不制造第二套写设备账本)。
|
|
6
8
|
*/
|
|
7
9
|
import type { DatabaseSync } from 'node:sqlite'
|
|
8
10
|
import { AppError } from '../../../utils/errors'
|
|
9
11
|
import { getAmlRuntime } from '../aml/runtime'
|
|
10
12
|
import { getDcwLineRepo } from '../dcw/dcw-line.repo'
|
|
13
|
+
import { estimateExperimentCost, resolveExperimentTier, type ExperimentPlanBody, type ExperimentCost } from './experiment-runner'
|
|
14
|
+
import { assertPlanNodesSafe } from './plan-safety'
|
|
11
15
|
|
|
12
16
|
export interface ExperimentPlanInput {
|
|
13
17
|
lineId: string
|
|
@@ -21,6 +25,10 @@ export interface ExperimentPlanInput {
|
|
|
21
25
|
abortOnAlarm?: boolean
|
|
22
26
|
budget?: { maxRuns?: number, maxDurationMs?: number }
|
|
23
27
|
createdBy?: string
|
|
28
|
+
/** MV → 观测目标节点(执行时读回;缺省不读) */
|
|
29
|
+
targets?: Record<string, string>
|
|
30
|
+
/** 已知主导扰动周期(ms;来自可辨识性引擎):成本核算按 3×周期给建议窗 */
|
|
31
|
+
dominantPeriodMs?: number
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
export interface ExperimentPlanRow {
|
|
@@ -44,7 +52,7 @@ export function assertSimulatedLine(lineId: string): { id: string, simSceneId?:
|
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
export function createExperimentPlan(input: ExperimentPlanInput): ExperimentPlanRow {
|
|
47
|
-
const
|
|
55
|
+
const tierInfo = resolveExperimentTier(input.lineId)
|
|
48
56
|
if (!Object.keys(input.levels).length) throw new AppError(422, 'EXPERIMENT_PLAN_INVALID', '至少需要 1 个 MV 的水平序列')
|
|
49
57
|
for (const [id, levels] of Object.entries(input.levels)) {
|
|
50
58
|
if (!Array.isArray(levels) || levels.length < 2) throw new AppError(422, 'EXPERIMENT_PLAN_INVALID', `MV ${id} 至少需要 2 个水平(阶跃/多水平)`)
|
|
@@ -54,13 +62,23 @@ export function createExperimentPlan(input: ExperimentPlanInput): ExperimentPlan
|
|
|
54
62
|
const repeats = Math.max(1, Math.min(input.repeats ?? 1, 20))
|
|
55
63
|
const settleMs = Math.max(1000, input.settleMs ?? 60_000)
|
|
56
64
|
const observeMs = Math.max(1000, input.observeMs ?? 120_000)
|
|
65
|
+
// 上线前加固:真实线计划在**创建时**即校验节点归属(须属本线/启用/量程内,targets 须同线 DAQ)。
|
|
66
|
+
// 仿真线计划允许用过程模型 MV 逻辑名(不落设备),创建不校验;执行时一律强校验(见 runner)。
|
|
67
|
+
if (tierInfo.tier === 'real_hitl') {
|
|
68
|
+
assertPlanNodesSafe({ lineId: input.lineId, levels: input.levels, targets: input.targets })
|
|
69
|
+
}
|
|
57
70
|
const db = getAmlRuntime().db
|
|
58
71
|
const id = `pexp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`
|
|
59
72
|
const now = new Date().toISOString()
|
|
60
|
-
|
|
73
|
+
// P4 成本前置:创建时就核算(真实线含 60s 写间隔下限;已知主导周期时按 3×周期建议窗)
|
|
74
|
+
const cost: ExperimentCost = estimateExperimentCost(
|
|
75
|
+
{ levels: input.levels, repeats, settleMs, observeMs, tier: tierInfo.tier },
|
|
76
|
+
{ dominantPeriodMs: input.dominantPeriodMs ?? null },
|
|
77
|
+
)
|
|
78
|
+
const plan: ExperimentPlanBody = {
|
|
61
79
|
version: 1,
|
|
62
80
|
lineId: input.lineId,
|
|
63
|
-
simSceneId:
|
|
81
|
+
simSceneId: tierInfo.simSceneId ?? null,
|
|
64
82
|
specId: input.specId ?? null,
|
|
65
83
|
levels: input.levels,
|
|
66
84
|
repeats,
|
|
@@ -69,12 +87,15 @@ export function createExperimentPlan(input: ExperimentPlanInput): ExperimentPlan
|
|
|
69
87
|
randomizedOrder: input.randomizedOrder !== false,
|
|
70
88
|
abortOnAlarm: input.abortOnAlarm !== false,
|
|
71
89
|
design: 'stepped_multi_level',
|
|
72
|
-
|
|
90
|
+
tier: tierInfo.tier,
|
|
91
|
+
...(input.targets ? { targets: input.targets } : {}),
|
|
92
|
+
cost,
|
|
93
|
+
note: '动作明细经 DCW 写咽喉落 intervention_events([pexp:<id>] 前缀关联);本台账只保存计划与状态',
|
|
73
94
|
}
|
|
74
|
-
const budget = { maxRuns: input.budget?.maxRuns ?? 20, maxDurationMs: input.budget?.maxDurationMs ?? 4 * 3600_000 }
|
|
95
|
+
const budget = { maxRuns: input.budget?.maxRuns ?? Math.max(20, cost.steps), maxDurationMs: input.budget?.maxDurationMs ?? 4 * 3600_000 }
|
|
75
96
|
db.prepare(`INSERT INTO process_model_experiments (id, line_id, plan_json, status, budget_json, created_by, created_at, updated_at)
|
|
76
|
-
VALUES (?, ?, ?,
|
|
77
|
-
.run(id, input.lineId, JSON.stringify(plan), JSON.stringify(budget), input.createdBy ?? '', now, now)
|
|
97
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
98
|
+
.run(id, input.lineId, JSON.stringify(plan), tierInfo.tier === 'real_hitl' ? 'awaiting_approval' : 'planned', JSON.stringify(budget), input.createdBy ?? '', now, now)
|
|
78
99
|
return this_get(db, id)!
|
|
79
100
|
}
|
|
80
101
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 试验计划安全校验(2026-11-02 上线前加固):
|
|
3
|
+
* 计划一旦被 HITL 批准,执行器会以平台身份直接写节点(单卡批准 = 全计划授权)。
|
|
4
|
+
* 因此**创建时与执行前都必须复核节点归属**,防止:
|
|
5
|
+
* - 跨线写:计划 lineId=A,levels 却点名 B 线的节点(越权写别的产线);
|
|
6
|
+
* - 类型错配:targets 写成数控节点(读不到真值)或控制量其实是数采节点;
|
|
7
|
+
* - 量程外水平:创建时就拒绝,避免批准后逐步被 write() 打回、白花产线时间。
|
|
8
|
+
* 纯校验函数,直接读控制器/节点仓(无副作用,不写库)。
|
|
9
|
+
*/
|
|
10
|
+
import { AppError } from '../../../utils/errors'
|
|
11
|
+
import { getDcwController } from '../dcw/dcw-controller'
|
|
12
|
+
import { getDaqNodeRepo } from '../daq/daq-node.repo'
|
|
13
|
+
import type { ExperimentPlanBody } from './experiment-runner'
|
|
14
|
+
|
|
15
|
+
export interface PlanNodeIssue {
|
|
16
|
+
kind: 'control' | 'target' | 'level'
|
|
17
|
+
nodeId: string
|
|
18
|
+
message: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 校验计划节点集合与量程。返回问题列表(空 = 通过);
|
|
23
|
+
* 调用方决定抛错(创建/执行前)还是仅告警。
|
|
24
|
+
*/
|
|
25
|
+
export function validatePlanNodes(plan: Pick<ExperimentPlanBody, 'lineId' | 'levels' | 'targets'>): PlanNodeIssue[] {
|
|
26
|
+
const issues: PlanNodeIssue[] = []
|
|
27
|
+
const controller = getDcwController()
|
|
28
|
+
for (const [controlId, levels] of Object.entries(plan.levels)) {
|
|
29
|
+
const node = controller.byId(controlId)
|
|
30
|
+
if (!node) {
|
|
31
|
+
issues.push({ kind: 'control', nodeId: controlId, message: `控制节点 ${controlId} 不存在(须为 DCW 数控节点)` })
|
|
32
|
+
continue
|
|
33
|
+
}
|
|
34
|
+
if (node.lineId && node.lineId !== plan.lineId) {
|
|
35
|
+
issues.push({ kind: 'control', nodeId: controlId, message: `控制节点 ${controlId} 属于产线 ${node.lineId},与计划产线 ${plan.lineId} 不一致(禁止跨线试验)` })
|
|
36
|
+
}
|
|
37
|
+
if (!node.enabled) {
|
|
38
|
+
issues.push({ kind: 'control', nodeId: controlId, message: `控制节点 ${controlId} 已停用(控制已暂停),不能用于试验` })
|
|
39
|
+
}
|
|
40
|
+
for (const level of levels) {
|
|
41
|
+
if (!Number.isFinite(level)) continue
|
|
42
|
+
if (level < node.min || level > node.max) {
|
|
43
|
+
issues.push({ kind: 'level', nodeId: controlId, message: `水平 ${level} 超出节点安全量程 ${node.min}~${node.max}${node.unit ?? ''}` })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const [controlId, targetId] of Object.entries(plan.targets ?? {})) {
|
|
48
|
+
if (!plan.levels[controlId]) {
|
|
49
|
+
issues.push({ kind: 'target', nodeId: targetId, message: `观测目标绑定到了未声明的控制量 ${controlId}` })
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
const daq = getDaqNodeRepo().byId(targetId)
|
|
53
|
+
if (!daq) {
|
|
54
|
+
issues.push({ kind: 'target', nodeId: targetId, message: `观测目标 ${targetId} 不是数采节点(判读需要 DAQ 序列)` })
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
if (daq.lineId && daq.lineId !== plan.lineId) {
|
|
58
|
+
issues.push({ kind: 'target', nodeId: targetId, message: `观测目标 ${targetId} 属于产线 ${daq.lineId},与计划产线 ${plan.lineId} 不一致` })
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return issues
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 创建/执行前强校验:有问题即 422(消息合并,便于一次改全) */
|
|
65
|
+
export function assertPlanNodesSafe(plan: Pick<ExperimentPlanBody, 'lineId' | 'levels' | 'targets'>): void {
|
|
66
|
+
const issues = validatePlanNodes(plan)
|
|
67
|
+
if (issues.length === 0) return
|
|
68
|
+
throw new AppError(422, 'EXPERIMENT_PLAN_NODE_INVALID', `试验计划节点校验失败:${issues.map(i => i.message).join(';')}`)
|
|
69
|
+
}
|