agentworkshop 0.7.51 → 0.7.53
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 +2097 -1955
- package/.output/.AgentWorkShop/prompts/host-tools.json +2097 -1955
- package/.output/.AgentWorkShop/schema.json +2 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{D0ldVwl-.js → 77DRSnQv.js} +1 -1
- package/.output/public/_nuxt/8oRmGaAV.js +1 -0
- package/.output/public/_nuxt/{BPou3U7b.js → BLnLjzka.js} +1 -1
- package/.output/public/_nuxt/{CFQyYMEn2.js → BSdJTnk12.js} +1 -1
- package/.output/public/_nuxt/{C4lagVdN2.js → BUD1CNvB2.js} +1 -1
- package/.output/public/_nuxt/BXR3tgEk.js +1 -0
- package/.output/public/_nuxt/{B9QzrmgE.js → BhlRInVa.js} +1 -1
- package/.output/public/_nuxt/{DhFv8S2Z.js → BkfA3BbD.js} +1 -1
- package/.output/public/_nuxt/{ChGuLxwW2.js → BpcQDwKM2.js} +1 -1
- package/.output/public/_nuxt/{DQMbdg4t.js → BwlGxRxA.js} +1 -1
- package/.output/public/_nuxt/{Bt2ZL5332.js → C4sQKuhk2.js} +1 -1
- package/.output/public/_nuxt/{zh-S_7rN2.js → CBUIODly2.js} +1 -1
- package/.output/public/_nuxt/CR-ILcRu2.js +1 -0
- package/.output/public/_nuxt/CZLnEnbE.js +14 -0
- package/.output/public/_nuxt/{jRTz0hjN2.js → Chxx-DIE2.js} +1 -1
- package/.output/public/_nuxt/{BGAaKBeo2.js → CjwxhpwR2.js} +1 -1
- package/.output/public/_nuxt/{D89BUtx6.js → CvGYm7w8.js} +1 -1
- package/.output/public/_nuxt/{B9BmiUil.js → DAGuPgXa.js} +1 -1
- package/.output/public/_nuxt/{DefDtlKK.js → DE6H1HdJ.js} +1 -1
- package/.output/public/_nuxt/{DzfVS8N72.js → DFhyhDGa2.js} +1 -1
- package/.output/public/_nuxt/{BXx9AxdF2.js → DSqMyLCV2.js} +1 -1
- package/.output/public/_nuxt/{asmJ99nX2.js → DV5joWTn2.js} +1 -1
- package/.output/public/_nuxt/{DClNt1uS.js → DVOR2pWg.js} +1 -1
- package/.output/public/_nuxt/DWsgRq2c.js +1 -0
- package/.output/public/_nuxt/{CU-mhG0-.js → DZDi8inD.js} +1 -1
- package/.output/public/_nuxt/{DMYYS5sK.js → Dep0Hc9w.js} +1 -1
- package/.output/public/_nuxt/{JAM4aNC_.js → DffgG8vT.js} +1 -1
- package/.output/public/_nuxt/{CFQSjB1h.js → DlCktWDT.js} +1 -1
- package/.output/public/_nuxt/{CP0I2l-6.js → DmzmgYHb.js} +1 -1
- package/.output/public/_nuxt/PluginSlot.CGH0vb95.css +1 -0
- package/.output/public/_nuxt/{lWYQbIR3.js → WmMwIS4y.js} +1 -1
- package/.output/public/_nuxt/{_id_.DamiFT0Q.css → _id_.rdGx-UDx.css} +1 -1
- package/.output/public/_nuxt/{BgEDwFMf.js → _kUzq9VF.js} +1 -1
- package/.output/public/_nuxt/_wsId_.XjmieZaJ.css +1 -0
- package/.output/public/_nuxt/{B7jlMWsz.js → aV6YPjg0.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/5ccc21c2-aba0-4b63-9a13-410e0569e345.json +1 -0
- package/.output/public/_nuxt/channel-templates.DkNZg-lF.css +1 -0
- package/.output/public/_nuxt/{default.CXb_zoN6.css → default.CyLpQD1C.css} +1 -1
- package/.output/public/_nuxt/o9rJf00k.js +1 -0
- package/.output/public/_nuxt/sl1EEoCr2.js +21 -0
- package/.output/public/robots.txt +3 -0
- package/.output/server/chunks/_/binding-authz.mjs +1 -1
- package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
- package/.output/server/chunks/_/entity.mjs +1 -1
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +2268 -1501
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
- package/.output/server/chunks/build/{PluginSlot-D2WUZgbp.mjs → PluginSlot-CT4YaNrB.mjs} +5 -5
- package/.output/server/chunks/build/{PluginSlot-D2WUZgbp.mjs.map → PluginSlot-CT4YaNrB.mjs.map} +1 -1
- package/.output/server/chunks/build/TownView-fP9BiALv.mjs +1 -1
- package/.output/server/chunks/build/{_id_-BUpQSlzo.mjs → _id_-CK-QFrDV.mjs} +55 -51
- package/.output/server/chunks/build/_id_-CK-QFrDV.mjs.map +1 -0
- package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs → _wsId_-DdqXzycE.mjs} +320 -202
- package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs.map → _wsId_-DdqXzycE.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-CDLcboCv.mjs → agents-DqICy4AL.mjs} +6 -6
- package/.output/server/chunks/build/{agents-CDLcboCv.mjs.map → agents-DqICy4AL.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-DjEsj0_v.mjs → channel-templates-gdCLajKy.mjs} +114 -25
- package/.output/server/chunks/build/channel-templates-gdCLajKy.mjs.map +1 -0
- package/.output/server/chunks/build/daq-N69AOtgw.mjs +1 -1
- package/.output/server/chunks/build/dcw-CN9d3Rs7.mjs +1 -1
- package/.output/server/chunks/build/{default-DCf9tn1i.mjs → default-CXUe4HL7.mjs} +65 -62
- package/.output/server/chunks/build/{default-DCf9tn1i.mjs.map → default-CXUe4HL7.mjs.map} +1 -1
- package/.output/server/chunks/build/{pages-rZKH72eC.mjs → pages-CRMeXrxG.mjs} +3 -3
- package/.output/server/chunks/build/{pages-rZKH72eC.mjs.map → pages-CRMeXrxG.mjs.map} +1 -1
- package/.output/server/chunks/build/{plugins-DSka7-vS.mjs → plugins-NAS9MQ5r.mjs} +2 -2
- package/.output/server/chunks/build/{plugins-DSka7-vS.mjs.map → plugins-NAS9MQ5r.mjs.map} +1 -1
- package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs → schedules-D8vYHgQ5.mjs} +2 -2
- package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs.map → schedules-D8vYHgQ5.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-CAJWvul5.mjs → settings-B7HA-sdb.mjs} +3 -3
- package/.output/server/chunks/build/{settings-CAJWvul5.mjs.map → settings-B7HA-sdb.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-DBBvIToa.mjs → teams-wM-MdLv9.mjs} +8 -8
- package/.output/server/chunks/build/{teams-DBBvIToa.mjs.map → teams-wM-MdLv9.mjs.map} +1 -1
- package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
- package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs → useAgentHarnessOptions-BnFCh23W.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs.map → useAgentHarnessOptions-BnFCh23W.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs → useAgentTemplateActions-DsBRUQni.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs.map → useAgentTemplateActions-DsBRUQni.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs → useAgentTemplateForm-DzQ_t2Ue.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs.map → useAgentTemplateForm-DzQ_t2Ue.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs → useAgentTemplatesCatalog-Q7LgG1Af.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs.map → useAgentTemplatesCatalog-Q7LgG1Af.mjs.map} +1 -1
- package/.output/server/chunks/build/useDaqAddNode-kW7uTSMQ.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailNode-D_vhG0jF.mjs +1 -1
- package/.output/server/chunks/build/useDaqDetailParams-JfqHvTxr.mjs +1 -1
- package/.output/server/chunks/build/useDaqFilters-BUQtZ82a.mjs +1 -1
- package/.output/server/chunks/build/useDaqStream-wOxZcMDA.mjs +1 -1
- package/.output/server/chunks/build/useDaqTemplates-BqQRdrIm.mjs +1 -1
- package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs → useDashboardData-DWJ6vHjm.mjs} +2 -2
- package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs.map → useDashboardData-DWJ6vHjm.mjs.map} +1 -1
- package/.output/server/chunks/build/useDcwAddNode-C1HDP3yG.mjs +1 -1
- package/.output/server/chunks/build/useDcwStream-D04kCV3J.mjs +1 -1
- package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs → useTeamActions-BOLQkYxg.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs.map → useTeamActions-BOLQkYxg.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs → useTeamAddMemberDialog-BCgrLPxI.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs.map → useTeamAddMemberDialog-BCgrLPxI.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs → useTeamCreateDialog-CJk40LqS.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs.map → useTeamCreateDialog-CJk40LqS.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs → useTeamDeployDialog-49hdUXQP.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs.map → useTeamDeployDialog-49hdUXQP.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs → useTeamPluginDialog-Dh-QOoiU.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs.map → useTeamPluginDialog-Dh-QOoiU.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs → useTeamsCatalog-HBSyKt5P.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs.map → useTeamsCatalog-HBSyKt5P.mjs.map} +1 -1
- package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs → useWorkshopApi-C9sTYu1F.mjs} +13 -2
- package/.output/server/chunks/build/useWorkshopApi-C9sTYu1F.mjs.map +1 -0
- package/.output/server/chunks/build/useWorkshopWs-Bm80bLn7.mjs.map +1 -1
- package/.output/server/chunks/routes/api/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/index.post.mjs +14 -3
- package/.output/server/chunks/routes/api/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/mcp/workshop.mjs +43 -14
- package/.output/server/chunks/routes/api/mcp/workshop.mjs.map +1 -1
- package/.output/server/chunks/routes/api/metrics.mjs +2 -0
- package/.output/server/chunks/routes/api/metrics.mjs.map +1 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
- package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
- package/.output/server/chunks/routes/api/system/backup/list.get.mjs +47 -0
- package/.output/server/chunks/routes/api/system/backup/list.get.mjs.map +1 -0
- package/.output/server/chunks/routes/api/system/backup/run.post.mjs +35 -0
- package/.output/server/chunks/routes/api/system/backup/run.post.mjs.map +1 -0
- 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/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/index.patch.mjs +15 -4
- package/.output/server/chunks/routes/api/system/index.patch.mjs.map +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/settings/events.get.mjs +1 -1
- package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +15 -3
- package/.output/server/chunks/routes/api/system/settings/reset.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/system/timezone.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.delete.mjs +14 -3
- package/.output/server/chunks/routes/api/users/_id_.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/users/_id_.put.mjs +14 -3
- package/.output/server/chunks/routes/api/users/_id_.put.mjs.map +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 +3 -2
- package/.output/server/chunks/routes/api/users/login.post.mjs.map +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 +4 -1
- package/.output/server/chunks/routes/api/users/register.post.mjs.map +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/a2a/_agentId/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +19 -15
- package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs.map +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 +54 -0
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs +51 -0
- package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs.map +1 -0
- 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/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.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/approvals/_id/decide.post.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.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 +10 -4
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +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.post.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/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/events.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.post.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/line.put.mjs +37 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.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/index.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +4 -4
- 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/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/index.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/journal/node/_nodeId/rollback.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +6 -1
- package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs.map +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/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 +3 -3
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.post.mjs.map +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/fs/dirs.get.mjs +14 -2
- package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs.map +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.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/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.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 +3 -3
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index9.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/notifications/read.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/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/schedules/_id/runs.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/report.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/tasks/_id_.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.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_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +4 -1
- package/.output/server/chunks/routes/api/workshop/users/register.post.mjs.map +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 +350 -52
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +7 -3
- package/README.md +11 -5
- package/app/components/app-header/HitlBell.vue +9 -9
- package/app/components/dcw/DcwAddNodeModal.vue +3 -3
- package/app/components/dcw/DcwNodesTable.vue +4 -4
- package/app/components/dcw/DcwRecipeEditModal.vue +2 -2
- package/app/components/workshop/ChatMemberPanel.vue +39 -38
- package/app/components/workshop/ChatTimeline.vue +33 -24
- package/app/components/workshop/Composer.vue +7 -7
- package/app/components/workshop/NotificationCenter.vue +22 -13
- package/app/components/workshop/PluginSlot.vue +1 -1
- package/app/components/workshop/TaskInspectorDrawer.vue +5 -5
- package/app/components/workshop/blocks/ClusterTool.vue +1 -1
- package/app/components/workshop/composer/ComposerToolbar.vue +2 -2
- package/app/components/workshop/composer/MentionMenu.vue +1 -1
- package/app/components/workshop/composer/ReplyChip.vue +2 -2
- package/app/components/workshop/composer/StatusChip.vue +7 -7
- package/app/components/workshop/console/LineOperationsPanel.vue +15 -14
- package/app/components/workshop/lanes/LaneHeader.vue +5 -3
- package/app/components/workshop/session-list/ChannelSettingsModal.vue +43 -1
- package/app/composables/useCodeCopy.ts +16 -2
- package/app/composables/workshop/useWorkshopApi.ts +11 -2
- package/app/pages/workshop/channel-templates.vue +43 -4
- package/app/stores/workshop/notifications.ts +43 -17
- package/config.yml +1 -1
- package/docs/cli.en.md +3 -3
- 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/dicts/_en.json +1551 -1557
- package/i18n/dicts/_en2.json +300 -300
- package/i18n/dicts/_en4.json +114 -115
- package/i18n/dicts/agentLanesView.json +61 -57
- package/i18n/dicts/appHeader.json +17 -7
- package/i18n/dicts/channelSessionList.json +51 -48
- package/i18n/dicts/chat.json +79 -0
- package/i18n/dicts/clusterTool.json +4 -3
- package/i18n/dicts/composer.json +38 -38
- package/i18n/dicts/ctpl.json +37 -32
- package/i18n/dicts/dcwDetail.json +219 -209
- package/i18n/dicts/lineOps.json +14 -0
- package/i18n/dicts/multiChannelView.json +13 -13
- package/i18n/dicts/notifications.json +13 -0
- package/i18n/dicts/taskInspectorDrawer.json +25 -19
- package/i18n/locales/en.ts +157 -8
- package/i18n/locales/zh-CN.ts +157 -8
- package/package.json +1 -1
- package/public/robots.txt +3 -0
- package/scripts/_audit/kb-team-mock-e2e.mjs +146 -0
- package/scripts/_audit/kb-team-omp-e2e.mjs +229 -0
- package/server/api/mcp/workshop.ts +8 -1
- package/server/api/metrics.ts +4 -1
- package/server/api/plugins/[name]/[...path].ts +4 -3
- package/server/api/system/backup/list.get.ts +32 -0
- package/server/api/system/backup/run.post.ts +21 -0
- package/server/api/system/settings/index.patch.ts +12 -2
- package/server/api/system/settings/reset.post.ts +11 -2
- package/server/api/users/[id].delete.ts +9 -2
- package/server/api/users/[id].put.ts +9 -2
- package/server/api/users/index.post.ts +9 -2
- package/server/api/users/login.post.ts +3 -3
- package/server/api/users/register.post.ts +11 -1
- package/server/api/workshop/a2a/[agentId]/rpc/index.post.ts +23 -13
- package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -0
- package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -0
- package/server/api/workshop/channel-templates/[id]/instantiate.post.ts +8 -1
- package/server/api/workshop/channels/[id]/line.put.ts +30 -0
- package/server/api/workshop/dcw/line/query.get.ts +6 -0
- package/server/api/workshop/dcw/recipes/[id]/revert.post.ts +3 -2
- package/server/api/workshop/fs/dirs.get.ts +19 -1
- package/server/api/workshop/ops-logs/index.get.ts +3 -2
- package/server/api/workshop/users/register.post.ts +7 -0
- package/server/mcp/workshop-server.ts +36 -13
- package/server/middleware/00-security-headers.ts +38 -0
- package/server/middleware/01-rate-guard.ts +101 -0
- package/server/plugins/backup.ts +56 -1
- package/server/plugins-builtin/diag-bridge/host/plugin.mjs +18 -11
- package/server/repositories/user.repository.ts +10 -5
- package/server/services/user.service.ts +24 -1
- package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +7 -2
- package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +4 -2
- package/server/services/workshop/agents/host-tool-bridge/tools/tasks.ts +15 -2
- package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -0
- package/server/services/workshop/agents/industrial/index.ts +1 -1
- package/server/services/workshop/agents/industrial/ops-tools.ts +168 -26
- package/server/services/workshop/agents/node-bindings.repo.ts +10 -1
- package/server/services/workshop/agents/node-delegation.ts +150 -0
- package/server/services/workshop/agents/tool-classes.ts +4 -0
- package/server/services/workshop/aml/dataset-builder.ts +4 -2
- package/server/services/workshop/aml/job-orchestrator/process.ts +1 -0
- package/server/services/workshop/aml/job-orchestrator/shared.ts +2 -0
- package/server/services/workshop/aml/job-orchestrator/start-job.ts +5 -2
- package/server/services/workshop/db/channel.repo.ts +11 -1
- package/server/services/workshop/db/database/migrations.ts +2 -0
- package/server/services/workshop/db/database/rows.ts +2 -0
- package/server/services/workshop/db/database/seed.ts +30 -0
- package/server/services/workshop/dcw/dcw-controller/recipes.ts +60 -4
- package/server/services/workshop/dcw/dcw-controller/write.ts +35 -6
- package/server/services/workshop/dcw/dcw-recipe.repo.ts +4 -3
- package/server/services/workshop/dcw/param-map.repo.ts +3 -0
- package/server/services/workshop/plugins/host/init.mjs +9 -1
- package/server/services/workshop/plugins/host/load.mjs +2 -2
- package/server/services/workshop/runtime/manager/admin-channel.ts +27 -1
- package/server/services/workshop/runtime/manager/channel-templates.ts +27 -2
- package/server/services/workshop/runtime/manager/runtime-wiring.ts +17 -1
- package/server/services/workshop/runtime/manager/types.ts +2 -0
- package/shared/config/schema.json +2 -0
- package/.output/public/_nuxt/8FXd9As6.js +0 -1
- package/.output/public/_nuxt/BOmDHp5L.js +0 -14
- package/.output/public/_nuxt/BWU1pvLL.js +0 -1
- package/.output/public/_nuxt/CdIsmU5a2.js +0 -21
- package/.output/public/_nuxt/D0SNhlnt.js +0 -1
- package/.output/public/_nuxt/DnH9SRMW2.js +0 -1
- package/.output/public/_nuxt/ON2x-t6n.js +0 -1
- package/.output/public/_nuxt/PluginSlot.DmjNbrcX.css +0 -1
- package/.output/public/_nuxt/_wsId_.DkrQkT6r.css +0 -1
- package/.output/public/_nuxt/builds/meta/912eb5bb-670e-4cc8-b21d-7fc097723466.json +0 -1
- package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +0 -1
- package/.output/server/chunks/build/_id_-BUpQSlzo.mjs.map +0 -1
- package/.output/server/chunks/build/channel-templates-DjEsj0_v.mjs.map +0 -1
- package/.output/server/chunks/build/useWorkshopApi-B1B9vd4m.mjs.map +0 -1
- package/scripts/.chk-tok +0 -1
- package/scripts/.retrain-body.json +0 -1
- package/scripts/.retrain3-body.json +0 -1
- package/scripts/.rt-tok +0 -1
- package/scripts/.rt3-tok +0 -1
|
@@ -17,10 +17,26 @@ import { fanoutQuery, windowOf } from './audit-query'
|
|
|
17
17
|
// 运维日志 / Recipe 变更史查询(Agent 自查面:负责产线 scoped)
|
|
18
18
|
// ================================================================
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/** v18:频道绑定产线(只读扩权)——经全局 manager 读;manager 未装配/未绑定 = null */
|
|
21
|
+
function channelBoundLineId(agentId: string): string | null {
|
|
22
|
+
try {
|
|
23
|
+
const g = globalThis as typeof globalThis & {
|
|
24
|
+
__workshopManager?: { channelLineBindingOf(id: string): string | null }
|
|
25
|
+
}
|
|
26
|
+
return g.__workshopManager?.channelLineBindingOf(agentId) ?? null
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Agent 负责范围 = 绑定节点的全集(节点 id 集 + 这些节点所属产线集;写权限依据)
|
|
34
|
+
* ∪ 频道绑定产线(boundLineIds;v18 只读扩权:日志/配方史/上下文可读,写仍走节点授权)。 */
|
|
35
|
+
export function agentOpsScope(agentId: string): { lineIds: string[], nodeIds: Set<string>, boundLineIds: string[] } | null {
|
|
22
36
|
const bindings = getAgentNodeBindingRepo().byAgent(agentId)
|
|
23
|
-
|
|
37
|
+
const boundLine = channelBoundLineId(agentId)
|
|
38
|
+
const boundLineIds = boundLine ? [boundLine] : []
|
|
39
|
+
if (bindings.length === 0 && boundLineIds.length === 0) return null
|
|
24
40
|
const lineIds = new Set<string>()
|
|
25
41
|
const nodeIds = new Set<string>()
|
|
26
42
|
for (const b of bindings) {
|
|
@@ -31,7 +47,17 @@ export function agentOpsScope(agentId: string): { lineIds: string[], nodeIds: Se
|
|
|
31
47
|
}
|
|
32
48
|
catch { /* 节点刚被删等情况忽略 */ }
|
|
33
49
|
}
|
|
34
|
-
return { lineIds: [...lineIds], nodeIds }
|
|
50
|
+
return { lineIds: [...lineIds], nodeIds, boundLineIds }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 读工具的可见产线全集 = 节点授权线 ∪ 频道绑定线(去重) */
|
|
54
|
+
function readableLineIds(scope: { lineIds: string[], boundLineIds: string[] }): string[] {
|
|
55
|
+
return [...new Set([...scope.lineIds, ...scope.boundLineIds])]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 产线展示标注:仅频道绑定(非节点授权)的线标注只读来源 */
|
|
59
|
+
function lineTag(lid: string, scope: { lineIds: string[], boundLineIds: string[] }): string {
|
|
60
|
+
return scope.lineIds.includes(lid) ? '' : '(频道绑定,只读)'
|
|
35
61
|
}
|
|
36
62
|
|
|
37
63
|
/** 配方参数的节点失效态(数据一致性展示/Agent 提示共用):null=正常 */
|
|
@@ -63,19 +89,20 @@ export async function toolOpsLog(agentId: string, args: {
|
|
|
63
89
|
const audit = getOps()?.audit
|
|
64
90
|
if (!audit) return { text: '审计仓储未装配(服务未就绪),请稍后重试。', isError: true }
|
|
65
91
|
const scope = agentOpsScope(agentId)
|
|
66
|
-
if (!scope) return { text: '
|
|
92
|
+
if (!scope) return { text: '你尚未绑定任何工业节点,所在频道也未绑定产线,无日志可查(日志权限跟随节点绑定或频道绑线)。', isError: true }
|
|
67
93
|
const nodeId = String(args.node_id ?? '').trim()
|
|
68
94
|
const lineId = String(args.line_id ?? '').trim()
|
|
95
|
+
const readable = readableLineIds(scope)
|
|
69
96
|
if (nodeId && !scope.nodeIds.has(nodeId))
|
|
70
97
|
return { text: `无权查询节点 ${nodeId} 的日志(仅可查自己绑定的节点;用 my_industrial_nodes 查看绑定)。`, isError: true }
|
|
71
|
-
if (lineId && !
|
|
72
|
-
return { text: `无权查询产线 ${lineId} 的日志(
|
|
98
|
+
if (lineId && !readable.includes(lineId))
|
|
99
|
+
return { text: `无权查询产线 ${lineId} 的日志(你的可读产线:${readable.join(', ') || '(无)'})。`, isError: true }
|
|
73
100
|
const kind = String(args.kind ?? '').trim() || undefined
|
|
74
101
|
const actorKind = String(args.actor_kind ?? '').trim() || undefined
|
|
75
102
|
const mine = args.mine === true || args.mine === 'true'
|
|
76
103
|
const { minutes, limit, from } = windowOf(args)
|
|
77
104
|
|
|
78
|
-
const lines = lineId ? [lineId] :
|
|
105
|
+
const lines = lineId ? [lineId] : readable
|
|
79
106
|
let rows = fanoutQuery(audit, lines, lid => ({ lineId: lid, kind, actorKind, actor: mine ? agentId : undefined, from, limit }))
|
|
80
107
|
if (nodeId) rows = rows.filter(r => r.targetId === nodeId)
|
|
81
108
|
rows.sort((a, b) => String(b.at).localeCompare(String(a.at)))
|
|
@@ -86,7 +113,7 @@ export async function toolOpsLog(agentId: string, args: {
|
|
|
86
113
|
const src = OPS_ACTOR_LABEL[String(r.actorKind)] ?? String(r.actorKind)
|
|
87
114
|
return `- [${fmtAuditAt(String(r.at))}] 来源=${src} 操作者=${String(r.actorName) || String(r.actor)} | ${String(r.action)} | ${String(r.summary)}`
|
|
88
115
|
})
|
|
89
|
-
const scopeNote = lineId ? `产线 ${lineId}` :
|
|
116
|
+
const scopeNote = lineId ? `产线 ${lineId}` : `可读产线 ${readable.length} 条`
|
|
90
117
|
return {
|
|
91
118
|
text: `运维日志(${scopeNote},近 ${minutes} 分钟,${rows.length} 条,新→旧):\n${body.join('\n')}\n\n说明:来源=Agent 的操作者格式为「Channel名/成员名」;需要节点级参数值变更史用 dcw_journal,配方下发/回退专门视图用 recipe_log。`,
|
|
92
119
|
}
|
|
@@ -103,14 +130,15 @@ export async function toolRecipeLog(agentId: string, args: {
|
|
|
103
130
|
const audit = getOps()?.audit
|
|
104
131
|
if (!audit) return { text: '审计仓储未装配(服务未就绪),请稍后重试。', isError: true }
|
|
105
132
|
const scope = agentOpsScope(agentId)
|
|
106
|
-
if (!scope) return { text: '
|
|
133
|
+
if (!scope) return { text: '你尚未绑定任何工业节点,所在频道也未绑定产线,无 Recipe 历史可查(权限跟随节点绑定或频道绑线)。', isError: true }
|
|
107
134
|
const lineId = String(args.line_id ?? '').trim()
|
|
108
|
-
|
|
109
|
-
|
|
135
|
+
const readable = readableLineIds(scope)
|
|
136
|
+
if (lineId && !readable.includes(lineId))
|
|
137
|
+
return { text: `无权查询产线 ${lineId} 的 Recipe 历史(你的可读产线:${readable.join(', ') || '(无)'})。`, isError: true }
|
|
110
138
|
const recipeId = String(args.recipe_id ?? '').trim() || undefined
|
|
111
139
|
const { minutes, limit, from } = windowOf(args)
|
|
112
140
|
|
|
113
|
-
const lines = lineId ? [lineId] :
|
|
141
|
+
const lines = lineId ? [lineId] : readable
|
|
114
142
|
const rows = fanoutQuery(audit, lines, lid => [
|
|
115
143
|
{ lineId: lid, kind: 'recipe', recipeId, from, limit },
|
|
116
144
|
{ lineId: lid, kind: 'rollback', recipeId, from, limit },
|
|
@@ -131,9 +159,8 @@ export async function toolRecipeLog(agentId: string, args: {
|
|
|
131
159
|
: action
|
|
132
160
|
return `- [${fmtAuditAt(String(r.at))}] ${tag} 来源=${src} 操作者=${String(r.actorName) || String(r.actor)} | ${String(r.summary)}${r.recipeId ? `(配方 ${String(r.recipeId).slice(0, 8)})` : ''}`
|
|
133
161
|
})
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
162
|
+
const text = `Recipe 变更史(${lineId ? `产线 ${lineId}` : `可读产线 ${readable.length} 条`},近 ${minutes} 分钟,${rows.length} 条,新→旧):\n${body.join('\n')}\n\n说明:配方下发=整批参数写命令;优化开窗=单次设定变更(含 Agent 假设);回退执行=已恢复基线值。节点级参数值逐笔历史用 dcw_journal(node_id)。`
|
|
163
|
+
return { text }
|
|
137
164
|
}
|
|
138
165
|
|
|
139
166
|
// ================================================================
|
|
@@ -145,11 +172,12 @@ export async function toolRecipeLog(agentId: string, args: {
|
|
|
145
172
|
* 配方目标 vs PLC 当前值对照、lastGood 批次。 */
|
|
146
173
|
export async function toolLineContext(agentId: string, args: { line_id?: string } = {}): Promise<{ text: string, isError?: boolean }> {
|
|
147
174
|
const scope = agentOpsScope(agentId)
|
|
148
|
-
if (!scope) return { text: '
|
|
175
|
+
if (!scope) return { text: '你尚未绑定任何工业节点,所在频道也未绑定产线,暂无产线上下文(可在频道设置绑定产线获得只读上下文,或在数字孪生界面绑定节点)。' }
|
|
149
176
|
const wanted = String(args.line_id ?? '').trim()
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
177
|
+
const readable = readableLineIds(scope)
|
|
178
|
+
const lineIds = wanted ? [wanted] : readable
|
|
179
|
+
if (wanted && !readable.includes(wanted)) {
|
|
180
|
+
return { text: `产线 ${wanted} 不在你的可读范围(节点授权与频道绑定覆盖:${readable.join(', ') || '无'})。`, isError: true }
|
|
153
181
|
}
|
|
154
182
|
if (lineIds.length === 0) return { text: '你绑定的节点均未分配产线(未挂线的节点没有产线/产品/配方上下文)。' }
|
|
155
183
|
|
|
@@ -159,7 +187,7 @@ export async function toolLineContext(agentId: string, args: { line_id?: string
|
|
|
159
187
|
const run = getActiveLineRun(lid)
|
|
160
188
|
const recipe = run?.recipeId ? getDcwController().listRecipes().find(r => r.id === run.recipeId) : undefined
|
|
161
189
|
const parts: string[] = []
|
|
162
|
-
parts.push(`■ 产线 ${line?.name ?? lid}(${lid})· 状态:${run ? '运行中' : '待机/停线'}`)
|
|
190
|
+
parts.push(`■ 产线 ${line?.name ?? lid}(${lid})${lineTag(lid, scope)} · 状态:${run ? '运行中' : '待机/停线'}`)
|
|
163
191
|
if (run) {
|
|
164
192
|
parts.push(` 活动批次 ${run.runId.slice(0, 8)} · 产品「${run.productName}」(${run.productId}) · 开跑 ${run.startedAt.slice(11, 19)} · 已打标 ${run.taggedSamples} 样本`)
|
|
165
193
|
}
|
|
@@ -210,7 +238,7 @@ export async function toolLineContext(agentId: string, args: { line_id?: string
|
|
|
210
238
|
sections.push(parts.join('\n'))
|
|
211
239
|
}
|
|
212
240
|
return {
|
|
213
|
-
text: `你控制的产线全景(${sections.length} 条):\n\n${sections.join('\n\n')}\n\n说明:配方目标=开跑批次冻结的工艺窗口;PLC
|
|
241
|
+
text: `你控制的产线全景(${sections.length} 条):\n\n${sections.join('\n\n')}\n\n说明:配方目标=开跑批次冻结的工艺窗口;PLC 当前值=实时读数;(频道绑定,只读)= 该线来自频道绑定的只读授权,可看日志/配方/状态,参数下发仍需节点授权。把验证过的最佳参数固化到配方用 recipe_update;回退配方到稳定版本用 recipe_rollback;逐节点参数变更史用 dcw_journal;配方版本史用 recipe_versions。`,
|
|
214
242
|
}
|
|
215
243
|
}
|
|
216
244
|
|
|
@@ -221,9 +249,11 @@ export async function toolRecipeVersions(agentId: string, args: { recipe_id?: st
|
|
|
221
249
|
if (!recipeId) return { text: 'recipe_id 必填(line_context 可看到当前配方的 id)。', isError: true }
|
|
222
250
|
const recipe = getDcwController().listRecipes().find(r => r.id === recipeId)
|
|
223
251
|
if (!recipe) return { text: `配方 ${recipeId} 不存在。`, isError: true }
|
|
252
|
+
// 只读面:节点授权线 ∪ 频道绑定线均可看版本史(回退走 toolRecipeRollback 的写门)
|
|
224
253
|
const scope = agentOpsScope(agentId)
|
|
225
|
-
|
|
226
|
-
|
|
254
|
+
const readable = scope ? readableLineIds(scope) : []
|
|
255
|
+
if (!recipe.lineId || !readable.includes(recipe.lineId)) {
|
|
256
|
+
return { text: `无权查看配方 ${recipeId} 的版本史(该配方不在你可读的产线上)。`, isError: true }
|
|
227
257
|
}
|
|
228
258
|
const rows = getDcwController().recipeVersions(recipeId)
|
|
229
259
|
const limit = Math.min(Number(args.limit) || 20, 50)
|
|
@@ -327,16 +357,19 @@ export async function toolRecipeUpdate(agentId: string, args: {
|
|
|
327
357
|
}
|
|
328
358
|
|
|
329
359
|
/** 工具:recipe_rollback —— 回退配方参数到稳定版本(指定历史版本或已知良好批次快照)。
|
|
330
|
-
* 生成新版本(非破坏,历史保留);不改运行中 PLC 当前值。
|
|
360
|
+
* 生成新版本(非破坏,历史保留);不改运行中 PLC 当前值。
|
|
361
|
+
* v19 dispatch=true = **统一回退**:定义回退 + 该版本参数整批重下发到 PLC(批次级恢复)。 */
|
|
331
362
|
export async function toolRecipeRollback(agentId: string, args: {
|
|
332
363
|
recipe_id?: string
|
|
333
364
|
version?: number | string
|
|
334
365
|
to_last_good?: boolean | string
|
|
366
|
+
dispatch?: boolean | string
|
|
335
367
|
reason?: string
|
|
336
368
|
}): Promise<{ text: string, isError?: boolean }> {
|
|
337
369
|
const recipeId = String(args.recipe_id ?? '').trim()
|
|
338
370
|
const reason = String(args.reason ?? '').trim()
|
|
339
371
|
const toLastGood = args.to_last_good === true || args.to_last_good === 'true'
|
|
372
|
+
const dispatch = args.dispatch === true || args.dispatch === 'true'
|
|
340
373
|
const version = Number(args.version)
|
|
341
374
|
if (!recipeId) return { text: 'recipe_id 必填。', isError: true }
|
|
342
375
|
if (!reason) return { text: 'reason 必填:回退必须说明原因(如优化翻车/越限),便于版本史追溯。', isError: true }
|
|
@@ -351,6 +384,20 @@ export async function toolRecipeRollback(agentId: string, args: {
|
|
|
351
384
|
return { text: `不能回退到 v${version}(当前已是 v${recipe.version ?? 1};回退目标是更早的版本)。`, isError: true }
|
|
352
385
|
}
|
|
353
386
|
try {
|
|
387
|
+
if (dispatch) {
|
|
388
|
+
const { recipe: updated, run } = await getDcwController().rollbackRecipeAndDispatch(recipeId, {
|
|
389
|
+
version: toLastGood ? undefined : version,
|
|
390
|
+
toLastGood,
|
|
391
|
+
by: 'agent',
|
|
392
|
+
actorName: agentBadgeLabel(agentId),
|
|
393
|
+
actor: agentId,
|
|
394
|
+
description: reason,
|
|
395
|
+
})
|
|
396
|
+
const okN = run.results.filter(r => r.ok).length
|
|
397
|
+
return {
|
|
398
|
+
text: `统一回退完成:配方「${updated.name}」已生成 v${updated.version ?? 1},参数恢复为目标版本(${toLastGood ? '已知良好批次冻结' : `v${version}`}),并已整批重下发到 PLC(${okN}/${run.results.length} 参数成功);原因:${reason}。\n用 daq_query 复测确认恢复效果;版本史用 recipe_versions 复核。`,
|
|
399
|
+
}
|
|
400
|
+
}
|
|
354
401
|
const updated = getDcwController().revertRecipe(recipeId, {
|
|
355
402
|
version: toLastGood ? undefined : version,
|
|
356
403
|
toLastGood,
|
|
@@ -361,10 +408,105 @@ export async function toolRecipeRollback(agentId: string, args: {
|
|
|
361
408
|
description: reason,
|
|
362
409
|
})
|
|
363
410
|
return {
|
|
364
|
-
text: `回退完成:配方「${updated.name}」已生成 v${updated.version ?? 1},参数恢复为目标版本(${toLastGood ? '已知良好批次冻结' : `v${version}`});原因:${reason}。\n
|
|
411
|
+
text: `回退完成:配方「${updated.name}」已生成 v${updated.version ?? 1},参数恢复为目标版本(${toLastGood ? '已知良好批次冻结' : `v${version}`});原因:${reason}。\n注意:仅回退了配方定义,运行中 PLC 未变动;要把恢复参数写入产线(统一回退),用 recipe_rollback 并带 dispatch=true。版本史用 recipe_versions 复核。`,
|
|
365
412
|
}
|
|
366
413
|
}
|
|
367
414
|
catch (err) {
|
|
368
415
|
return { text: `回退失败:${err instanceof Error ? err.message : String(err)}`, isError: true }
|
|
369
416
|
}
|
|
370
417
|
}
|
|
418
|
+
|
|
419
|
+
/** 工具:recipe_trial —— 多参数候选整批试验下发(v19 配方链路核心)。
|
|
420
|
+
* 候选值只覆盖列出节点(**必须是自己绑定的数控节点**);整批一次落产线,**不写配方版本** ——
|
|
421
|
+
* 复测判读:有进步/达标 → recipe_update 固化(同 id 版本+1);劣化 → recipe_rollback(dispatch=true) 统一回退。
|
|
422
|
+
* 受同线试验节拍卡控(默认 ≥5 分钟,防连发震荡);四层限界(量程∩参数∩产品)照常拦截。 */
|
|
423
|
+
export async function toolRecipeTrial(agentId: string, args: {
|
|
424
|
+
recipe_id?: string
|
|
425
|
+
params?: Array<{ node_id?: string, value?: number | string }>
|
|
426
|
+
hypothesis?: string
|
|
427
|
+
}): Promise<{ text: string, isError?: boolean }> {
|
|
428
|
+
const recipeId = String(args.recipe_id ?? '').trim()
|
|
429
|
+
const hypothesis = String(args.hypothesis ?? '').trim()
|
|
430
|
+
if (!recipeId) return { text: 'recipe_id 必填(line_context 可看到当前配方 id)。', isError: true }
|
|
431
|
+
if (!hypothesis) return { text: 'hypothesis 必填:试验必须声明依据(知识库条目/数据分析结论),便于审计追溯。', isError: true }
|
|
432
|
+
const list = (args.params ?? []).filter(p => p && String(p.node_id ?? '').trim() && Number.isFinite(Number(p.value)))
|
|
433
|
+
.map(p => ({ nodeId: String(p.node_id).trim(), value: Number(p.value) }))
|
|
434
|
+
if (list.length === 0) return { text: 'params 至少提供一条 {node_id, value}(value 必须为数字);试验的意义就是多参数一次整批改动。', isError: true }
|
|
435
|
+
const recipe = getDcwController().listRecipes().find(r => r.id === recipeId)
|
|
436
|
+
if (!recipe) return { text: `配方 ${recipeId} 不存在。`, isError: true }
|
|
437
|
+
const repo = getAgentNodeBindingRepo()
|
|
438
|
+
for (const p of list) {
|
|
439
|
+
const node = getDcwController().byId(p.nodeId)
|
|
440
|
+
if (!node) return { text: `节点 ${p.nodeId} 已删除,不能纳入试验。`, isError: true }
|
|
441
|
+
if (node.lineId !== recipe.lineId) return { text: `节点「${node.name}」不在配方「${recipe.name}」所在产线,不可混入试验。`, isError: true }
|
|
442
|
+
if (!node.enabled) return { text: `节点「${node.name}」已停用,试验被拒。`, isError: true }
|
|
443
|
+
if (!repo.find(agentId, p.nodeId, 'dcw')) {
|
|
444
|
+
return { text: `无权试验节点「${node.name}」(仅可改自己绑定的数控节点;缺授权找 lead 用 team_grant_nodes 授予)。`, isError: true }
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
try {
|
|
448
|
+
const run = await getDcwController().applyRecipe(recipeId, { overrides: list, trial: true })
|
|
449
|
+
const okN = run.results.filter(r => r.ok).length
|
|
450
|
+
// 批次级留痕:试验动作入审计(逐参数写已有 write-audit;这里是"一次试验"粒度)
|
|
451
|
+
try {
|
|
452
|
+
const { recordOps } = await import('../../ops/ops')
|
|
453
|
+
recordOps({
|
|
454
|
+
actor: agentId, actorName: agentBadgeLabel(agentId), actorKind: 'agent',
|
|
455
|
+
action: 'recipe.trial', kind: 'recipe', targetKind: 'recipe', targetId: recipeId, recipeId, lineId: recipe.lineId,
|
|
456
|
+
summary: `配方试验整批下发(${okN}/${run.results.length} 成功,批次 ${run.id.slice(0, 8)}):${list.map(p => `${p.nodeId.slice(0, 8)}→${p.value}`).join(';')} | 假设:${hypothesis}`,
|
|
457
|
+
})
|
|
458
|
+
}
|
|
459
|
+
catch { /* 审计失败不影响试验结果 */ }
|
|
460
|
+
const changed = run.results.map((r) => {
|
|
461
|
+
const node = r.nodeId ? getDcwController().byId(r.nodeId) : undefined
|
|
462
|
+
const reason = r.ok ? '' : `(${String(r.message).slice(0, 60)})`
|
|
463
|
+
return `${node?.name ?? r.templateRef}→${r.value}${node?.unit ?? ''}${r.ok ? '' : ` 被拒${reason}`}`
|
|
464
|
+
}).join(';')
|
|
465
|
+
return {
|
|
466
|
+
text: `试验已整批下发(${okN}/${run.results.length} 成功,批次 ${run.id.slice(0, 8)}):${changed}。假设:${hypothesis}。注意:本次试验**未写入配方版本** —— 等待工艺惯性后 daq_query 复测判读:有进步/达标 → recipe_update 把候选值固化进配方(同 id 版本+1);无进步/劣化 → recipe_rollback(recipe_id, dispatch=true, reason=…) 统一回退(定义回退+PLC 整批恢复)。`,
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
catch (err) {
|
|
470
|
+
return { text: `试验下发失败:${err instanceof Error ? err.message : String(err)}`, isError: true }
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/** 工具:recipe_apply —— 把配方当前已固化参数整批下发到产线(改配方(recipe_update)之后用)。
|
|
475
|
+
* 与 recipe_trial 的区别:apply 下发的是**已固化版本**(无候选覆盖),用于"改配方 → 配方下发"链路的正式下发。 */
|
|
476
|
+
export async function toolRecipeApply(agentId: string, args: {
|
|
477
|
+
recipe_id?: string
|
|
478
|
+
reason?: string
|
|
479
|
+
}): Promise<{ text: string, isError?: boolean }> {
|
|
480
|
+
const recipeId = String(args.recipe_id ?? '').trim()
|
|
481
|
+
if (!recipeId) return { text: 'recipe_id 必填(line_context 可看到当前配方 id)。', isError: true }
|
|
482
|
+
const recipe = getDcwController().listRecipes().find(r => r.id === recipeId)
|
|
483
|
+
if (!recipe) return { text: `配方 ${recipeId} 不存在。`, isError: true }
|
|
484
|
+
const scope = agentOpsScope(agentId)
|
|
485
|
+
if (!scope || !recipe.lineId || !scope.lineIds.includes(recipe.lineId)) {
|
|
486
|
+
return { text: `无权下发配方 ${recipeId}(该配方不在你负责的产线上)。`, isError: true }
|
|
487
|
+
}
|
|
488
|
+
const boundInRecipe = getAgentNodeBindingRepo().byAgent(agentId)
|
|
489
|
+
.some(b => b.kind === 'dcw' && recipe.params.some(p => p.nodeId === b.nodeId))
|
|
490
|
+
if (!boundInRecipe) {
|
|
491
|
+
return { text: `无权下发配方 ${recipeId}(需持有该配方至少一个数控节点的授权;找 lead 用 team_grant_nodes 授予)。`, isError: true }
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
const run = await getDcwController().applyRecipe(recipeId)
|
|
495
|
+
const okN = run.results.filter(r => r.ok).length
|
|
496
|
+
try {
|
|
497
|
+
const { recordOps } = await import('../../ops/ops')
|
|
498
|
+
recordOps({
|
|
499
|
+
actor: agentId, actorName: agentBadgeLabel(agentId), actorKind: 'agent',
|
|
500
|
+
action: 'recipe.apply', kind: 'recipe', targetKind: 'recipe', targetId: recipeId, recipeId, lineId: recipe.lineId,
|
|
501
|
+
summary: `Agent 整批下发配方 v${recipe.version ?? 1}(${okN}/${run.results.length} 参数成功,批次 ${run.id.slice(0, 8)})${args.reason ? ` | 原因:${String(args.reason).trim()}` : ''}`,
|
|
502
|
+
})
|
|
503
|
+
}
|
|
504
|
+
catch { /* 审计失败不影响下发结果 */ }
|
|
505
|
+
return {
|
|
506
|
+
text: `配方「${recipe.name}」v${recipe.version ?? 1} 已整批下发(${okN}/${run.results.length} 参数成功,批次 ${run.id.slice(0, 8)})。用 daq_query 复测确认工艺响应。`,
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
catch (err) {
|
|
510
|
+
return { text: `配方下发失败:${err instanceof Error ? err.message : String(err)}`, isError: true }
|
|
511
|
+
}
|
|
512
|
+
}
|
|
@@ -38,6 +38,10 @@ export interface AgentNodeBinding {
|
|
|
38
38
|
kind: AgentNodeBindingKind
|
|
39
39
|
mode: AgentNodeBindingMode
|
|
40
40
|
tuning?: AgentNodeBindingTuning
|
|
41
|
+
/** 委派来源:lead 经 team_grant_nodes / dispatch_task(grant_node_ids) 授予时 = lead 成员实例 id */
|
|
42
|
+
grantedByAgentId?: string
|
|
43
|
+
/** 委派时间(ISO;仅委派产生的绑定携带) */
|
|
44
|
+
grantedAt?: string
|
|
41
45
|
createdAt: string
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -83,7 +87,7 @@ export class AgentNodeBindingRepo {
|
|
|
83
87
|
return this.list.find(b => b.agentId === agentId && b.nodeId === nodeId && b.kind === kind)
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
bind(agentId: string, nodeId: string, kind: AgentNodeBindingKind, mode: AgentNodeBindingMode, tuning?: AgentNodeBindingTuning): AgentNodeBinding {
|
|
90
|
+
bind(agentId: string, nodeId: string, kind: AgentNodeBindingKind, mode: AgentNodeBindingMode, tuning?: AgentNodeBindingTuning, provenance?: { grantedByAgentId?: string }): AgentNodeBinding {
|
|
87
91
|
if (!agentId) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'agentId 必填')
|
|
88
92
|
if (!nodeId) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'nodeId 必填')
|
|
89
93
|
if (kind !== 'dcw' && kind !== 'daq') throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `未知节点类型: ${kind}`)
|
|
@@ -92,6 +96,10 @@ export class AgentNodeBindingRepo {
|
|
|
92
96
|
if (prev) {
|
|
93
97
|
prev.mode = mode
|
|
94
98
|
if (tuning !== undefined) prev.tuning = normalizeTuning(tuning)
|
|
99
|
+
if (provenance?.grantedByAgentId) {
|
|
100
|
+
prev.grantedByAgentId = provenance.grantedByAgentId
|
|
101
|
+
prev.grantedAt = new Date().toISOString()
|
|
102
|
+
}
|
|
95
103
|
this.flush()
|
|
96
104
|
return prev
|
|
97
105
|
}
|
|
@@ -102,6 +110,7 @@ export class AgentNodeBindingRepo {
|
|
|
102
110
|
kind,
|
|
103
111
|
mode,
|
|
104
112
|
...(tuning ? { tuning: normalizeTuning(tuning) } : {}),
|
|
113
|
+
...(provenance?.grantedByAgentId ? { grantedByAgentId: provenance.grantedByAgentId, grantedAt: new Date().toISOString() } : {}),
|
|
105
114
|
createdAt: new Date().toISOString(),
|
|
106
115
|
}
|
|
107
116
|
this.list.push(binding)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* node-delegation —— lead → worker 节点权限委派(核心校验面,宿主工具与 REST 共用)。
|
|
3
|
+
*
|
|
4
|
+
* 语义:lead 把**自己已绑定**的 DAQ/DCW 节点授权给同 Channel 的 worker:
|
|
5
|
+
* - 节点必须是 leader 本人已有绑定的节点(权限不可超越授予者,hard rule);
|
|
6
|
+
* - 目标必须是同 Channel 的启用 worker(不能授给 lead 自己/其他频道成员);
|
|
7
|
+
* - 绑定逐 (nodeId, kind) 复制 leader 的 kind/tuning;mode 缺省随 leader,
|
|
8
|
+
* 显式传 mode 可覆盖(auto↔manual 均允许 —— mode 只决定是否走 HITL,不放大节点面);
|
|
9
|
+
* - 委派产生的绑定带 grantedByAgentId/grantedAt 溯源;撤销时 leader 只能撤
|
|
10
|
+
* 「自己授予的」或「自己也持有的」绑定。
|
|
11
|
+
* 校验全部 fail-closed:任何节点不满足 → 整单拒绝并列出明细,不做部分授予。
|
|
12
|
+
*/
|
|
13
|
+
import { AppError, ErrorCodes } from '../../../utils/errors'
|
|
14
|
+
import { getAgentNodeBindingRepo, type AgentNodeBinding, type AgentNodeBindingMode } from './node-bindings.repo'
|
|
15
|
+
|
|
16
|
+
export interface DelegationMember {
|
|
17
|
+
id: string
|
|
18
|
+
role: 'lead' | 'worker'
|
|
19
|
+
enabled?: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DelegationGrantInput {
|
|
23
|
+
leaderAgentId: string
|
|
24
|
+
channelId: string
|
|
25
|
+
targetAgentId: string
|
|
26
|
+
nodeIds: string[]
|
|
27
|
+
members: DelegationMember[]
|
|
28
|
+
mode?: AgentNodeBindingMode
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface DelegationPlanItem {
|
|
32
|
+
nodeId: string
|
|
33
|
+
kind: 'dcw' | 'daq'
|
|
34
|
+
mode: AgentNodeBindingMode
|
|
35
|
+
tuning?: AgentNodeBinding['tuning']
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface DelegationPlan {
|
|
39
|
+
targetAgentId: string
|
|
40
|
+
grants: DelegationPlanItem[]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 前置校验 + 逐节点计划(fail-closed;不落库 —— 落库由调用方按计划执行) */
|
|
44
|
+
export function planDelegation(input: DelegationGrantInput): DelegationPlan {
|
|
45
|
+
const leaderAgentId = String(input.leaderAgentId ?? '')
|
|
46
|
+
const targetAgentId = String(input.targetAgentId ?? '')
|
|
47
|
+
const nodeIds = (Array.isArray(input.nodeIds) ? input.nodeIds : []).map(x => String(x ?? '').trim()).filter(Boolean)
|
|
48
|
+
if (!leaderAgentId || !targetAgentId) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'leaderAgentId 与 targetAgentId 必填')
|
|
49
|
+
if (!nodeIds.length) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'node_ids 必填(要授予的节点 id 列表)')
|
|
50
|
+
|
|
51
|
+
const members = Array.isArray(input.members) ? input.members : []
|
|
52
|
+
const leader = members.find(m => m.id === leaderAgentId)
|
|
53
|
+
if (!leader || leader.role !== 'lead') {
|
|
54
|
+
throw new AppError(403, 'DELEGATION_NOT_LEAD', '只有频道 lead 可以分发节点权限')
|
|
55
|
+
}
|
|
56
|
+
const target = members.find(m => m.id === targetAgentId)
|
|
57
|
+
if (!target) {
|
|
58
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `目标成员不在本频道: ${targetAgentId}(需传频道成员实例 id,可经 GET /api/workshop/channels/:id/agents 获取)`)
|
|
59
|
+
}
|
|
60
|
+
if (target.id === leaderAgentId) {
|
|
61
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, '不能把节点权限授予 lead 自己(绑定面在 lead 名下已存在)')
|
|
62
|
+
}
|
|
63
|
+
if (target.role !== 'worker') {
|
|
64
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, '只能向 worker 分发节点权限')
|
|
65
|
+
}
|
|
66
|
+
if (target.enabled === 0) {
|
|
67
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `目标成员已被停用: ${targetAgentId}`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const repo = getAgentNodeBindingRepo()
|
|
71
|
+
const leaderBindings = repo.byAgent(leaderAgentId)
|
|
72
|
+
const missing: string[] = []
|
|
73
|
+
const grants: DelegationPlanItem[] = []
|
|
74
|
+
const seen = new Set<string>()
|
|
75
|
+
for (const nodeId of nodeIds) {
|
|
76
|
+
if (seen.has(nodeId)) continue
|
|
77
|
+
seen.add(nodeId)
|
|
78
|
+
const held = leaderBindings.filter(b => b.nodeId === nodeId)
|
|
79
|
+
if (!held.length) {
|
|
80
|
+
missing.push(nodeId)
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
for (const h of held) {
|
|
84
|
+
grants.push({
|
|
85
|
+
nodeId,
|
|
86
|
+
kind: h.kind,
|
|
87
|
+
mode: input.mode ?? h.mode,
|
|
88
|
+
tuning: h.tuning ? { ...h.tuning } : undefined,
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (missing.length) {
|
|
93
|
+
throw new AppError(403, 'DELEGATION_NOT_OWNED', `以下节点不在 lead 的绑定面内,拒绝授予(权限不可超越授予者):${missing.join('、')}`)
|
|
94
|
+
}
|
|
95
|
+
return { targetAgentId, grants }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 执行授予:按计划逐条落库(已存在的绑定更新 mode/溯源,不重复建行) */
|
|
99
|
+
export function applyDelegation(plan: DelegationPlan, leaderAgentId: string): AgentNodeBinding[] {
|
|
100
|
+
const repo = getAgentNodeBindingRepo()
|
|
101
|
+
return plan.grants.map((g) => {
|
|
102
|
+
const binding = repo.bind(plan.targetAgentId, g.nodeId, g.kind, g.mode, g.tuning, { grantedByAgentId: leaderAgentId })
|
|
103
|
+
return binding
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface DelegationRevokeInput {
|
|
108
|
+
leaderAgentId: string
|
|
109
|
+
targetAgentId: string
|
|
110
|
+
nodeIds: string[]
|
|
111
|
+
members: DelegationMember[]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** 撤销授予:可撤「自己授予的」或「自己也持有的」绑定;两者都不是 → 拒绝该节点 */
|
|
115
|
+
export function revokeDelegation(input: DelegationRevokeInput): Array<{ nodeId: string, kind: 'dcw' | 'daq', revoked: boolean }> {
|
|
116
|
+
const leaderAgentId = String(input.leaderAgentId ?? '')
|
|
117
|
+
const targetAgentId = String(input.targetAgentId ?? '')
|
|
118
|
+
const nodeIds = (Array.isArray(input.nodeIds) ? input.nodeIds : []).map(x => String(x ?? '').trim()).filter(Boolean)
|
|
119
|
+
if (!leaderAgentId || !targetAgentId || !nodeIds.length) {
|
|
120
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'leaderAgentId / targetAgentId / node_ids 必填')
|
|
121
|
+
}
|
|
122
|
+
const members = Array.isArray(input.members) ? input.members : []
|
|
123
|
+
const leader = members.find(m => m.id === leaderAgentId)
|
|
124
|
+
if (!leader || leader.role !== 'lead') {
|
|
125
|
+
throw new AppError(403, 'DELEGATION_NOT_LEAD', '只有频道 lead 可以撤销节点权限')
|
|
126
|
+
}
|
|
127
|
+
if (!members.some(m => m.id === targetAgentId)) {
|
|
128
|
+
throw new AppError(404, ErrorCodes.NOT_FOUND, `目标成员不在本频道: ${targetAgentId}`)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const repo = getAgentNodeBindingRepo()
|
|
132
|
+
const leaderNodes = new Set(repo.byAgent(leaderAgentId).map(b => b.nodeId))
|
|
133
|
+
const out: Array<{ nodeId: string, kind: 'dcw' | 'daq', revoked: boolean }> = []
|
|
134
|
+
for (const nodeId of nodeIds) {
|
|
135
|
+
const workerBindings = repo.byAgent(targetAgentId).filter(b => b.nodeId === nodeId)
|
|
136
|
+
if (!workerBindings.length) {
|
|
137
|
+
for (const kind of ['dcw', 'daq'] as const) out.push({ nodeId, kind, revoked: false })
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
for (const b of workerBindings) {
|
|
141
|
+
const allowed = b.grantedByAgentId === leaderAgentId || leaderNodes.has(nodeId)
|
|
142
|
+
if (!allowed) {
|
|
143
|
+
out.push({ nodeId, kind: b.kind, revoked: false })
|
|
144
|
+
continue
|
|
145
|
+
}
|
|
146
|
+
out.push({ nodeId, kind: b.kind, revoked: repo.unbind(b.id) })
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return out
|
|
150
|
+
}
|
|
@@ -16,6 +16,8 @@ export const LEAD_ONLY_TOOL_NAMES = new Set([
|
|
|
16
16
|
'update_team_agent',
|
|
17
17
|
'remove_team_agent',
|
|
18
18
|
'aml_model_promote',
|
|
19
|
+
'team_grant_nodes',
|
|
20
|
+
'team_revoke_nodes',
|
|
19
21
|
])
|
|
20
22
|
|
|
21
23
|
/** Hybrid Twin 的直接写入工具:权限面(permission-scope)与目录注入面(host-tool-bridge/catalog)fail-closed 同源于本集合;dispatch 分发层的同款守卫为并行在飞改动,待其收敛后接入(勿在此重复第三份清单)。 */
|
|
@@ -25,4 +27,6 @@ export const HYBRID_TWIN_DIRECT_WRITE_TOOL_NAMES = new Set([
|
|
|
25
27
|
'dcw_rollback',
|
|
26
28
|
'recipe_update',
|
|
27
29
|
'recipe_rollback',
|
|
30
|
+
'recipe_trial',
|
|
31
|
+
'recipe_apply',
|
|
28
32
|
])
|
|
@@ -194,7 +194,9 @@ export async function buildDataset(spec: AmlDatasetSpec, by: { id: string, kind:
|
|
|
194
194
|
continue
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
// 公共网格:[max(t0), min(t1)];逐节点最近邻对齐,网格点缺失计 NaN
|
|
197
|
+
// 公共网格:[max(t0), min(t1)];逐节点最近邻对齐,网格点缺失计 NaN。
|
|
198
|
+
// 全节点查空(如该 run 采样缺失/时序库丢数)时 g0/g1 保持 ±Infinity,
|
|
199
|
+
// 必须按丢弃处理 —— 否则 steps=Infinity 会把网格循环推到 RangeError(500)。
|
|
198
200
|
let g0 = -Infinity
|
|
199
201
|
let g1 = Infinity
|
|
200
202
|
for (const n of order) {
|
|
@@ -206,7 +208,7 @@ export async function buildDataset(spec: AmlDatasetSpec, by: { id: string, kind:
|
|
|
206
208
|
g0 = Math.max(g0, first.at)
|
|
207
209
|
g1 = Math.min(g1, last.at)
|
|
208
210
|
}
|
|
209
|
-
const steps = g1 > g0 ? Math.floor((g1 - g0) / beat) + 1 : 0
|
|
211
|
+
const steps = Number.isFinite(g0) && Number.isFinite(g1) && g1 > g0 ? Math.floor((g1 - g0) / beat) + 1 : 0
|
|
210
212
|
if (steps < spec.window.historySteps + spec.window.horizonSteps + 2) {
|
|
211
213
|
runsDropped.push({ runId: run.id, reason: `有效网格 ${steps} 步不足一个窗口` })
|
|
212
214
|
continue
|
|
@@ -96,5 +96,6 @@ export function handleProtocolLine(run: RunningJob, rawLine: string): void {
|
|
|
96
96
|
}
|
|
97
97
|
else if (evt.type === 'error' && evt.message) {
|
|
98
98
|
pushLog(run, `[error] ${evt.message}`)
|
|
99
|
+
run.lastProtocolError = String(evt.message).slice(0, 300) // 结题失败原因优先用它(见 start-job 评估段)
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -140,8 +140,11 @@ export async function startJob(row: AmlJobRow): Promise<void> {
|
|
|
140
140
|
const exit2 = await runPython(run, vpy, [evalScript, '--job', join(jobDir, 'job.json')], jobDir)
|
|
141
141
|
if (run.killed) return
|
|
142
142
|
if (exit2.code !== 0) {
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
// 失败原因优先取评估器的 ##AML error 协议消息(如「test 切分为空…」,人读可操作);
|
|
144
|
+
// stderr 尾兜底 —— 评估器把错误走 stdout 协议行时 errTail 常为空,只给 "exit" 无从排查。
|
|
145
|
+
const reason = run.lastProtocolError || lastErrLine(exit2.errTail)
|
|
146
|
+
rt.repo.job.fail(row.id, 'failed', `评估失败:${reason}(永久错误不重试)`, new Date().toISOString())
|
|
147
|
+
experimentFail(run, `评估失败:${reason}`)
|
|
145
148
|
finishRun(run)
|
|
146
149
|
return
|
|
147
150
|
}
|
|
@@ -11,7 +11,7 @@ import type { DatabaseSync } from 'node:sqlite'
|
|
|
11
11
|
import type { ChannelRow } from './database'
|
|
12
12
|
|
|
13
13
|
/** 查询列(蛇形列名 → 驼峰行字段) */
|
|
14
|
-
const COLS = 'id, name, description, scenario_prompt AS scenarioPrompt, llm_json AS llmJson, lead_agent_id AS leadAgentId, workspace, enabled, owner_user_id AS ownerUserId, visibility, join_policy AS joinPolicy, approval_policy AS approvalPolicy, chat_enabled AS chatEnabled, version, created_at AS createdAt, updated_at AS updatedAt'
|
|
14
|
+
const COLS = 'id, name, description, scenario_prompt AS scenarioPrompt, llm_json AS llmJson, lead_agent_id AS leadAgentId, workspace, enabled, owner_user_id AS ownerUserId, visibility, join_policy AS joinPolicy, approval_policy AS approvalPolicy, chat_enabled AS chatEnabled, version, line_id AS lineId, created_at AS createdAt, updated_at AS updatedAt'
|
|
15
15
|
|
|
16
16
|
export interface ChannelCreateInput {
|
|
17
17
|
name: string
|
|
@@ -99,6 +99,7 @@ export function createChannelRepo(db: DatabaseSync) {
|
|
|
99
99
|
approvalPolicy: input.approvalPolicy ?? 'owner_only',
|
|
100
100
|
chatEnabled: input.chatEnabled ?? 0,
|
|
101
101
|
version: 1,
|
|
102
|
+
lineId: '',
|
|
102
103
|
createdAt: now,
|
|
103
104
|
updatedAt: now,
|
|
104
105
|
}
|
|
@@ -189,5 +190,14 @@ export function createChannelRepo(db: DatabaseSync) {
|
|
|
189
190
|
remove(id: string): void {
|
|
190
191
|
removeStmt.run(id)
|
|
191
192
|
},
|
|
193
|
+
|
|
194
|
+
/** v18:绑定/解绑产线(lineId=''=解绑)。只读扩权面:成员可读该线日志/配方/历史/状态;写仍走节点授权。 */
|
|
195
|
+
setLine(id: string, lineId: string): ChannelRow | undefined {
|
|
196
|
+
const current = selectById.get(id) as unknown as ChannelRow | undefined
|
|
197
|
+
if (!current) return undefined
|
|
198
|
+
db.prepare('UPDATE channels SET line_id = ?, updated_at = ? WHERE id = ?')
|
|
199
|
+
.run(lineId, new Date().toISOString(), id)
|
|
200
|
+
return { ...current, lineId, updatedAt: new Date().toISOString() }
|
|
201
|
+
},
|
|
192
202
|
}
|
|
193
203
|
}
|
|
@@ -10,6 +10,8 @@ export function migrateGroupChatV17(db: DatabaseSync): void {
|
|
|
10
10
|
migrateAddColumn(db, 'channels', 'approval_policy', 'TEXT NOT NULL DEFAULT \'owner_only\'')
|
|
11
11
|
migrateAddColumn(db, 'channels', 'chat_enabled', 'INTEGER NOT NULL DEFAULT 0')
|
|
12
12
|
migrateAddColumn(db, 'channels', 'version', 'INTEGER NOT NULL DEFAULT 1')
|
|
13
|
+
// v18:Channel 绑定产线(空串=未绑定;只读扩权面,见 ops-tools agentOpsScope)
|
|
14
|
+
migrateAddColumn(db, 'channels', 'line_id', 'TEXT NOT NULL DEFAULT \'\'')
|
|
13
15
|
// 规范化非法值(历史手改/测试数据):未知取值一律回落到最保守档,不放宽权限
|
|
14
16
|
db.exec(`UPDATE channels SET visibility = 'private' WHERE visibility NOT IN ('private', 'public')`)
|
|
15
17
|
db.exec(`UPDATE channels SET join_policy = 'owner_approve' WHERE join_policy NOT IN ('open', 'owner_approve')`)
|