agentworkshop 0.7.50 → 0.7.52
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 +2028 -1955
- package/.output/.AgentWorkShop/prompts/host-tools.json +2028 -1955
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{CdIsmU5a2.js → 4wrEQ3np2.js} +1 -1
- package/.output/public/_nuxt/{asmJ99nX2.js → B8zP7kaj2.js} +1 -1
- package/.output/public/_nuxt/{D89BUtx6.js → B9cGf8mg.js} +1 -1
- package/.output/public/_nuxt/{CP0I2l-6.js → BVzw5a_0.js} +1 -1
- package/.output/public/_nuxt/{CFQSjB1h.js → B_opxrHJ.js} +1 -1
- package/.output/public/_nuxt/{BGAaKBeo2.js → BiUhxH3t2.js} +1 -1
- package/.output/public/_nuxt/{B7jlMWsz.js → C00Rd6Cg.js} +1 -1
- package/.output/public/_nuxt/{BOmDHp5L.js → CGQvF-Gg.js} +3 -3
- package/.output/public/_nuxt/CTvh8v4T.js +1 -0
- package/.output/public/_nuxt/{B9QzrmgE.js → Cbeifv55.js} +1 -1
- package/.output/public/_nuxt/{BWU1pvLL.js → CcGuXiOa.js} +1 -1
- package/.output/public/_nuxt/{zh-S_7rN2.js → CkPxL4UX2.js} +1 -1
- package/.output/public/_nuxt/{DzfVS8N72.js → D_Ce9Fon2.js} +1 -1
- package/.output/public/_nuxt/{DClNt1uS.js → Da90gveK.js} +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/c64014ca-3595-4b7a-a5ca-055687c83ba2.json +1 -0
- package/.output/public/_nuxt/channel-templates.DkNZg-lF.css +1 -0
- package/.output/public/_nuxt/{JAM4aNC_.js → evt5VGDh.js} +1 -1
- package/.output/public/_nuxt/{DhFv8S2Z.js → mNnuUoSy.js} +1 -1
- package/.output/public/_nuxt/{CU-mhG0-.js → mgWHSRc8.js} +1 -1
- package/.output/public/_nuxt/{jRTz0hjN2.js → qPsch_ny2.js} +1 -1
- package/.output/public/_nuxt/{lWYQbIR3.js → ty5W5QwO.js} +1 -1
- package/.output/public/_nuxt/{DMYYS5sK.js → xQX5r6tW.js} +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 +1123 -881
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
- package/.output/server/chunks/build/TownView-fP9BiALv.mjs +1 -1
- package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs → _wsId_-C4L9fVHC.mjs} +2 -2
- package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs.map → _wsId_-C4L9fVHC.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-CDLcboCv.mjs → agents-ydYu-Ol9.mjs} +6 -6
- package/.output/server/chunks/build/{agents-CDLcboCv.mjs.map → agents-ydYu-Ol9.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-DjEsj0_v.mjs → channel-templates-DP1ndA5K.mjs} +114 -25
- package/.output/server/chunks/build/channel-templates-DP1ndA5K.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/{pages-rZKH72eC.mjs → pages-BzmrmLL_.mjs} +3 -3
- package/.output/server/chunks/build/{pages-rZKH72eC.mjs.map → pages-BzmrmLL_.mjs.map} +1 -1
- package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs → schedules-BYR-lA1k.mjs} +2 -2
- package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs.map → schedules-BYR-lA1k.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-CAJWvul5.mjs → settings-UyZ78w2e.mjs} +2 -2
- package/.output/server/chunks/build/{settings-CAJWvul5.mjs.map → settings-UyZ78w2e.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-DBBvIToa.mjs → teams-D-Y5mzU7.mjs} +8 -8
- package/.output/server/chunks/build/{teams-DBBvIToa.mjs.map → teams-D-Y5mzU7.mjs.map} +1 -1
- package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
- package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs → useAgentHarnessOptions-CRyQYYY0.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs.map → useAgentHarnessOptions-CRyQYYY0.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs → useAgentTemplateActions-CaRsOBmB.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs.map → useAgentTemplateActions-CaRsOBmB.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs → useAgentTemplateForm-ChiIuPYr.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs.map → useAgentTemplateForm-ChiIuPYr.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs → useAgentTemplatesCatalog-Bf5hk6Jf.mjs} +2 -2
- package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs.map → useAgentTemplatesCatalog-Bf5hk6Jf.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-CNOY4Bi3.mjs} +2 -2
- package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs.map → useDashboardData-CNOY4Bi3.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-C51ciLb0.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs.map → useTeamActions-C51ciLb0.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs → useTeamAddMemberDialog-DthpCMP8.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs.map → useTeamAddMemberDialog-DthpCMP8.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs → useTeamCreateDialog-Dc2KTwyg.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs.map → useTeamCreateDialog-Dc2KTwyg.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs → useTeamDeployDialog-CXpvPnJD.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs.map → useTeamDeployDialog-CXpvPnJD.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs → useTeamPluginDialog-DTs-7SSm.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs.map → useTeamPluginDialog-DTs-7SSm.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs → useTeamsCatalog-CcpetYyW.mjs} +2 -2
- package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs.map → useTeamsCatalog-CcpetYyW.mjs.map} +1 -1
- package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs → useWorkshopApi-CO3ophqt.mjs} +5 -2
- package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs.map → useWorkshopApi-CO3ophqt.mjs.map} +1 -1
- package/.output/server/chunks/routes/api/mcp/workshop.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/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/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/assets/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +5 -4
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +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/chat/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/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.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/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 +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/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/rollback-good.post.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/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/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.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index2.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/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/teams/_id/deploy.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/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 +29 -19
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +829 -829
- package/README.md +839 -839
- package/app/composables/workshop/useWorkshopApi.ts +4 -2
- package/app/pages/workshop/channel-templates.vue +43 -4
- package/config.yml +1 -1
- package/docs/cli.en.md +447 -447
- package/docs/cli.md +412 -412
- package/docs/mcp.en.md +27 -0
- package/docs/mcp.md +108 -0
- 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/ctpl.json +37 -32
- package/i18n/locales/en.ts +5 -0
- package/i18n/locales/zh-CN.ts +5 -0
- package/mcp/aw-mcp-server.mjs +796 -0
- package/mcp/discovery.mjs +227 -0
- package/package.json +4 -1
- package/scripts/_audit/kb-team-mock-e2e.mjs +146 -0
- package/scripts/_audit/kb-team-omp-e2e.mjs +229 -0
- 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 +2 -1
- package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +6 -1
- 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/node-bindings.repo.ts +10 -1
- package/server/services/workshop/agents/node-delegation.ts +150 -0
- package/server/services/workshop/agents/tool-classes.ts +2 -0
- package/server/services/workshop/db/database/seed.ts +20 -0
- package/server/services/workshop/runtime/manager/channel-templates.ts +26 -2
- package/server/services/workshop/runtime/manager/types.ts +2 -0
- package/.output/public/_nuxt/8FXd9As6.js +0 -1
- package/.output/public/_nuxt/builds/meta/08ba670b-7512-426b-a0ae-b10cbeb1c985.json +0 -1
- package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +0 -1
- package/.output/server/chunks/build/channel-templates-DjEsj0_v.mjs.map +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/agent-tools/bindings/grant —— lead 把自己绑定的节点授权给同频道 worker。
|
|
3
|
+
* body: { channelId, agentId(worker 成员实例), nodeIds: string[], mode?: 'auto'|'manual' }
|
|
4
|
+
* 硬约束:nodeIds 每一个都必须在频道 lead 的绑定面内(权限不可超越授予者);全成全败。
|
|
5
|
+
* 产线权限随绑定继承(lead 绑定建立时已校验);绑定带 grantedByAgentId/grantedAt 溯源。
|
|
6
|
+
* 鉴权:channel 归属者(遗留公共 channel 需 admin)。
|
|
7
|
+
*/
|
|
8
|
+
import { readBody } from 'h3'
|
|
9
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
10
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
11
|
+
import { getWorkshopManager } from '@/server/plugins/workshop'
|
|
12
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
13
|
+
import { applyDelegation, planDelegation } from '@/server/services/workshop/agents/node-delegation'
|
|
14
|
+
import type { DelegationMember } from '@/server/services/workshop/agents/node-delegation'
|
|
15
|
+
|
|
16
|
+
export default defineApiHandler(async (event) => {
|
|
17
|
+
const user = resolveUser(event)
|
|
18
|
+
const body = await readBody<{ channelId?: string, agentId?: string, nodeIds?: string[], mode?: 'auto' | 'manual' }>(event) ?? {}
|
|
19
|
+
const channelId = String(body.channelId ?? '')
|
|
20
|
+
const agentId = String(body.agentId ?? '')
|
|
21
|
+
const nodeIds = Array.isArray(body.nodeIds) ? body.nodeIds.map(x => String(x ?? '').trim()).filter(Boolean) : []
|
|
22
|
+
if (!channelId || !agentId || !nodeIds.length) {
|
|
23
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'channelId / agentId / nodeIds 必填')
|
|
24
|
+
}
|
|
25
|
+
const manager = getWorkshopManager()
|
|
26
|
+
const channel = manager.getChannelForUser(channelId, user.id)
|
|
27
|
+
if (channel?.ownerUserId === null) {
|
|
28
|
+
const { requireAdmin } = await import('@/server/api/workshop/caller')
|
|
29
|
+
requireAdmin(event)
|
|
30
|
+
}
|
|
31
|
+
const row = (await manager.listChannels()).find(c => c.id === channelId)
|
|
32
|
+
if (!row?.leadAgentId) throw new AppError(404, ErrorCodes.NOT_FOUND, `频道不存在或没有 lead: ${channelId}`)
|
|
33
|
+
|
|
34
|
+
const members = await manager.listChannelAgents(channelId) as unknown as DelegationMember[]
|
|
35
|
+
const plan = planDelegation({
|
|
36
|
+
leaderAgentId: row.leadAgentId,
|
|
37
|
+
channelId,
|
|
38
|
+
targetAgentId: agentId,
|
|
39
|
+
nodeIds,
|
|
40
|
+
members,
|
|
41
|
+
mode: body.mode,
|
|
42
|
+
})
|
|
43
|
+
const bindings = applyDelegation(plan, row.leadAgentId)
|
|
44
|
+
return { granted: bindings }
|
|
45
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* POST /api/workshop/agent-tools/bindings/revoke —— lead 收回授予给 worker 的节点授权。
|
|
3
|
+
* body: { channelId, agentId(worker 成员实例), nodeIds: string[] }
|
|
4
|
+
* 可收回:lead 自己授予的(grantedByAgentId=lead)或 lead 也持有的节点绑定;
|
|
5
|
+
* 其余绑定原样保留并在结果中标注 revoked=false。
|
|
6
|
+
* 鉴权:channel 归属者(遗留公共 channel 需 admin)。
|
|
7
|
+
*/
|
|
8
|
+
import { readBody } from 'h3'
|
|
9
|
+
import { resolveUser } from '@/server/api/workshop/caller'
|
|
10
|
+
import { defineApiHandler } from '@/server/utils/response'
|
|
11
|
+
import { getWorkshopManager } from '@/server/plugins/workshop'
|
|
12
|
+
import { AppError, ErrorCodes } from '@/server/utils/errors'
|
|
13
|
+
import { revokeDelegation } from '@/server/services/workshop/agents/node-delegation'
|
|
14
|
+
import type { DelegationMember } from '@/server/services/workshop/agents/node-delegation'
|
|
15
|
+
|
|
16
|
+
export default defineApiHandler(async (event) => {
|
|
17
|
+
const user = resolveUser(event)
|
|
18
|
+
const body = await readBody<{ channelId?: string, agentId?: string, nodeIds?: string[] }>(event) ?? {}
|
|
19
|
+
const channelId = String(body.channelId ?? '')
|
|
20
|
+
const agentId = String(body.agentId ?? '')
|
|
21
|
+
const nodeIds = Array.isArray(body.nodeIds) ? body.nodeIds.map(x => String(x ?? '').trim()).filter(Boolean) : []
|
|
22
|
+
if (!channelId || !agentId || !nodeIds.length) {
|
|
23
|
+
throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'channelId / agentId / nodeIds 必填')
|
|
24
|
+
}
|
|
25
|
+
const manager = getWorkshopManager()
|
|
26
|
+
const channel = manager.getChannelForUser(channelId, user.id)
|
|
27
|
+
if (channel?.ownerUserId === null) {
|
|
28
|
+
const { requireAdmin } = await import('@/server/api/workshop/caller')
|
|
29
|
+
requireAdmin(event)
|
|
30
|
+
}
|
|
31
|
+
const row = (await manager.listChannels()).find(c => c.id === channelId)
|
|
32
|
+
if (!row?.leadAgentId) throw new AppError(404, ErrorCodes.NOT_FOUND, `频道不存在或没有 lead: ${channelId}`)
|
|
33
|
+
|
|
34
|
+
const members = await manager.listChannelAgents(channelId) as unknown as DelegationMember[]
|
|
35
|
+
const results = revokeDelegation({
|
|
36
|
+
leaderAgentId: row.leadAgentId,
|
|
37
|
+
targetAgentId: agentId,
|
|
38
|
+
nodeIds,
|
|
39
|
+
members,
|
|
40
|
+
})
|
|
41
|
+
return { results }
|
|
42
|
+
})
|
|
@@ -23,6 +23,7 @@ const instantiateSchema = z.object({
|
|
|
23
23
|
scenePackId: z.string().min(1).optional(),
|
|
24
24
|
optimizationMode: z.enum(['exploration', 'aml']).optional(),
|
|
25
25
|
boundModelId: z.string().min(1).optional(),
|
|
26
|
+
enableKnowledgeBase: z.boolean().optional(),
|
|
26
27
|
})
|
|
27
28
|
|
|
28
29
|
export default defineApiHandler(async (event) => {
|
|
@@ -30,7 +31,7 @@ export default defineApiHandler(async (event) => {
|
|
|
30
31
|
const user = resolveUser(event)
|
|
31
32
|
const body = await readValidatedBody(event, zValidator(instantiateSchema))
|
|
32
33
|
const manager = getWorkshopManager()
|
|
33
|
-
const result = await manager.instantiateChannelTemplate(templateId, user, body.name, { scene: body.scene, promptVariables: body.promptVariables, objective: body.objective, toolProfile: body.toolProfile, controlPolicy: body.controlPolicy, providerId: body.providerId, providerVersion: body.providerVersion, providerHash: body.providerHash, scenePackId: body.scenePackId, optimizationMode: body.optimizationMode, boundModelId: body.boundModelId })
|
|
34
|
+
const result = await manager.instantiateChannelTemplate(templateId, user, body.name, { scene: body.scene, promptVariables: body.promptVariables, objective: body.objective, toolProfile: body.toolProfile, controlPolicy: body.controlPolicy, providerId: body.providerId, providerVersion: body.providerVersion, providerHash: body.providerHash, scenePackId: body.scenePackId, optimizationMode: body.optimizationMode, boundModelId: body.boundModelId, enableKnowledgeBase: body.enableKnowledgeBase })
|
|
34
35
|
// 模板含 lead 时直接启动调度循环(可提交任务)
|
|
35
36
|
if (result.leadAgentId) {
|
|
36
37
|
ensureLeadSchedulerLoop(manager, result.channelId)
|
|
@@ -19,6 +19,7 @@ import type { HostToolBridgeContext, HostToolCall, HostToolResult } from './type
|
|
|
19
19
|
import { INDUSTRIAL_TOOL_NAMES, dispatchIndustrialTool } from './tools/industrial'
|
|
20
20
|
import { handleCompleteTask, handleReportProgress } from './tools/progress'
|
|
21
21
|
import { handleCancelTask, handleDispatchTask, handleGetMyTaskQueue, handleGetTaskDetails, handleListChannelTasks, handleReassignTask, handleRefuseTask, handleSubmitTask, handleUpdateTask } from './tools/tasks'
|
|
22
|
+
import { handleGrantNodes, handleRevokeNodes } from './tools/team-delegation'
|
|
22
23
|
import { handleBroadcastMessage, handleListOtherTeams, handlePollMessages, handleReadChannelMail, handleSearchOtherTeamsMemory, handleSendCrossChannelMessage, handleSendMessageToAgent } from './tools/messaging'
|
|
23
24
|
import { handleSaveMemory, handleSearchMemory } from './tools/memory'
|
|
24
25
|
import { handleCreateTeamAgent, handleGetQueueOverview, handleListTeamAgents, handleRemoveTeamAgent, handleUpdateTeamAgent } from './tools/team'
|
|
@@ -121,7 +122,11 @@ export async function dispatchHostTool(ctx: HostToolBridgeContext, req: HostTool
|
|
|
121
122
|
case 'submit_task':
|
|
122
123
|
return await handleSubmitTask(args, state, ws)
|
|
123
124
|
case 'dispatch_task':
|
|
124
|
-
return await handleDispatchTask(args, ws)
|
|
125
|
+
return await handleDispatchTask(args, ws, identity)
|
|
126
|
+
case 'team_grant_nodes':
|
|
127
|
+
return await handleGrantNodes(identity, args, ws)
|
|
128
|
+
case 'team_revoke_nodes':
|
|
129
|
+
return await handleRevokeNodes(identity, args, ws)
|
|
125
130
|
case 'send_message_to_agent':
|
|
126
131
|
return await handleSendMessageToAgent(args, state, ws)
|
|
127
132
|
case 'send_cross_channel_message':
|
|
@@ -23,12 +23,25 @@ export async function handleSubmitTask(args: Record<string, unknown>, state: Hos
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export async function handleDispatchTask(args: Record<string, unknown>, ws: AgentWorkspace): Promise<HostToolResult> {
|
|
26
|
+
export async function handleDispatchTask(args: Record<string, unknown>, ws: AgentWorkspace, identity?: HostToolBridgeContext['identity']): Promise<HostToolResult> {
|
|
27
27
|
const assigneeId = args.assignee_id as string
|
|
28
28
|
const title = args.title as string
|
|
29
29
|
const description = args.description as string | undefined
|
|
30
30
|
const parentTaskId = args.parent_task_id as string | undefined
|
|
31
31
|
const routeReason = args.route_reason as string | undefined
|
|
32
|
+
// 派发时随任务授予节点权限(lead 专属;grant_node_ids ⊆ lead 自身绑定面,fail-closed):
|
|
33
|
+
// 任一节点不满足则整单拒绝,任务不创建 —— 避免 worker 拿到任务却没有节点权限的半途态。
|
|
34
|
+
let grantNote = ''
|
|
35
|
+
const rawGrant = args.grant_node_ids ?? args.grantNodeIds
|
|
36
|
+
if (rawGrant != null && identity) {
|
|
37
|
+
const { grantNodesForDispatch } = await import('./team-delegation')
|
|
38
|
+
const grantNodeIds = (Array.isArray(rawGrant) ? rawGrant : String(rawGrant).split(',')).map(x => String(x ?? '').trim()).filter(Boolean)
|
|
39
|
+
if (!grantNodeIds.length) return { text: 'grant_node_ids 为空:要么不传,要么给出至少一个节点 id。', isError: true }
|
|
40
|
+
const grantMode = args.grant_mode === 'manual' || args.grant_mode === 'auto' ? (args.grant_mode as 'auto' | 'manual') : undefined
|
|
41
|
+
const grant = await grantNodesForDispatch(identity, assigneeId, grantNodeIds, grantMode, ws)
|
|
42
|
+
if (!grant.ok) return { text: `未派发:${grant.text}\n请先用 team_grant_nodes 确认你持有这些节点,或修正 node id 后重试。`, isError: true }
|
|
43
|
+
grantNote = `\n${grant.text}`
|
|
44
|
+
}
|
|
32
45
|
// 重复派发守卫(真实场景实测:lead 模型可能对同一目标重复派发,引发协调风暴):
|
|
33
46
|
// 同父任务下已存在同标题非终态子任务 → 不再创建,直接指路既有任务
|
|
34
47
|
const dup = await ws.listTasks()
|
|
@@ -42,7 +55,7 @@ export async function handleDispatchTask(args: Record<string, unknown>, ws: Agen
|
|
|
42
55
|
}
|
|
43
56
|
}
|
|
44
57
|
const task = await ws.dispatchTask({ assigneeId, title, description, parentTaskId, routeReason })
|
|
45
|
-
return { text: `子任务 ${task.id} 已创建并指派 → ${assigneeId}(父任务 ${parentTaskId ?? '无'},标题: ${title}${routeReason ? `,路由理由: ${routeReason}` : ''})` }
|
|
58
|
+
return { text: `子任务 ${task.id} 已创建并指派 → ${assigneeId}(父任务 ${parentTaskId ?? '无'},标题: ${title}${routeReason ? `,路由理由: ${routeReason}` : ''})${grantNote}` }
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
export async function handleRefuseTask(args: Record<string, unknown>, ws: AgentWorkspace): Promise<HostToolResult> {
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 团队节点权限委派工具(lead 专属):team_grant_nodes / team_revoke_nodes。
|
|
3
|
+
*
|
|
4
|
+
* lead 把**自己已绑定**的 DAQ/DCW 节点授权给同频道 worker(派发前、执行中均可),
|
|
5
|
+
* 授权面不可超越 lead 本人的绑定面(planDelegation fail-closed 校验)。
|
|
6
|
+
* 校验核心在 agents/node-delegation.ts;本文件只做工具面参数解析与结果文本。
|
|
7
|
+
*/
|
|
8
|
+
import { AppError } from '../../../../../utils/errors'
|
|
9
|
+
import { applyDelegation, planDelegation, revokeDelegation, type DelegationMember } from '../../node-delegation'
|
|
10
|
+
import type { HostToolBridgeContext, HostToolResult } from '../types'
|
|
11
|
+
|
|
12
|
+
/** workspace 成员视图(listAgents 与本工具面的最小接口;便于单测桩替换) */
|
|
13
|
+
interface MembersView {
|
|
14
|
+
listAgents(): Promise<Array<{ id: string, role: 'lead' | 'worker', enabled?: number }>>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function membersOf(ws: MembersView): Promise<DelegationMember[]> {
|
|
18
|
+
return ws.listAgents() as Promise<DelegationMember[]>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function summaryText(bindings: Array<{ nodeId: string, kind: string, mode: string }>): string {
|
|
22
|
+
const lines = bindings.map(b => ` - ${b.kind === 'daq' ? '数采' : '写控'} ${b.nodeId}(mode=${b.mode})`)
|
|
23
|
+
return `\n${lines.join('\n')}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function parseNodeIds(args: Record<string, unknown>): string[] {
|
|
27
|
+
const raw = args.node_ids ?? args.nodeIds
|
|
28
|
+
const list = Array.isArray(raw) ? raw : String(raw ?? '').split(',')
|
|
29
|
+
return list.map(x => String(x ?? '').trim()).filter(Boolean)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** lead → worker 授予节点(自己绑定面内的节点;fail-closed 全成全败) */
|
|
33
|
+
export async function handleGrantNodes(identity: HostToolBridgeContext['identity'], args: Record<string, unknown>, ws: MembersView): Promise<HostToolResult> {
|
|
34
|
+
const targetAgentId = String(args.agent_id ?? args.assignee_id ?? '').trim()
|
|
35
|
+
const nodeIds = parseNodeIds(args)
|
|
36
|
+
const mode = args.mode === 'manual' || args.mode === 'auto' ? (args.mode as 'auto' | 'manual') : undefined
|
|
37
|
+
try {
|
|
38
|
+
const plan = planDelegation({
|
|
39
|
+
leaderAgentId: identity.agentId,
|
|
40
|
+
channelId: identity.channelId,
|
|
41
|
+
targetAgentId,
|
|
42
|
+
nodeIds,
|
|
43
|
+
members: await membersOf(ws),
|
|
44
|
+
mode,
|
|
45
|
+
})
|
|
46
|
+
const bindings = applyDelegation(plan, identity.agentId)
|
|
47
|
+
return {
|
|
48
|
+
text: `已把 ${bindings.length} 条节点授权授予 ${targetAgentId}:${summaryText(bindings)}\n来源:lead 绑定面内的节点;worker 现在可用 my_industrial_nodes 查看自己的授权。`,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return { text: err instanceof AppError ? err.message : `节点授权失败: ${err instanceof Error ? err.message : String(err)}`, isError: true }
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** lead 收回授予给 worker 的节点授权 */
|
|
57
|
+
export async function handleRevokeNodes(identity: HostToolBridgeContext['identity'], args: Record<string, unknown>, ws: MembersView): Promise<HostToolResult> {
|
|
58
|
+
const targetAgentId = String(args.agent_id ?? args.assignee_id ?? '').trim()
|
|
59
|
+
const nodeIds = parseNodeIds(args)
|
|
60
|
+
try {
|
|
61
|
+
const results = revokeDelegation({
|
|
62
|
+
leaderAgentId: identity.agentId,
|
|
63
|
+
targetAgentId,
|
|
64
|
+
nodeIds,
|
|
65
|
+
members: await membersOf(ws),
|
|
66
|
+
})
|
|
67
|
+
const okList = results.filter(r => r.revoked)
|
|
68
|
+
const missList = results.filter(r => !r.revoked)
|
|
69
|
+
const parts = [`已收回 ${okList.length} 条授权`, ...okList.map(r => ` - ${r.kind} ${r.nodeId}`)]
|
|
70
|
+
if (missList.length) parts.push(`未收回(不在其绑定面或非你授予):${missList.map(r => `${r.kind}:${r.nodeId}`).join('、')}`)
|
|
71
|
+
return { text: parts.join('\n') }
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return { text: err instanceof AppError ? err.message : `收回授权失败: ${err instanceof Error ? err.message : String(err)}`, isError: true }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface DispatchGrantResult {
|
|
79
|
+
ok: boolean
|
|
80
|
+
text: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 派发时随任务授予节点(dispatch_task 的 grant_node_ids;lead 专属)。
|
|
85
|
+
* fail-closed:任一节点不在 lead 绑定面 → 整单失败,任务不创建。
|
|
86
|
+
*/
|
|
87
|
+
export async function grantNodesForDispatch(identity: HostToolBridgeContext['identity'], assigneeId: string, nodeIds: string[], mode: 'auto' | 'manual' | undefined, ws: MembersView): Promise<DispatchGrantResult> {
|
|
88
|
+
try {
|
|
89
|
+
const plan = planDelegation({
|
|
90
|
+
leaderAgentId: identity.agentId,
|
|
91
|
+
channelId: identity.channelId,
|
|
92
|
+
targetAgentId: assigneeId,
|
|
93
|
+
nodeIds,
|
|
94
|
+
members: await membersOf(ws),
|
|
95
|
+
mode,
|
|
96
|
+
})
|
|
97
|
+
const bindings = applyDelegation(plan, identity.agentId)
|
|
98
|
+
return { ok: true, text: `随任务授予 ${bindings.length} 条节点授权 → ${assigneeId}${summaryText(bindings)}` }
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
const msg = err instanceof AppError ? err.message : `随任务授予节点失败: ${err instanceof Error ? err.message : String(err)}`
|
|
102
|
+
return { ok: false, text: msg }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -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 分发层的同款守卫为并行在飞改动,待其收敛后接入(勿在此重复第三份清单)。 */
|
|
@@ -118,6 +118,26 @@ export const DEFAULT_CHANNEL_TEMPLATES: Array<{
|
|
|
118
118
|
{ inline: { name: '优化执行器', harness: 'omp', config: { rpcMode: 'rpc', systemPromptPrefix: '你是工艺参数优化执行器:按 goal 与节点物理意义规划探索方向与步长;用 optimization_explore 真实下发激励并读回目标响应;绑定模型后用 twin_trial_run 验证候选、twin_bayes_optimize 收敛寻优;所有写入遵守治理审批。结论必须引用带单位的数据。' } }, role: 'worker' },
|
|
119
119
|
],
|
|
120
120
|
},
|
|
121
|
+
{
|
|
122
|
+
id: 'chtpl-generic-optimize-default',
|
|
123
|
+
name: '通用闭环优化频道(标准)',
|
|
124
|
+
description: '标准 goal 驱动闭环优化团队,适配任意已建模产线(注塑/污水/退火/流延/双拉等):lead 编排(可选知识库检索与经验沉淀,支持把 lead 已绑定节点授权给 worker),工艺工程师治理下发,数据分析师证据判读。实例化时可开知识库集成(enableKnowledgeBase)。',
|
|
125
|
+
scenarioPrompt: `## 通用闭环优化作业(标准流程)
|
|
126
|
+
你是产线闭环优化团队,围绕用户 goal 对**任意已接入产线**做「取证 → 寻优 → 治理下发 → 复测收口」的闭环优化。开工前先用 my_industrial_nodes 与 line_context 弄清本频道持有的节点授权、产线/产品/配方与安全量程,不假设场景。
|
|
127
|
+
|
|
128
|
+
## 团队分工
|
|
129
|
+
- 生产主管(lead):把 goal 拆解为「数据分析」与「参数调整」子任务并派发(worker 缺节点权限时,用 team_grant_nodes 把 lead 已绑定的节点授予对应 worker,或在 dispatch_task 里带 grant_node_ids 随任务授予;只授予自己绑定的节点);复核成员结论(必须带数据证据)→ 汇总收口;对拿不准的现象先查知识库(若已启用)。
|
|
130
|
+
- 工艺工程师(worker):持有数控节点授权 —— daq_query 取证 → 判定设定-响应关系 → 在「安全量程 ∩ 配方窗口 ∩ 单步限幅」内用 dcw_control/param_control 小步幅下发(单变量);manual 模式节点先说明理由等用户批准;调整后等工艺惯性响应再复测;把「调整↔响应」证据回报 lead。
|
|
131
|
+
- 数据分析师(worker):持有数采节点授权 —— daq_query 时序取证(按批次/时间窗过滤),输出趋势/均值/越限统计与工况判读;异常第一时间通报 lead 与工艺工程师。
|
|
132
|
+
|
|
133
|
+
## 作业纪律
|
|
134
|
+
数据先行 → 窗口内小步幅(单次 ≤ 量程 2%)→ 单变量调整 → 复测闭环 → 结论必附带单位与时间窗的数据证据;不得操作未授权节点;治理审批与硬约束(步长限幅/写入间隔)被拒时按指引降步重试,不绕行。`,
|
|
135
|
+
members: [
|
|
136
|
+
{ inline: { name: '生产主管', harness: 'omp', config: { rpcMode: 'rpc', role: 'lead', systemPromptPrefix: '你是通用闭环优化团队的生产主管(lead):把用户 goal 拆解为「数据分析」「参数调整」子任务并用 dispatch_task 派发(可带 grant_node_ids 随任务把你自己已绑定的节点授权给 worker,或用 team_grant_nodes 执行中授予;只能授予自己绑定的节点);复核成员结论(必须带数据证据)后 complete 收口;若知识库已启用,开工前先用 kb_agent(mode=sync) 检索场景相关数据分析与物理机理,收口后用 kb_agent(mode=async) 沉淀本次经验(标题/类别/问题/解决方案/关键数据)。' } }, role: 'lead' },
|
|
137
|
+
{ inline: { name: '工艺工程师', harness: 'omp', config: { rpcMode: 'rpc', systemPromptPrefix: '你是通用闭环优化团队的工艺工程师,按节点物理意义做治理参数下发:my_industrial_nodes 确认授权 → daq_query 取证 → dcw_control/param_control 在「安全量程 ∩ 配方窗口 ∩ 单步限幅」内小步幅下发(单变量)→ 等待工艺惯性后 daq_query 复测。你的节点授权可能由 lead 在派发时或执行中授予(权限变化以 my_industrial_nodes 实时查询为准)。manual 模式节点下发前说明理由等批准。结论一律引用带单位与时间窗的数据。' } }, role: 'worker' },
|
|
138
|
+
{ inline: { name: '数据分析师', harness: 'omp', config: { rpcMode: 'rpc', systemPromptPrefix: '你是通用闭环优化团队的数据分析师,擅长时序取证与工况判读:用 daq_query 获取授权数采节点数据(按批次/时间窗),输出趋势/均值/极值/越限统计,结合数控设定考虑设定-响应滞后;发现越限或异常趋势立即用 send_message_to_agent 通报 lead 与工艺工程师。结论一律引用具体数值。' } }, role: 'worker' },
|
|
139
|
+
],
|
|
140
|
+
},
|
|
121
141
|
]
|
|
122
142
|
|
|
123
143
|
/**
|
|
@@ -11,6 +11,19 @@ import { KNOWN_HARNESSES } from './helpers'
|
|
|
11
11
|
import { parseJson } from '../../db/database'
|
|
12
12
|
import { setHybridChannelProfile } from '../../aml/twin/channel-profile'
|
|
13
13
|
import { defaultInjectionScene } from '../../aml/twin/physics-runtime'
|
|
14
|
+
import { getChannelPluginsRepo } from '../../db/channel-plugins.repo'
|
|
15
|
+
|
|
16
|
+
/** 携带「知识库集成」选项的模板:实例化时可显式启停 rag-bridge(开 → 注入 KB 作业段提示词) */
|
|
17
|
+
export const KNOWLEDGE_BASE_TEMPLATE_IDS = new Set(['chtpl-aml-optimization-default', 'chtpl-generic-optimize-default'])
|
|
18
|
+
|
|
19
|
+
/** 知识库集成开启时追加到频道场景提示词的作业段(教 lead 先检索后沉淀) */
|
|
20
|
+
export const KNOWLEDGE_BASE_PROMPT_SECTION = `
|
|
21
|
+
|
|
22
|
+
## 知识库集成(已启用 rag-bridge)
|
|
23
|
+
本频道接入了 rag-knowledge 知识库,优化作业遵循「先检索、后行动、再沉淀」:
|
|
24
|
+
1. 优化启动前,lead 先用 kb_agent(mode=sync) 检索知识库中与本场景相关的**数据分析结论**与**物理机理知识**(检索词带上产线/产品/关键物理量,如「注塑 保压 克重 波动」「烘箱温度 膜厚 滞后」);把检索所得的机理关系、历史阈值与经验教训作为探索方向、步长与安全边界的依据;
|
|
25
|
+
2. 优化过程中,若对某个现象拿不准,先查知识库再动手;worker 也可各自检索,但入库/沉淀由 lead 统一收口;
|
|
26
|
+
3. 优化闭环收口后(目标达标或 judge 判定 keep),lead 用 kb_agent(mode=async) 把本次经验沉淀入知识库:标题、类别(工艺经验/数据分析/故障案例)、问题、解决方案、关键数据(带单位的参数调整↔响应变化)。异步提交后无需等待,可继续汇报。`
|
|
14
27
|
|
|
15
28
|
export abstract class ManagerChannelTemplates extends ManagerTeams {
|
|
16
29
|
/** 可见性感知 Channel 模板列表:普通用户 = 本人 + public(含内置);admin = 全量 */
|
|
@@ -101,21 +114,31 @@ export abstract class ManagerChannelTemplates extends ManagerTeams {
|
|
|
101
114
|
* 场景/工作目录照搬;lead 内联创建;成员逐个克隆(引用模板时校验操作者可读)。
|
|
102
115
|
* 返回 createChannel 同构结果 + 成员实例数。
|
|
103
116
|
*/
|
|
104
|
-
async instantiateChannelTemplate(templateId: string, user: ActingUser, nameOverride?: string, options?: { scene?: Record<string, unknown>, promptVariables?: Record<string, unknown>, objective?: Record<string, unknown>, toolProfile?: string, controlPolicy?: 'recommendation_only' | 'hitl_governed' | 'bounded_auto', providerId?: string, providerVersion?: string, providerHash?: string, scenePackId?: string, optimizationMode?: 'exploration' | 'aml', boundModelId?: string }): Promise<{ channelId: string, workspace: string, agentCount: number, leadAgentId?: string, agents: Array<{ id: string, templateId?: string | null, name: string, role: string }> }> {
|
|
117
|
+
async instantiateChannelTemplate(templateId: string, user: ActingUser, nameOverride?: string, options?: { scene?: Record<string, unknown>, promptVariables?: Record<string, unknown>, objective?: Record<string, unknown>, toolProfile?: string, controlPolicy?: 'recommendation_only' | 'hitl_governed' | 'bounded_auto', providerId?: string, providerVersion?: string, providerHash?: string, scenePackId?: string, optimizationMode?: 'exploration' | 'aml', boundModelId?: string, enableKnowledgeBase?: boolean }): Promise<{ channelId: string, workspace: string, agentCount: number, leadAgentId?: string, agents: Array<{ id: string, templateId?: string | null, name: string, role: string }> }> {
|
|
105
118
|
const tpl = this.deps.repos.channelTemplates.findById(templateId)
|
|
106
119
|
if (!tpl) throw new AppError(404, 'NOT_FOUND', `Channel 模板不存在: ${templateId}`)
|
|
107
120
|
this.requireTemplateReadable(tpl, user, 'Channel 模板')
|
|
108
121
|
const lead = tpl.leadJson
|
|
109
122
|
? parseJson<{ name: string, harness: string, config?: Record<string, unknown> } | null>(tpl.leadJson, null)
|
|
110
123
|
: null
|
|
124
|
+
// 知识库集成:显式 true → 启用 rag-bridge 并在场景提示词追加 KB 作业段;
|
|
125
|
+
// 显式 false → 显式停用(频道内 kb_* 工具不注入);缺省 → 不写开关行(平台默认)。
|
|
126
|
+
const kb = options?.enableKnowledgeBase
|
|
127
|
+
const kbOn = kb === true
|
|
128
|
+
const scenarioPrompt = kbOn && KNOWLEDGE_BASE_TEMPLATE_IDS.has(tpl.id)
|
|
129
|
+
? (tpl.scenarioPrompt ?? '') + KNOWLEDGE_BASE_PROMPT_SECTION
|
|
130
|
+
: tpl.scenarioPrompt
|
|
111
131
|
const created = await this.createChannel({
|
|
112
132
|
name: (nameOverride && nameOverride.trim()) || tpl.name,
|
|
113
133
|
description: tpl.description,
|
|
114
|
-
scenarioPrompt
|
|
134
|
+
scenarioPrompt,
|
|
115
135
|
workspace: tpl.workspace || undefined,
|
|
116
136
|
leadAgent: lead ? { name: lead.name, harness: lead.harness, config: lead.config } : undefined,
|
|
117
137
|
ownerUserId: user.id,
|
|
118
138
|
})
|
|
139
|
+
if (kb !== undefined) {
|
|
140
|
+
getChannelPluginsRepo().setMany(created.channelId, [{ name: 'rag-bridge', enabled: kbOn }])
|
|
141
|
+
}
|
|
119
142
|
const members = parseJson<ChannelTemplateMember[]>(tpl.membersJson, [])
|
|
120
143
|
const agents: Array<{ id: string, templateId?: string | null, name: string, role: string }> = []
|
|
121
144
|
if (created.leadAgentId) agents.push({ id: created.leadAgentId, name: lead?.name ?? 'lead', role: 'lead' })
|
|
@@ -189,6 +212,7 @@ export abstract class ManagerChannelTemplates extends ManagerTeams {
|
|
|
189
212
|
visibility: row.ownerUserId === null ? 'public' : row.visibility,
|
|
190
213
|
isBuiltin: row.ownerUserId === null,
|
|
191
214
|
ownerUserId: row.ownerUserId ?? null,
|
|
215
|
+
knowledgeBaseCapable: KNOWLEDGE_BASE_TEMPLATE_IDS.has(row.id),
|
|
192
216
|
createdAt: row.createdAt,
|
|
193
217
|
updatedAt: row.updatedAt,
|
|
194
218
|
}
|
|
@@ -122,6 +122,8 @@ export interface ChannelTemplateDetail {
|
|
|
122
122
|
visibility: string
|
|
123
123
|
isBuiltin: boolean
|
|
124
124
|
ownerUserId: string | null
|
|
125
|
+
/** 模板支持「知识库集成」选项(实例化可传 enableKnowledgeBase 启停 rag-bridge) */
|
|
126
|
+
knowledgeBaseCapable?: boolean
|
|
125
127
|
createdAt: string
|
|
126
128
|
updatedAt: string
|
|
127
129
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{N as e,dt as t,g as n,mt as r,u as i,v as a}from"./CavpkQb0.js";import{S as o,V as s,W as ee,b as c,d as l,f as u,h as d,i as f,m as p,nt as m,p as h,y as g}from"./ByMj6e7s.js";import{d as te}from"./Br3AySNQ.js";import{n as _}from"./DkpmSnHX.js";import{n as v}from"./Cnrmlixo.js";import{t as ne}from"./Bub2P5me.js";import{a as y,c as re,n as ie}from"./wDPc4SSR.js";import{n as ae,t as oe}from"./k5K6Jj6g.js";import{t as se}from"./eutnXI4F.js";import{t as ce}from"./CAaSPBqk.js";import{i as le,n as ue,t as de}from"./DppqsiPC.js";import{t as fe}from"./B2x8SKRO2.js";import{t as pe}from"./CPeZNE4S2.js";import{t as me}from"./DzBbYWrw2.js";import{t as he}from"./DqtnqNgL2.js";import{t as ge}from"./CfLUvgr32.js";import{t as b}from"./CI2yXRr42.js";import{t as x}from"./BDNMzG2s2.js";import{t as S}from"./JgheoP3e.js";import{t as C}from"./CNs_Ozdc.js";import{t as w}from"./BWU1pvLL.js";import{i as T,n as E}from"./Du9v6qGB2.js";var _e={class:`page`},D={class:`head`},O={class:`sub`},k={class:`toolbar`},A={key:0,class:`admin-note`},j={class:`grid`},M={class:`card-head`},N={class:`name`},P={class:`owner`},F={key:0,class:`desc`},I={class:`member-line`},ve={class:`lead-name`},ye={key:0,class:`count`},L={key:1,class:`count`},be=[`title`],xe={class:`card-foot`},Se=[`title`],R=x(o({__name:`channel-templates`,setup(o){let{t:x}=v(),R=e=>E[e.id]?.desc?x(E[e.id].desc):e.description,z=e=>E[e.id]?.scenario?x(E[e.id].scenario):e.scenarioPrompt;C({layout:`default`});let B=w(),V=b(),H=a([]),U=a([]),W=a(!1),G=async()=>{W.value=!0;try{let[e,t]=await Promise.all([B.listChannelTemplates(),B.listTemplates()]);H.value=e?.data??[],U.value=t?.data??[]}finally{W.value=!1}};G();let K=a(`all`),q=l(()=>{let e=V.user?.id;switch(K.value){case`mine`:return H.value.filter(t=>t.ownerUserId===e);case`public`:return H.value.filter(e=>e.visibility===`public`);case`builtin`:return H.value.filter(e=>e.isBuiltin);default:return H.value}}),J=e=>!e.isBuiltin&&(e.ownerUserId===V.user?.id||V.isAdmin),Y=e=>e.isBuiltin?{text:x(`ctpl.k3x23c021`),color:`default`,icon:`i-tabler-lock`}:e.visibility===`public`?{text:x(`ctpl.k3wv1t022`),color:`green`}:{text:x(`ctpl.k447jj023`),color:`default`},Ce=e=>`templateId`in e?T(x,U.value.find(t=>t.id===e.templateId)??{id:e.templateId,name:e.templateId.slice(0,8)}):e.inline.name,X=a(!1),Z=n({name:``,description:``,scenarioPrompt:``,workspace:``,visibility:`private`,leadId:``,memberIds:[]}),Q=()=>{Z.name=``,Z.description=``,Z.scenarioPrompt=``,Z.workspace=``,Z.visibility=`private`,Z.leadId=``,Z.memberIds=[],X.value=!0},we=async()=>{if(!Z.name.trim()){y.warning(x(`ctpl.k1i0ji0y024`));return}let e=Z.leadId?U.value.find(e=>e.id===Z.leadId):void 0,t=Z.memberIds.filter(e=>e!==Z.leadId).map(e=>({templateId:e,role:`worker`}));try{await B.createChannelTemplate({name:Z.name.trim(),description:Z.description||void 0,scenarioPrompt:Z.scenarioPrompt||void 0,workspace:Z.workspace||void 0,lead:e?{name:e.name,harness:e.harness,config:e.config}:null,members:t,visibility:Z.visibility}),y.success(x(`ctpl.kyppebc025`)),X.value=!1,G()}catch(e){y.error(S(e))}},Te=async(e,t)=>{try{await B.updateChannelTemplate(e.id,{visibility:t?`public`:`private`}),y.success(x(t?`ctpl.kkziya3026`:`ctpl.k1xxabaf027`)),G()}catch(e){y.error(S(e))}},$=a(null),Ee=async e=>{$.value=e.id;try{let t=(await B.instantiateChannelTemplate(e.id))?.data;y.success(x(`ctpl.kefkfnl030`,{p0:e.name,p1:t?.agentCount??0}))}catch(e){y.error(S(e))}finally{$.value=null}},De=async e=>{await B.deleteChannelTemplate(e.id),y.success(x(`ctpl.k1oxfuqj028`)),G()};return _({title:()=>x(`titles.ctpl`)}),(n,a)=>{let o=re,l=pe,_=ge,v=de,y=he,b=fe,S=me,C=ce,w=ae,E=se,B=ne,G=ue,Oe=le,ke=oe,Ae=ie;return s(),d(`div`,_e,[u(`div`,D,[u(`div`,null,[u(`h2`,null,`Channel `+r(n.$t(`ctpl.k1f54iqd029`)),1),u(`p`,O,r(n.$t(`ctpl.k18gglgp011`)),1)]),c(l,null,{default:m(()=>[c(o,{onClick:a[0]||=t=>(`navigateTo`in n?n.navigateTo:e(te))(`/workshop`)},{default:m(()=>[g(r(n.$t(`ctpl.krpx6qa012`)),1)]),_:1}),c(o,{type:`primary`,onClick:Q},{default:m(()=>[g(r(n.$t(`ctpl.k1efixrj013`)),1)]),_:1})]),_:1})]),u(`div`,k,[c(_,{value:e(K),"onUpdate:value":a[1]||=e=>i(K)?K.value=e:null,size:`small`,options:[{value:`all`,label:n.$t(`chips.chipAll`,{n:e(H).length})},{value:`mine`,label:n.$t(`chips.mine`)},{value:`public`,label:n.$t(`chips.public`)},{value:`builtin`,label:n.$t(`chips.builtin`)}]},null,8,[`value`,`options`]),e(V).isAdmin?(s(),d(`span`,A,[a[10]||=u(`span`,{class:`i-tabler-shield-check`},null,-1),g(` `+r(n.$t(`ctpl.ka1gpdj014`)),1)])):p(``,!0)]),c(S,{spinning:e(W)},{default:m(()=>[u(`div`,j,[(s(!0),d(f,null,ee(e(q),i=>(s(),d(`div`,{key:i.id,class:`card`},[u(`div`,M,[u(`span`,N,r((`seedName`in n?n.seedName:e(T))(e(x),i)),1),c(v,{color:Y(i).color,class:`vis-tag`},{default:m(()=>[Y(i).icon?(s(),d(`span`,{key:0,class:t(Y(i).icon)},null,2)):p(``,!0),g(r(Y(i).text),1)]),_:2},1032,[`color`]),!i.isBuiltin&&J(i)?(s(),h(y,{key:0,checked:i.visibility===`public`,size:`small`,"checked-children":n.$t(`ctpl.visPublic`),"un-checked-children":n.$t(`ctpl.visPrivate`),onChange:e=>Te(i,e===!0)},null,8,[`checked`,`checked-children`,`un-checked-children`,`onChange`])):p(``,!0),u(`span`,P,r(i.ownerName??`-`),1)]),i.description?(s(),d(`p`,F,r(R(i)),1)):p(``,!0),u(`div`,I,[a[12]||=u(`span`,{class:`i-tabler-users-group`},null,-1),i.lead||i.members.length>0?(s(),d(f,{key:0},[c(v,{color:`gold`},{default:m(()=>[...a[11]||=[g(` lead `,-1)]]),_:1}),u(`span`,ve,r(i.lead?.name??Ce(i.members.find(e=>e.role===`lead`)??i.members[0])),1),i.members.filter(e=>e.role!==`lead`).length>0?(s(),d(`span`,ye,`+ `+r(i.members.filter(e=>e.role!==`lead`).length)+` worker`,1)):p(``,!0)],64)):(s(),d(`span`,L,r(n.$t(`ctpl.k3rx4ps015`)),1))]),i.scenarioPrompt?(s(),d(`div`,{key:1,class:`scenario`,title:i.scenarioPrompt},r(z(i).slice(0,90))+r(z(i).length>90?`…`:``),9,be)):p(``,!0),u(`div`,xe,[i.workspace?(s(),d(`span`,{key:0,class:`ws`,title:i.workspace},[a[13]||=u(`span`,{class:`i-tabler-folder`},null,-1),g(` `+r(i.workspace),1)],8,Se)):p(``,!0),a[14]||=u(`span`,{class:`spacer`},null,-1),J(i)?(s(),h(b,{key:1,title:n.$t(`ctpl.k117jag9001`),onConfirm:e=>De(i)},{default:m(()=>[c(o,{size:`small`,type:`text`,danger:``},{default:m(()=>[g(r(n.$t(`ctpl.k3xakp016`)),1)]),_:1})]),_:1},8,[`title`,`onConfirm`])):p(``,!0),c(o,{size:`small`,type:`primary`,ghost:``,loading:e($)===i.id,title:n.$t(`ctpl.knjomku002`),onClick:e=>Ee(i)},{default:m(()=>[g(r(n.$t(`ctpl.k3mr1fo017`)),1)]),_:1},8,[`loading`,`title`,`onClick`])])]))),128)),e(q).length===0?(s(),d(`div`,{key:0,class:`card placeholder`,onClick:Q},[a[15]||=u(`span`,{class:`i-tabler-layout-grid-add big`},null,-1),u(`span`,null,r(n.$t(`ctpl.k19fglby018`)),1)])):p(``,!0)])]),_:1},8,[`spinning`]),c(Ae,{open:e(X),"onUpdate:open":a[9]||=e=>i(X)?X.value=e:null,title:n.$t(`ctpl.newTplTitle`),"ok-text":n.$t(`common.create`),"cancel-text":n.$t(`common.cancel`),onOk:we},{default:m(()=>[c(ke,{layout:`vertical`},{default:m(()=>[c(w,{label:n.$t(`ctpl.k1f55q76003`)},{default:m(()=>[c(C,{value:e(Z).name,"onUpdate:value":a[2]||=t=>e(Z).name=t},null,8,[`value`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.k40gkk004`)},{default:m(()=>[c(C,{value:e(Z).description,"onUpdate:value":a[3]||=t=>e(Z).description=t},null,8,[`value`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.leadTplLabel`)},{default:m(()=>[c(E,{value:e(Z).leadId,"onUpdate:value":a[4]||=t=>e(Z).leadId=t,"allow-clear":``,placeholder:n.$t(`ctpl.k1ju32o7005`),options:e(U).map(e=>({value:e.id,label:`${e.name}(${e.harness})`}))},null,8,[`value`,`placeholder`,`options`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.k5uq1js006`)},{default:m(()=>[c(E,{value:e(Z).memberIds,"onUpdate:value":a[5]||=t=>e(Z).memberIds=t,mode:`multiple`,placeholder:n.$t(`ctpl.kqmdkc9007`),options:e(U).filter(t=>t.id!==e(Z).leadId).map(e=>({value:e.id,label:`${e.name}(${e.harness})`}))},null,8,[`value`,`placeholder`,`options`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.k1q87yho008`)},{default:m(()=>[c(B,{value:e(Z).scenarioPrompt,"onUpdate:value":a[6]||=t=>e(Z).scenarioPrompt=t,rows:3},null,8,[`value`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.kk4u5cr009`)},{default:m(()=>[c(C,{value:e(Z).workspace,"onUpdate:value":a[7]||=t=>e(Z).workspace=t,placeholder:`data/workspaces/<channelId>`},null,8,[`value`])]),_:1},8,[`label`]),c(w,{label:n.$t(`ctpl.k3lrqn0010`)},{default:m(()=>[c(Oe,{value:e(Z).visibility,"onUpdate:value":a[8]||=t=>e(Z).visibility=t},{default:m(()=>[c(G,{value:`private`},{default:m(()=>[g(r(n.$t(`ctpl.k17jfge3019`)),1)]),_:1}),c(G,{value:`public`},{default:m(()=>[g(r(n.$t(`ctpl.k191u0u5020`)),1)]),_:1})]),_:1},8,[`value`])]),_:1},8,[`label`])]),_:1})]),_:1},8,[`open`,`title`,`ok-text`,`cancel-text`])])}}}),[[`__scopeId`,`data-v-2c33b698`]]);export{R as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"08ba670b-7512-426b-a0ae-b10cbeb1c985","timestamp":1790570910812,"prerendered":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.page[data-v-2c33b698]{padding:4px}.head[data-v-2c33b698]{justify-content:space-between;align-items:center;margin-bottom:12px;display:flex}h2[data-v-2c33b698]{margin:0 0 4px}.sub[data-v-2c33b698]{opacity:.55;margin:0;font-size:12px}.toolbar[data-v-2c33b698]{align-items:center;gap:12px;margin-bottom:12px;display:flex}.admin-note[data-v-2c33b698]{color:var(--ink-faint);align-items:center;gap:5px;font-size:11px;display:inline-flex}.grid[data-v-2c33b698]{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px;display:grid}.card[data-v-2c33b698]{background:var(--paper-raised);border:1px solid var(--line);border-radius:var(--radius-panel);transition:border-color var(--transition-fast);flex-direction:column;gap:8px;padding:14px;display:flex}.card[data-v-2c33b698]:hover{border-color:var(--line-strong)}.card-head[data-v-2c33b698]{align-items:center;gap:8px;display:flex}.name[data-v-2c33b698]{text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:15px;font-weight:600;overflow:hidden}.vis-tag[data-v-2c33b698]{margin-right:2px}.owner[data-v-2c33b698]{color:var(--ink-faint);font-size:11px}.desc[data-v-2c33b698]{color:var(--ink-soft);margin:0;font-size:12px}.member-line[data-v-2c33b698]{align-items:center;gap:6px;font-size:12px;display:flex}.lead-name[data-v-2c33b698]{font-weight:500}.count[data-v-2c33b698]{font-family:var(--font-mono);color:var(--ink-faint);font-size:11px}.scenario[data-v-2c33b698]{font-family:var(--font-mono);color:var(--ink-faint);-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:10.5px;line-height:1.5;display:-webkit-box;overflow:hidden}.card-foot[data-v-2c33b698]{align-items:center;gap:6px;margin-top:2px;display:flex}.ws[data-v-2c33b698]{max-width:60%;font-family:var(--font-mono);color:var(--ink-faint);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:4px;font-size:10.5px;display:inline-flex;overflow:hidden}.spacer[data-v-2c33b698]{flex:auto}.card.placeholder[data-v-2c33b698]{opacity:.55;cursor:pointer;border-style:dashed;justify-content:center;align-items:center;min-height:160px;font-size:13px}.big[data-v-2c33b698]{font-size:28px}@media (width<=900px){.head[data-v-2c33b698]{flex-direction:column;align-items:stretch;gap:12px}.head>div[data-v-2c33b698]{min-width:0}.head h2[data-v-2c33b698]{font-size:21px;line-height:1.25}.head[data-v-2c33b698] .ant-space{flex-direction:column;align-items:stretch;gap:8px;width:100%;display:flex}.head[data-v-2c33b698] .ant-space-item{width:100%}.head[data-v-2c33b698] .ant-btn{width:100%;min-height:40px}.toolbar[data-v-2c33b698]{flex-wrap:wrap;gap:8px}.toolbar[data-v-2c33b698] .ant-segmented{flex:100%;min-width:0}.admin-note[data-v-2c33b698]{flex:100%;min-width:0;font-size:11.5px;line-height:1.5}.grid[data-v-2c33b698]{grid-template-columns:1fr}.card-head[data-v-2c33b698],.member-line[data-v-2c33b698],.card-foot[data-v-2c33b698]{flex-wrap:wrap}.ws[data-v-2c33b698]{max-width:100%}}@media (width<=640px){.page[data-v-2c33b698]{padding:0}.head h2[data-v-2c33b698]{font-size:19px}.sub[data-v-2c33b698]{font-size:11.5px;line-height:1.5}.scenario[data-v-2c33b698]{font-size:11.5px}}
|