agentworkshop 0.7.39 → 0.7.40
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 +55 -0
- package/.output/.AgentWorkShop/prompts/host-tools.json +55 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/88GOowgO2.js +1 -0
- package/.output/public/_nuxt/{BNT8gYU92.js → BC9wjTJK2.js} +2 -2
- package/.output/public/_nuxt/BOt2SP4z.js +1 -0
- package/.output/public/_nuxt/BP-NyKVG.js +18 -0
- package/.output/public/_nuxt/{HBLJ-wei.js → BXxH0UQE.js} +1 -1
- package/.output/public/_nuxt/{zIGh7R49.js → BneN7fbu.js} +1 -1
- package/.output/public/_nuxt/BsROmY89.js +1 -0
- package/.output/public/_nuxt/{C_OLzD09.js → C4oW1HsE.js} +1 -1
- package/.output/public/_nuxt/CFxtLwjp.js +1 -0
- package/.output/public/_nuxt/{Cec0Ua3F.js → CS50LB_l.js} +1 -1
- package/.output/public/_nuxt/C_iYD-EB.js +1 -0
- package/.output/public/_nuxt/{DAe0h2MB.js → ClILjvWH.js} +1 -1
- package/.output/public/_nuxt/CssgYAAL2.js +1 -0
- package/.output/public/_nuxt/{CY9LbPCI.js → CzOCSGLe.js} +1 -1
- package/.output/public/_nuxt/D8qvkfyY.js +1 -0
- package/.output/public/_nuxt/DCn7QZ5N.js +2 -0
- package/.output/public/_nuxt/DGIuvyRN2.js +1 -0
- package/.output/public/_nuxt/{CojCTLKD.js → DGj-WEBg.js} +1 -1
- package/.output/public/_nuxt/{DDShH71m.js → DS8qj8EL.js} +1 -1
- package/.output/public/_nuxt/DTFCy6h-.js +1 -0
- package/.output/public/_nuxt/{DrYV5i68.js → DUjW5Yq5.js} +1 -1
- package/.output/public/_nuxt/DZshyNLa.js +1 -0
- package/.output/public/_nuxt/{45zuyAso.js → D_OTvQza.js} +1 -1
- package/.output/public/_nuxt/DcsCcxp4.js +1 -0
- package/.output/public/_nuxt/{DUrecWPx.js → Dihnimlk.js} +2 -2
- package/.output/public/_nuxt/Dqw1lpr-.js +1 -0
- package/.output/public/_nuxt/{CUDwzgLV.js → Dr9v6C0f.js} +9 -9
- package/.output/public/_nuxt/{8NMOXZOV.js → Du9ZJtnj.js} +1 -1
- package/.output/public/_nuxt/TownView.f-YOdXRs.css +1 -0
- package/.output/public/_nuxt/_id_.CM4bIgKY.css +1 -0
- package/.output/public/_nuxt/_id_.bNV69Dtf.css +1 -0
- package/.output/public/_nuxt/_wsId_.B4WiqkIS.css +1 -0
- package/.output/public/_nuxt/agents.ZD0rVdHE.css +1 -0
- package/.output/public/_nuxt/aml.BN8ZEW4h.css +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +1 -0
- package/.output/public/_nuxt/channel-templates.BOtahzPi.css +1 -0
- package/.output/public/_nuxt/daq.B0D3dPAc.css +1 -0
- package/.output/public/_nuxt/dcw.8Y7FqCVN.css +1 -0
- package/.output/public/_nuxt/default.J32SgqFY.css +1 -0
- package/.output/public/_nuxt/entry.bdm0tv6M.css +1 -0
- package/.output/public/_nuxt/logs.BpKzmKsh.css +1 -0
- package/.output/public/_nuxt/monitor.D9pe7qN6.css +1 -0
- package/.output/public/_nuxt/pages.D7aSDlUI.css +1 -0
- package/.output/public/_nuxt/permissions.DwTVlFe6.css +1 -0
- package/.output/public/_nuxt/plugins.sb4nDGqr.css +1 -0
- package/.output/public/_nuxt/{Cbq-mryP.js → qr6R6Ha1.js} +1 -1
- package/.output/public/_nuxt/settings.BTgR-NiE.css +1 -0
- package/.output/public/_nuxt/teams.CxnxKVVs.css +1 -0
- package/.output/public/_nuxt/tokens.BFY7qv4f.css +1 -0
- package/.output/public/_nuxt/{town.DKIAhKnx.css → town.BBXZmeoP.css} +1 -1
- package/.output/public/_nuxt/users.DLgZ1D0h.css +1 -0
- package/.output/public/_nuxt/workshop.CR_QzeAN.css +1 -0
- package/.output/public/_nuxt/{BzHEilTt.js → xh3_vYcu.js} +1 -1
- package/.output/public/_nuxt/yF0aYMF1.js +4 -0
- package/.output/server/chunks/_/entity.mjs.map +1 -1
- package/.output/server/chunks/_/nitro.mjs +2225 -1445
- package/.output/server/chunks/_/nitro.mjs.map +1 -1
- package/.output/server/chunks/build/{TownView-jVazYOjN.mjs → TownView-BuLAsmpR.mjs} +288 -206
- package/.output/server/chunks/build/TownView-BuLAsmpR.mjs.map +1 -0
- package/.output/server/chunks/build/{_id_-CfVosNg3.mjs → _id_-BU1wfOID.mjs} +138 -138
- package/.output/server/chunks/build/{_id_-CfVosNg3.mjs.map → _id_-BU1wfOID.mjs.map} +1 -1
- package/.output/server/chunks/build/{_id_-Hwr4rZpr.mjs → _id_-BYsEua57.mjs} +33 -32
- package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +1 -0
- package/.output/server/chunks/build/{_wsId_-BVg3bB77.mjs → _wsId_-BxlDcJHg.mjs} +293 -259
- package/.output/server/chunks/build/{_wsId_-BVg3bB77.mjs.map → _wsId_-BxlDcJHg.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-Bvin73QY.mjs → agents-CLQqJF2y.mjs} +21 -27
- package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +1 -0
- package/.output/server/chunks/build/{aml-BCSJCdX7.mjs → aml-_7FdFL2p.mjs} +109 -109
- package/.output/server/chunks/build/{aml-BCSJCdX7.mjs.map → aml-_7FdFL2p.mjs.map} +1 -1
- package/.output/server/chunks/build/api-error-dul30BYQ.mjs.map +1 -1
- package/.output/server/chunks/build/{channel-templates-BTq8570n.mjs → channel-templates-p6SZNjlM.mjs} +19 -19
- package/.output/server/chunks/build/{channel-templates-BTq8570n.mjs.map → channel-templates-p6SZNjlM.mjs.map} +1 -1
- package/.output/server/chunks/build/{daq-C03Uu5UE.mjs → daq-cgyjKmJu.mjs} +188 -122
- package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +1 -0
- package/.output/server/chunks/build/{dcw-6vEYVeje.mjs → dcw-CoTxBlAZ.mjs} +45 -45
- package/.output/server/chunks/build/{dcw-6vEYVeje.mjs.map → dcw-CoTxBlAZ.mjs.map} +1 -1
- package/.output/server/chunks/build/{default-CZmZFpqH.mjs → default-BE4r0FZN.mjs} +152 -58
- package/.output/server/chunks/build/{default-CZmZFpqH.mjs.map → default-BE4r0FZN.mjs.map} +1 -1
- package/.output/server/chunks/build/{logs-B-xhuqln.mjs → logs-BSOeZwwI.mjs} +34 -34
- package/.output/server/chunks/build/{logs-B-xhuqln.mjs.map → logs-BSOeZwwI.mjs.map} +1 -1
- package/.output/server/chunks/build/{monitor-CyfDt4nR.mjs → monitor-C0okQaXz.mjs} +33 -33
- package/.output/server/chunks/build/{monitor-CyfDt4nR.mjs.map → monitor-C0okQaXz.mjs.map} +1 -1
- package/.output/server/chunks/build/{pages-BO7yZsXA.mjs → pages-DFxjn9Xa.mjs} +33 -17
- package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +1 -0
- package/.output/server/chunks/build/{permissions-B52oOmaO.mjs → permissions-68SsNjex.mjs} +12 -12
- package/.output/server/chunks/build/{permissions-B52oOmaO.mjs.map → permissions-68SsNjex.mjs.map} +1 -1
- package/.output/server/chunks/build/{plugins-CUWmMdyt.mjs → plugins-lGlUr1lj.mjs} +17 -17
- package/.output/server/chunks/build/{plugins-CUWmMdyt.mjs.map → plugins-lGlUr1lj.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-DoQ2Oq3P.mjs → settings-Ddd1qx2Z.mjs} +50 -47
- package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +1 -0
- package/.output/server/chunks/build/{teams-2kz3CusY.mjs → teams-MEDLZdMn.mjs} +38 -34
- package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +1 -0
- package/.output/server/chunks/build/{tokens-BbWLqtVz.mjs → tokens-C7fTM5C2.mjs} +14 -14
- package/.output/server/chunks/build/{tokens-BbWLqtVz.mjs.map → tokens-C7fTM5C2.mjs.map} +1 -1
- package/.output/server/chunks/build/{town-BOl6hs9B.mjs → town-qMPql9Se.mjs} +36 -10
- package/.output/server/chunks/build/town-qMPql9Se.mjs.map +1 -0
- package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs +1 -1
- package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs +1 -1
- package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs +49 -0
- package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs.map +1 -0
- package/.output/server/chunks/build/{users-fohSmF-J.mjs → users-Cfd5-l2-.mjs} +6 -6
- package/.output/server/chunks/build/{users-fohSmF-J.mjs.map → users-Cfd5-l2-.mjs.map} +1 -1
- package/.output/server/chunks/build/{workshop-DX5-ldc4.mjs → workshop-BL5bhfs0.mjs} +15 -15
- package/.output/server/chunks/build/{workshop-DX5-ldc4.mjs.map → workshop-BL5bhfs0.mjs.map} +1 -1
- package/.output/server/chunks/build/{workspaces-BuydxM-3.mjs → workspaces-Bgz5Ekwp.mjs} +18 -3
- package/.output/server/chunks/build/workspaces-Bgz5Ekwp.mjs.map +1 -0
- package/.output/server/chunks/routes/api/system/config-groups/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/system/index.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/system/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/system/settings/events.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +2 -1
- package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
- package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +3 -2
- package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -1
- package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +8 -6
- package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +5 -5
- package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +14 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +4 -4
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +4 -3
- package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +31 -0
- package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +28 -0
- package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +32 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +34 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +33 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +34 -0
- package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs.map +1 -0
- 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/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/index6.get.mjs +2 -0
- package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs +3 -1
- package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +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/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +3 -3
- package/.output/server/chunks/virtual/entry.mjs +51 -25
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/README-zh.md +199 -35
- package/README.md +739 -591
- package/app/app.vue +9 -3
- package/app/assets/css/main.css +517 -7
- package/app/components/AppHeader.vue +98 -7
- package/app/components/AppSidebar.vue +117 -11
- package/app/components/AwChart.vue +2 -1
- package/app/components/workshop/AgentInspectorDrawer.vue +6 -6
- package/app/components/workshop/AgentLanesView.vue +52 -1
- package/app/components/workshop/AssetLibrary.vue +4 -2
- package/app/components/workshop/ChannelSessionList.vue +4 -2
- package/app/components/workshop/Composer.vue +96 -0
- package/app/components/workshop/DaqNodeRow.vue +19 -0
- package/app/components/workshop/DaqTemplateIcon.vue +33 -0
- package/app/components/workshop/DeviceTwinPanel.vue +37 -35
- package/app/components/workshop/EventBlock.vue +3 -3
- package/app/components/workshop/InspectorPanel.vue +47 -11
- package/app/components/workshop/LiveAgentBar.vue +34 -0
- package/app/components/workshop/TaskBoardView.vue +83 -33
- package/app/components/workshop/TranscriptTimeline.vue +56 -0
- package/app/components/workshop/blocks/ClusterError.vue +1 -1
- package/app/components/workshop/blocks/ClusterRoute.vue +3 -1
- package/app/components/workshop/blocks/ClusterStatus.vue +2 -2
- package/app/components/workshop/blocks/ClusterStream.vue +8 -2
- package/app/components/workshop/town/ModelPreview3D.vue +1 -1
- package/app/components/workshop/town/TownView.vue +507 -82
- package/app/composables/useResponsive.ts +88 -0
- package/app/composables/useRouteMeta.ts +3 -0
- package/app/composables/workshop/useDcwStream.ts +1 -1
- package/app/composables/workshop/useVisibleInterval.ts +2 -2
- package/app/composables/workshop/useWorkshopApi.ts +1 -1
- package/app/layouts/default.vue +46 -2
- package/app/pages/aml/index.vue +712 -616
- package/app/pages/daq/[id].vue +3 -2
- package/app/pages/daq/index.vue +209 -9
- package/app/pages/dcw/[id].vue +109 -28
- package/app/pages/dcw/index.vue +83 -23
- package/app/pages/index.vue +35 -1
- package/app/pages/logs/index.vue +147 -13
- package/app/pages/monitor.vue +56 -12
- package/app/pages/permissions/index.vue +34 -0
- package/app/pages/plugins/index.vue +35 -4
- package/app/pages/settings.vue +90 -21
- package/app/pages/tokens.vue +23 -0
- package/app/pages/town.vue +50 -5
- package/app/pages/users.vue +23 -0
- package/app/pages/workshop/agents.vue +92 -2
- package/app/pages/workshop/channel-templates.vue +53 -0
- package/app/pages/workshop/index.vue +14 -0
- package/app/pages/workshop/teams.vue +66 -6
- package/app/pages/workshop/w/[wsId].vue +202 -14
- package/app/plugins/aw-plugins.client.ts +13 -8
- package/app/stores/app.ts +33 -1
- package/app/stores/workshop/user.ts +1 -1
- package/app/stores/workshop/workspaces.ts +18 -2
- package/app/utils/api-error.ts +1 -1
- package/cli/commands/build.mjs +8 -1
- package/docker-compose.yml +6 -0
- package/i18n/locales/en.ts +2 -0
- package/i18n/locales/zh-CN.ts +2 -0
- package/nuxt.config.ts +31 -0
- package/package.json +9 -1
- package/scripts/_dbg-param-map-e2e.ts +242 -0
- package/scripts/_dbg-param-map-rest-smoke.mjs +73 -0
- package/scripts/_dbg-param-real-scenario.mjs +153 -0
- package/scripts/api-live-e2e.mjs +40 -8
- package/scripts/capture-walkthrough.mjs +232 -0
- package/scripts/render-walkthrough-figure.mjs +46 -0
- package/scripts/seed-walkthrough-fixture.mjs +143 -0
- package/scripts/test-plugin-hardening.mjs +8 -0
- package/scripts/ui/admin-shots.mjs +46 -0
- package/scripts/ui/audit-layout.mjs +301 -0
- package/scripts/ui/bump-microfont.mjs +39 -0
- package/scripts/ui/lib.mjs +198 -0
- package/scripts/ui/linkcheck2.mjs +37 -0
- package/scripts/ui/live-render-check.mjs +72 -0
- package/scripts/ui/md-lint.mjs +80 -0
- package/scripts/ui/perf-audit.mjs +132 -0
- package/scripts/ui/readme-assets.mjs +30 -0
- package/scripts/ui/readme-shots.mjs +42 -0
- package/scripts/ui/record.mjs +225 -0
- package/scripts/ui/seed-admin.mjs +68 -0
- package/scripts/ui/seed-demo.mjs +83 -0
- package/scripts/ui/shot-hero.mjs +25 -0
- package/scripts/ui/shots.mjs +75 -0
- package/scripts/ui/sim-ui-shot.mjs +16 -0
- package/scripts/ui/verify-nav.mjs +51 -0
- package/scripts/ui/verify-responsive.mjs +285 -0
- package/server/api/system/config-groups/[id].patch.ts +1 -1
- package/server/api/system/config-groups/index.post.ts +1 -1
- package/server/api/system/settings/events.get.ts +1 -1
- package/server/api/system/settings/index.patch.ts +1 -1
- package/server/api/workshop/agent-tools/invoke.post.ts +16 -2
- package/server/api/workshop/aml/datasets/[id].get.ts +8 -1
- package/server/api/workshop/daq/infra/reconnect.post.ts +1 -1
- package/server/api/workshop/daq/templates/[key].delete.ts +1 -0
- package/server/api/workshop/daq/templates/[key].patch.ts +1 -0
- package/server/api/workshop/daq/templates/index.post.ts +1 -0
- package/server/api/workshop/dcw/[id]/write.post.ts +10 -2
- package/server/api/workshop/dcw/[id].delete.ts +5 -2
- package/server/api/workshop/dcw/index.get.ts +2 -0
- package/server/api/workshop/dcw/lines/[id].patch.ts +1 -1
- package/server/api/workshop/dcw/params/[id]/read.post.ts +17 -0
- package/server/api/workshop/dcw/params/[id]/write.post.ts +21 -0
- package/server/api/workshop/dcw/params/[id].delete.ts +19 -0
- package/server/api/workshop/dcw/params/[id].patch.ts +23 -0
- package/server/api/workshop/dcw/params/index.get.ts +27 -0
- package/server/api/workshop/dcw/params/index.post.ts +25 -0
- package/server/api/workshop/permissions/index.get.ts +3 -1
- package/server/plugins/aw-plugins.ts +14 -3
- package/server/plugins/dev-stability-guard.ts +3 -1
- package/server/plugins/system-config.ts +6 -1
- package/server/services/system-config.ts +28 -9
- package/server/services/workshop/agents/adapters/one-shot-cli-agent.ts +2 -1
- package/server/services/workshop/agents/agent-interface.ts +8 -6
- package/server/services/workshop/agents/base-agent.ts +18 -4
- package/server/services/workshop/agents/claude-agent.ts +7 -3
- package/server/services/workshop/agents/codex-agent.ts +3 -3
- package/server/services/workshop/agents/dsh-agent.ts +3 -3
- package/server/services/workshop/agents/goose-agent.ts +0 -1
- package/server/services/workshop/agents/harness-terminal.ts +14 -1
- package/server/services/workshop/agents/hermes-agent.ts +4 -2
- package/server/services/workshop/agents/host-tool-bridge.ts +5 -1
- package/server/services/workshop/agents/industrial-context.ts +4 -1
- package/server/services/workshop/agents/industrial-tools.ts +164 -6
- package/server/services/workshop/agents/omp-agent.ts +15 -9
- package/server/services/workshop/agents/opencode-agent.ts +47 -21
- package/server/services/workshop/agents/qwen-agent.ts +10 -5
- package/server/services/workshop/aml/entity.ts +3 -1
- package/server/services/workshop/aml/python-runtime.ts +3 -2
- package/server/services/workshop/daq/bus/mqtt.adapter.ts +8 -4
- package/server/services/workshop/daq/daq-controller.ts +18 -3
- package/server/services/workshop/daq/daq-runtime.ts +5 -3
- package/server/services/workshop/daq/drivers.ts +63 -8
- package/server/services/workshop/daq/host-ports.ts +3 -2
- package/server/services/workshop/daq/storage/timescale.adapter.ts +3 -1
- package/server/services/workshop/db/channel.repo.ts +4 -0
- package/server/services/workshop/db/ops.repo.ts +5 -2
- package/server/services/workshop/db/retention.ts +8 -3
- package/server/services/workshop/dcw/dcw-controller.ts +143 -16
- package/server/services/workshop/dcw/dcw-product.repo.ts +38 -1
- package/server/services/workshop/dcw/dcw-runtime.ts +3 -2
- package/server/services/workshop/dcw/drivers.ts +5 -2
- package/server/services/workshop/dcw/param-conversion.ts +78 -0
- package/server/services/workshop/dcw/param-limits.ts +142 -0
- package/server/services/workshop/dcw/param-map.repo.ts +305 -0
- package/server/services/workshop/dcw/recipe-rollback-manager.ts +13 -7
- package/server/services/workshop/runtime/agent-runtime.ts +4 -0
- package/server/services/workshop/runtime/manager.ts +9 -2
- package/server/services/workshop/settings.ts +4 -2
- package/server/types/pg.d.ts +49 -0
- package/server/utils/stability-severity.ts +13 -2
- package/shared/config/groups.mjs +22 -1
- package/shared/config/home.d.mts +28 -0
- package/shared/dcw-protocol.ts +136 -0
- package/uno.config.ts +12 -1
- package/.output/public/_nuxt/BFkgkW8u.js +0 -4
- package/.output/public/_nuxt/C5gUkRwn.js +0 -1
- package/.output/public/_nuxt/CM12FuB42.js +0 -1
- package/.output/public/_nuxt/CZiw7sEV.js +0 -1
- package/.output/public/_nuxt/Cc_9VzD42.js +0 -1
- package/.output/public/_nuxt/CdPzkOMV.js +0 -1
- package/.output/public/_nuxt/CmsOtOAA2.js +0 -1
- package/.output/public/_nuxt/D1YDxZpZ.js +0 -1
- package/.output/public/_nuxt/D20Yamr4.js +0 -1
- package/.output/public/_nuxt/DmqknNvV.js +0 -18
- package/.output/public/_nuxt/DnUuIR83.js +0 -1
- package/.output/public/_nuxt/S_fVQwJK.js +0 -1
- package/.output/public/_nuxt/TownView.0oLiQgTC.css +0 -1
- package/.output/public/_nuxt/_id_.D-SYuyZb.css +0 -1
- package/.output/public/_nuxt/_id_.hma_BU6T.css +0 -1
- package/.output/public/_nuxt/_wsId_.B12v3PhY.css +0 -1
- package/.output/public/_nuxt/agents.BV70ioCv.css +0 -1
- package/.output/public/_nuxt/ahgEJu2R.js +0 -1
- package/.output/public/_nuxt/aml.COEKNNqK.css +0 -1
- package/.output/public/_nuxt/builds/meta/4457d63f-0866-4cea-b320-04a321f24795.json +0 -1
- package/.output/public/_nuxt/channel-templates.C-M5nKcC.css +0 -1
- package/.output/public/_nuxt/daq.B3265ZDn.css +0 -1
- package/.output/public/_nuxt/dcw.DLYZqEhT.css +0 -1
- package/.output/public/_nuxt/default.BXI_fZUi.css +0 -1
- package/.output/public/_nuxt/entry.BB-Eeh-J.css +0 -1
- package/.output/public/_nuxt/logs.CqFyMrJw.css +0 -1
- package/.output/public/_nuxt/monitor.B--1dPzs.css +0 -1
- package/.output/public/_nuxt/pages.ooEzrMm9.css +0 -1
- package/.output/public/_nuxt/permissions.B1pjGChZ.css +0 -1
- package/.output/public/_nuxt/plugins.5e5chZ67.css +0 -1
- package/.output/public/_nuxt/pz2JDAM7.js +0 -2
- package/.output/public/_nuxt/settings.Dm3M0RLy.css +0 -1
- package/.output/public/_nuxt/teams.BC75EGnR.css +0 -1
- package/.output/public/_nuxt/tokens.xRb1fSPU.css +0 -1
- package/.output/public/_nuxt/users.CXnP2E08.css +0 -1
- package/.output/public/_nuxt/workshop.Jk5HxWPE.css +0 -1
- package/.output/server/chunks/build/TownView-jVazYOjN.mjs.map +0 -1
- package/.output/server/chunks/build/_id_-Hwr4rZpr.mjs.map +0 -1
- package/.output/server/chunks/build/agents-Bvin73QY.mjs.map +0 -1
- package/.output/server/chunks/build/daq-C03Uu5UE.mjs.map +0 -1
- package/.output/server/chunks/build/pages-BO7yZsXA.mjs.map +0 -1
- package/.output/server/chunks/build/settings-DoQ2Oq3P.mjs.map +0 -1
- package/.output/server/chunks/build/teams-2kz3CusY.mjs.map +0 -1
- package/.output/server/chunks/build/town-BOl6hs9B.mjs.map +0 -1
- package/.output/server/chunks/build/workspaces-BuydxM-3.mjs.map +0 -1
- /package/.output/public/_nuxt/{36oeS8_R2.js → 36oeS8_R.js} +0 -0
- /package/.output/public/_nuxt/{CYWVXZTS.js → CYWVXZTS2.js} +0 -0
|
@@ -19,6 +19,9 @@ import { daqRuntimeSettings } from '../settings'
|
|
|
19
19
|
import { getDaqNodeRepo } from '../daq/daq-node.repo'
|
|
20
20
|
import { findDaqTemplate } from '../daq/daq-templates'
|
|
21
21
|
import { getRecipeRollBackManager } from '../dcw/recipe-rollback-manager'
|
|
22
|
+
import { getDcwParamRepo } from '../dcw/param-map.repo'
|
|
23
|
+
import { limitsBreakdownOf } from '../dcw/param-limits'
|
|
24
|
+
import type { DcwParamView } from '../../../../shared/dcw-protocol'
|
|
22
25
|
import { getOps, recordOps } from '../ops/ops'
|
|
23
26
|
import { getDcwLineRepo } from '../dcw/dcw-line.repo'
|
|
24
27
|
import { getDcwProductRepo } from '../dcw/dcw-product.repo'
|
|
@@ -75,7 +78,10 @@ export async function toolMyIndustrialNodes(agentId: string): Promise<{ text: st
|
|
|
75
78
|
---
|
|
76
79
|
通用规则:
|
|
77
80
|
1. 一个 Agent 可绑定多个节点;先读本清单理解每个节点的物理意义与操作守则,再动手。
|
|
78
|
-
2.
|
|
81
|
+
2. 数控下发优先用 param_control(param, value) 以**工艺参数**寻址(key 语义稳定,跨批次/换配方不变);
|
|
82
|
+
dcw_control(node_id, value) 为节点直接寻址的兼容面。设定值受四层限界联锁
|
|
83
|
+
(节点安全量程 ∩ 工艺参数基准限界 ∩ 活动产品限界 ∩ 活动配方工艺窗口)逐层收窄,
|
|
84
|
+
越界一律拒绝 —— 用户与 Agent 一体约束,无旁路。下发前/后用 param_read(param) 读 PLC 当前值取证复核(被动观测免审批)。
|
|
79
85
|
3. 数据获取 daq_query(不传 node_id = 全部数采节点),支持按产线/产品/配方/时间检索;解读数据时结合语义卡的判读方法。
|
|
80
86
|
4. 改动设定后等待工艺响应(热惯性/传动惯量)再评估,避免连续大幅调整。
|
|
81
87
|
5. 调控闭环:每次下发自动开一条优化记录(open);观察数采后用 dcw_judge 落判定(keep/rollback/uncertain);
|
|
@@ -130,11 +136,8 @@ export async function toolDcwControl(agentId: string, args: { node_id?: string,
|
|
|
130
136
|
if (approvals.hasPendingFor(agentId, nodeId)) {
|
|
131
137
|
return { text: `你对该节点已有一条待审批的下发指令,请等待用户处理后再发新指令(避免审批堆积)。`, isError: true }
|
|
132
138
|
}
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
const param = recipe?.params.find(p => p.nodeId === nodeId)
|
|
136
|
-
const detail = `${node.name}(${tpl?.ch ?? node.templateKey})设定 ${value}${node.unit}`
|
|
137
|
-
+ (param && (param.min != null || param.max != null) ? `,配方窗口 ${param.min ?? '-∞'}~${param.max ?? '+∞'}${node.unit}` : `,安全量程 ${node.min}~${node.max}${node.unit}`)
|
|
139
|
+
const bd = limitsBreakdownOf(node)
|
|
140
|
+
const detail = `${node.name}(${tpl?.ch ?? node.templateKey})设定 ${value}${node.unit},有效写入区间 ${bd.effective.min}~${bd.effective.max}${node.unit}(${bd.layers.map(l => l.label).join(' ∩ ')})`
|
|
138
141
|
const ap = await approvals.request(agentId, nodeId, 'dcw', detail)
|
|
139
142
|
if (!ap.approved) {
|
|
140
143
|
return { text: `指令未执行:用户${ap.comment.includes('超时') ? '未在时限内批准(超时)' : `拒绝了本次下发`}。用户备注:${ap.comment || '(无)'}` }
|
|
@@ -236,6 +239,161 @@ function writeToleranceOf(node: { decimals: number, min: number, max: number }):
|
|
|
236
239
|
return Math.max(0.5 * 10 ** -node.decimals, (node.max - node.min) * 0.005)
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
/** 工艺参数解析(param_control/param_read 共用):pp-id 优先,其次按 key;跨产线同名需 line_id 消歧 */
|
|
243
|
+
function resolveParamRef(ref: string, lineId?: string): { ok: true, param: DcwParamView } | { ok: false, text: string, isError: true } {
|
|
244
|
+
const repo = getDcwParamRepo()
|
|
245
|
+
const trimmed = String(ref ?? '').trim()
|
|
246
|
+
if (!trimmed) {
|
|
247
|
+
return { ok: false, text: 'param 必填:工艺参数 id(pp-*)或参数 key(见 my_industrial_nodes)。', isError: true }
|
|
248
|
+
}
|
|
249
|
+
const row = trimmed.startsWith('pp-') ? repo.byId(trimmed) : undefined
|
|
250
|
+
if (row) {
|
|
251
|
+
const view = repo.viewOf(row)
|
|
252
|
+
if (!view) return { ok: false, text: `工艺参数 ${trimmed} 的执行节点已不存在(映射悬空)。`, isError: true }
|
|
253
|
+
if (lineId && view.lineId !== lineId) {
|
|
254
|
+
return { ok: false, text: `工艺参数 ${view.key} 不属于产线 ${lineId}(实际归属:${view.lineId || '未分配'})。`, isError: true }
|
|
255
|
+
}
|
|
256
|
+
return { ok: true, param: view }
|
|
257
|
+
}
|
|
258
|
+
const hits = repo.byKey(trimmed)
|
|
259
|
+
.map(r => repo.viewOf(r))
|
|
260
|
+
.filter((v): v is DcwParamView => v != null)
|
|
261
|
+
const scoped = lineId ? hits.filter(v => v.lineId === lineId) : hits
|
|
262
|
+
if (scoped.length === 1) return { ok: true, param: scoped[0]! }
|
|
263
|
+
if (scoped.length === 0) {
|
|
264
|
+
const catalog = repo.listViews().slice(0, 12).map(v => `${v.key}(${v.name})`).join('、')
|
|
265
|
+
return { ok: false, text: `未找到工艺参数「${trimmed}」${lineId ? `(产线 ${lineId})` : ''}。可用参数:${catalog || '无 —— 请先让用户创建写控节点生成参数面'}。`, isError: true }
|
|
266
|
+
}
|
|
267
|
+
return { ok: false, text: `工艺参数「${trimmed}」命中 ${scoped.length} 条同名映射,请附加 line_id 消歧或改用参数 id(${scoped.map(v => v.id).join(' / ')})。`, isError: true }
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** 参数面权限摘要(工具回包统一口径;不透出寄存器等 PLC 寻址细节) */
|
|
271
|
+
function paramLimitsText(param: DcwParamView): string {
|
|
272
|
+
const node = getDcwController().byId(param.nodeId)
|
|
273
|
+
if (!node) return '执行节点已删除'
|
|
274
|
+
const bd = limitsBreakdownOf(node)
|
|
275
|
+
const layers = bd.layers.filter(l => l.min != null || l.max != null).map(l => l.label).join(' ∩ ')
|
|
276
|
+
return `有效写入区间 ${bd.effective.min}~${bd.effective.max}${param.unit}(约束层:${layers || '无'})`
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** 工具:param_control —— 按工艺参数下发设定值(推荐的参数语义寻址面)。
|
|
280
|
+
* 权限沿用节点绑定(参数 → 执行节点);限界联锁(参数基准 ∩ 产品 ∩ 配方 ∩ 节点安全量程)
|
|
281
|
+
* 在网关咽喉点统一生效。args.hypothesis 声明本次假设(入册),args.task_id 关联任务。 */
|
|
282
|
+
export async function toolParamControl(agentId: string, args: {
|
|
283
|
+
param?: string
|
|
284
|
+
value?: number | string
|
|
285
|
+
hypothesis?: string
|
|
286
|
+
task_id?: string
|
|
287
|
+
line_id?: string
|
|
288
|
+
}): Promise<{ text: string, isError?: boolean }> {
|
|
289
|
+
const resolved = resolveParamRef(String(args.param ?? ''), args.line_id ? String(args.line_id) : undefined)
|
|
290
|
+
if (!resolved.ok) return resolved
|
|
291
|
+
const param = resolved.param
|
|
292
|
+
const value = Number(args.value)
|
|
293
|
+
if (!Number.isFinite(value)) {
|
|
294
|
+
return { text: '设定值 value 必须为数字。', isError: true }
|
|
295
|
+
}
|
|
296
|
+
const repo = getAgentNodeBindingRepo()
|
|
297
|
+
const binding = repo.find(agentId, param.nodeId, 'dcw')
|
|
298
|
+
if (!binding) {
|
|
299
|
+
const mine = repo.byAgent(agentId).filter(b => b.kind === 'dcw')
|
|
300
|
+
return {
|
|
301
|
+
text: mine.length
|
|
302
|
+
? `无权操作工艺参数「${param.key}」(执行节点 ${param.nodeId} 未绑定给你)。你有权控制的数控节点:${mine.map(b => b.nodeId).join(', ')}。`
|
|
303
|
+
: '你尚未绑定任何数控节点,无权下发控制指令。请在数字孪生界面绑定数控节点。',
|
|
304
|
+
isError: true,
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const node = getDcwController().byId(param.nodeId)
|
|
308
|
+
if (!node) {
|
|
309
|
+
repo.removeAgentNode(agentId, param.nodeId, 'dcw')
|
|
310
|
+
return { text: `工艺参数「${param.key}」的执行节点已不存在(可能被删除),原绑定已自动清理。`, isError: true }
|
|
311
|
+
}
|
|
312
|
+
if (!node.enabled) {
|
|
313
|
+
return { text: `工艺参数「${param.key}」的执行节点「${node.name}」已停用(控制已暂停),无法下发。`, isError: true }
|
|
314
|
+
}
|
|
315
|
+
// 手动确认模式:与 dcw_control 同源审批面,备注回给 Agent
|
|
316
|
+
if (binding.mode === 'manual') {
|
|
317
|
+
const approvals = getToolApprovals()
|
|
318
|
+
if (approvals.hasPendingFor(agentId, param.nodeId)) {
|
|
319
|
+
return { text: '你对该执行节点已有一条待审批的下发指令,请等待用户处理后再发新指令(避免审批堆积)。', isError: true }
|
|
320
|
+
}
|
|
321
|
+
const detail = `工艺参数「${param.key}」(${param.name})设定 ${value}${param.unit},${paramLimitsText(param)}`
|
|
322
|
+
const ap = await approvals.request(agentId, param.nodeId, 'dcw', detail)
|
|
323
|
+
if (!ap.approved) {
|
|
324
|
+
return { text: `指令未执行:用户${ap.comment.includes('超时') ? '未在时限内批准(超时)' : `拒绝了本次下发`}。用户备注:${ap.comment || '(无)'}` }
|
|
325
|
+
}
|
|
326
|
+
if (!repo.find(agentId, param.nodeId, 'dcw')) {
|
|
327
|
+
return { text: '指令未执行:审批通过时你的该节点绑定已被解除(权限在批准时失效)。', isError: true }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
const meta = {
|
|
332
|
+
source: 'agent' as const,
|
|
333
|
+
actor: agentId,
|
|
334
|
+
actorName: agentBadgeLabel(agentId),
|
|
335
|
+
taskId: args.task_id ? String(args.task_id) : undefined,
|
|
336
|
+
hypothesis: args.hypothesis ? String(args.hypothesis) : '',
|
|
337
|
+
}
|
|
338
|
+
const outcome = await getDcwController().writeParam(param.id, value, meta)
|
|
339
|
+
if (outcome.ok) {
|
|
340
|
+
const stable = getRecipeRollBackManager().journal({ nodeId: param.nodeId, limit: 10 }).find(a => a.prevValue != null && a.prevValue !== a.newValue)
|
|
341
|
+
const loopTxt = [
|
|
342
|
+
outcome.recordId ? `优化记录 ${outcome.recordId} 已开窗(观察数采后 dcw_judge 落判定)` : null,
|
|
343
|
+
stable ? `上一稳定锚:${stable.prevValue}${param.unit}(可 dcw_rollback 回退)` : null,
|
|
344
|
+
].filter(Boolean).join(';')
|
|
345
|
+
return {
|
|
346
|
+
text: `下发成功:工艺参数「${param.key}」(${param.name})设定 ${value}${param.unit} → 执行节点「${node.name}」;回读 ${outcome.readback != null ? `${outcome.readback}${param.unit}` : '不支持'}一致。${paramLimitsText(param)}。${outcome.message}${loopTxt ? `\n[调控闭环] ${loopTxt}` : ''}`,
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return { text: `下发失败:${outcome.message}(工艺参数 ${param.key},执行节点「${node.name}」;${paramLimitsText(param)};当前设定值保持 ${node.value ?? '原值'}${param.unit} 未被改动)`, isError: true }
|
|
350
|
+
}
|
|
351
|
+
catch (err) {
|
|
352
|
+
const msg = err instanceof Error ? err.message : String(err)
|
|
353
|
+
return { text: `下发被拒绝:${msg}(工艺参数 ${param.key};${paramLimitsText(param)})`, isError: true }
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** 工具:param_read —— 按工艺参数读取 PLC 当前值(被动观测免审批) */
|
|
358
|
+
export async function toolParamRead(agentId: string, args: {
|
|
359
|
+
param?: string
|
|
360
|
+
line_id?: string
|
|
361
|
+
}): Promise<{ text: string, isError?: boolean }> {
|
|
362
|
+
const resolved = resolveParamRef(String(args.param ?? ''), args.line_id ? String(args.line_id) : undefined)
|
|
363
|
+
if (!resolved.ok) return resolved
|
|
364
|
+
const param = resolved.param
|
|
365
|
+
const repo = getAgentNodeBindingRepo()
|
|
366
|
+
if (!repo.find(agentId, param.nodeId, 'dcw')) {
|
|
367
|
+
const mine = repo.byAgent(agentId).filter(b => b.kind === 'dcw')
|
|
368
|
+
return {
|
|
369
|
+
text: mine.length
|
|
370
|
+
? `无权读取工艺参数「${param.key}」(执行节点 ${param.nodeId} 未绑定给你)。你有权读取的数控节点:${mine.map(b => b.nodeId).join(', ')}。`
|
|
371
|
+
: '你尚未绑定任何数控节点,无权读取控制通道数据。请在数字孪生界面绑定数控节点。',
|
|
372
|
+
isError: true,
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const node = getDcwController().byId(param.nodeId)
|
|
376
|
+
if (!node) {
|
|
377
|
+
repo.removeAgentNode(agentId, param.nodeId, 'dcw')
|
|
378
|
+
return { text: `工艺参数「${param.key}」的执行节点已不存在(可能被删除),原绑定已自动清理。`, isError: true }
|
|
379
|
+
}
|
|
380
|
+
try {
|
|
381
|
+
const read = await getDcwController().readParam(param.id)
|
|
382
|
+
if (!read.ok && read.value == null && !node.readValue) {
|
|
383
|
+
return { text: `读取失败:${read.message}(执行节点「${node.name}」驱动 ${node.driver} 可能不支持读取;可改用 daq_query 查关联数采通道)`, isError: true }
|
|
384
|
+
}
|
|
385
|
+
const readTxt = read.value != null
|
|
386
|
+
? `${Number(read.value.toFixed(param.decimals))}${param.unit} @ ${read.at.slice(11, 19)}`
|
|
387
|
+
: (node.readValue != null ? `${node.readValue}${param.unit}(最近一次)` : '无读数')
|
|
388
|
+
return {
|
|
389
|
+
text: `读取成功:工艺参数「${param.key}」(${param.name})\n PLC 读数(ACT): ${readTxt}\n 当前设定(SET): ${node.value != null ? `${node.value}${param.unit}` : '从未下发'}\n ${paramLimitsText(param)}`,
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
return { text: `读取被拒绝:${err instanceof Error ? err.message : String(err)}(工艺参数 ${param.key})`, isError: true }
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
239
397
|
/**
|
|
240
398
|
* 数采目标集解析(工具共用鉴权面):Agent 绑定(kind=daq)为权限边界 ——
|
|
241
399
|
* node_id/line_id 只能缩小范围,不能放大(越权节点一律拒绝)。
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 与 codex/dsh/opencode impl 全引擎一致。协议权威:omp://rpc.md。
|
|
19
19
|
*/
|
|
20
20
|
import { createLogger } from '../logger'
|
|
21
|
-
import { BaseAgentImpl } from './base-agent'
|
|
21
|
+
import { BaseAgentImpl, type BaseAgentConfigView } from './base-agent'
|
|
22
22
|
import { randomUUID } from 'node:crypto'
|
|
23
23
|
import type {
|
|
24
24
|
AgentEvent,
|
|
@@ -133,8 +133,8 @@ export class OmpRpcAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
133
133
|
return 'omp'
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
protected configRecord():
|
|
137
|
-
return this.config
|
|
136
|
+
protected configRecord(): BaseAgentConfigView {
|
|
137
|
+
return this.config
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
/**
|
|
@@ -205,7 +205,9 @@ export class OmpRpcAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
205
205
|
/** 当前回合产生的 assistant 文本(供诊断) */
|
|
206
206
|
private turnText = ''
|
|
207
207
|
/** agent 身份信息(factory 注入;无需等待 init()) */
|
|
208
|
-
|
|
208
|
+
// agentRole 由 BaseAgentImpl 持有(protected);同名私有声明会遮蔽基类 identity 角色。
|
|
209
|
+
// 仅收窄可见性声明,运行时代码不变(构造函数与 ensureClient 仍显式同步)。
|
|
210
|
+
protected override agentRole: 'lead' | 'worker' = 'worker'
|
|
209
211
|
|
|
210
212
|
// ===== 上下文治理(70% 无中断压缩环)=====
|
|
211
213
|
/** 压缩进行中(平台 gate 与 omp 原生压缩共用互斥位) */
|
|
@@ -421,7 +423,7 @@ export class OmpRpcAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
421
423
|
|
|
422
424
|
// ===== 生命周期 =====
|
|
423
425
|
|
|
424
|
-
async init(input: { agent: AgentInfo, channelId: string }): Promise<void> {
|
|
426
|
+
override async init(input: { agent: AgentInfo, channelId: string }): Promise<void> {
|
|
425
427
|
this.agentInfo = input.agent
|
|
426
428
|
this.channelId = input.channelId
|
|
427
429
|
this.agentName = input.agent.name
|
|
@@ -550,10 +552,13 @@ export class OmpRpcAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
550
552
|
|
|
551
553
|
// ===== supervise() =====
|
|
552
554
|
|
|
553
|
-
/**
|
|
554
|
-
|
|
555
|
+
/**
|
|
556
|
+
* supervise 单飞守卫:同一 client 不并发 LLM 回合(残留回合与下一 prompt 混流的根因)。
|
|
557
|
+
* 守卫位由 BaseAgentImpl 的 protected supervising 承载 —— 本类原先的私有重复声明与基类构成
|
|
558
|
+
* "两个私有声明"(TS2415),而 JS 只有一个实例字段,故删除后语义与运行时完全一致。
|
|
559
|
+
*/
|
|
555
560
|
|
|
556
|
-
async supervise(snapshot: SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<SupervisionDecision[]> {
|
|
561
|
+
override async supervise(snapshot: SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<SupervisionDecision[]> {
|
|
557
562
|
await this.ensureClient(ctx)
|
|
558
563
|
if (!this.client) return []
|
|
559
564
|
if (this.supervising) return [] // 上一轮 supervise 未收口:跳过本拍(节流即正确)
|
|
@@ -1109,7 +1114,8 @@ export class OmpRpcAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
1109
1114
|
const client = new OmpRpcClient({
|
|
1110
1115
|
command,
|
|
1111
1116
|
mode: this.rpcMode,
|
|
1112
|
-
args
|
|
1117
|
+
// 重复键 args 的生效者是下一行(JS 对象字面量后写覆盖先写):保留生效语义,删除被覆盖项。
|
|
1118
|
+
// (原 ['--thinking', level] 从未真正传给 omp —— 见报告"未修的缺陷"一节。)
|
|
1113
1119
|
args: this.config.args,
|
|
1114
1120
|
cwd: this.config.cwd ?? process.cwd(),
|
|
1115
1121
|
// 进程退出 → 注册表标记(供运行时资源监控);pid=-1 表示无法取得,忽略
|
|
@@ -32,7 +32,7 @@ import { extractJsonArray, peerPrompt, supervisePrompt, systemManual, toolArgsPr
|
|
|
32
32
|
import { getHitlRegistry } from './hitl-registry'
|
|
33
33
|
import { harnessSettings } from '../settings'
|
|
34
34
|
import { spawnLineProcess } from './adapters/line-spawn'
|
|
35
|
-
import { BaseAgentImpl } from './base-agent'
|
|
35
|
+
import { BaseAgentImpl, type BaseAgentConfigView } from './base-agent'
|
|
36
36
|
import { resolveBridgePath, resolvePlatformBaseUrl } from './harness-env'
|
|
37
37
|
|
|
38
38
|
const log = createLogger('workshop.opencode')
|
|
@@ -152,7 +152,7 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
152
152
|
return 'opencode'
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
protected configRecord():
|
|
155
|
+
protected configRecord(): BaseAgentConfigView {
|
|
156
156
|
return this.config
|
|
157
157
|
}
|
|
158
158
|
|
|
@@ -222,7 +222,7 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
/** HITL 应答(codex/opencode/dsh 统一入口;本 impl 处理 opencode-permission) */
|
|
225
|
-
async respondHitl(kind: string, id: string, outcome: {
|
|
225
|
+
override async respondHitl(kind: string, id: string, outcome: {
|
|
226
226
|
confirmed?: boolean
|
|
227
227
|
cancelled?: boolean
|
|
228
228
|
value?: string
|
|
@@ -247,7 +247,9 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
247
247
|
await this.api('POST', `/question/${encodeURIComponent(id)}/reply`, { answer: outcome.value ?? outcome.comment ?? '' })
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
|
-
|
|
250
|
+
// 原为 clearTimeout(p.timer):p 在本作用域不存在(ReferenceError,且仅当计时器非空时触发),
|
|
251
|
+
// 该待办条目在此处就是 pending(与 dsh/codex/hermes 的同名分支写法一致)。
|
|
252
|
+
if (pending.timer) clearTimeout(pending.timer)
|
|
251
253
|
this.pendingHitl.delete(id)
|
|
252
254
|
getHitlRegistry().resolve(kind, id, cancelled ? 'cancelled' : 'answered')
|
|
253
255
|
}
|
|
@@ -273,9 +275,9 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
// supervising 由 BaseAgentImpl 持有(protected):同名私有声明会与基类形成"两个私有声明"(TS2415)。
|
|
277
279
|
|
|
278
|
-
async supervise(snapshot: SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<SupervisionDecision[]> {
|
|
280
|
+
override async supervise(snapshot: SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<SupervisionDecision[]> {
|
|
279
281
|
// 引擎/会话不可用 → 本轮监督降级为空(调度器回退规则引擎);绝不让引擎故障
|
|
280
282
|
// 以 unhandledRejection 形态逃逸(dev-stability-guard 会据此杀掉整个服务端)
|
|
281
283
|
try {
|
|
@@ -296,16 +298,22 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
296
298
|
memory: ctx.memory,
|
|
297
299
|
})
|
|
298
300
|
const timeoutMs = this.config.superviseTimeoutMs ?? 150_000
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
301
|
+
// runTurn 是 async generator(返回 AsyncGenerator,不是 Promise),必须以异步迭代消费完整个回合。
|
|
302
|
+
// (原实现写 .then(...)/.catch(...):运行时是 "then is not a function" 的 TypeError,supervise 整条路径实际不可用。)
|
|
303
|
+
try {
|
|
304
|
+
const events: AgentEvent[] = []
|
|
305
|
+
for await (const e of this.runTurn(prompt, undefined, {
|
|
306
|
+
timeoutMs,
|
|
307
|
+
signal: opts?.signal,
|
|
308
|
+
onDone: async () => {
|
|
309
|
+
this.supervising = false
|
|
310
|
+
},
|
|
311
|
+
beforeStart: () => {
|
|
312
|
+
this.supervising = true
|
|
313
|
+
},
|
|
314
|
+
})) {
|
|
315
|
+
events.push(e)
|
|
316
|
+
}
|
|
309
317
|
// 从事件流提取最终文本 → JSON 决策兜底(工具直执行路径返回空)
|
|
310
318
|
let text = ''
|
|
311
319
|
for (const e of events) {
|
|
@@ -315,10 +323,21 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
315
323
|
}
|
|
316
324
|
const parsed = extractJsonArray(text)
|
|
317
325
|
return parsed && parsed.length > 0 ? parsed as SupervisionDecision[] : []
|
|
318
|
-
}
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
319
328
|
this.supervising = false
|
|
320
329
|
return []
|
|
321
|
-
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** supervise 用:收齐整个回合的事件(基类抽象成员;本类 supervise 自行消费并需 beforeStart/onDone 钩子) */
|
|
334
|
+
protected async collectTurnEvents(prompt: string, timeoutMs: number, signal?: AbortSignal): Promise<AgentEvent[]> {
|
|
335
|
+
const events: AgentEvent[] = []
|
|
336
|
+
for await (const e of this.runTurn(prompt, undefined, { timeoutMs, signal })) {
|
|
337
|
+
events.push(e)
|
|
338
|
+
if (e.kind === 'error') break
|
|
339
|
+
}
|
|
340
|
+
return events
|
|
322
341
|
}
|
|
323
342
|
|
|
324
343
|
protected async* workerTurn(request: AgentRunRequest, ctx: AgentRunContext): AsyncGenerator<AgentEvent, void, unknown> {
|
|
@@ -800,10 +819,17 @@ export class OpenCodeAgentImpl extends BaseAgentImpl implements AgentInterface {
|
|
|
800
819
|
}
|
|
801
820
|
const createWith = async (extra: Record<string, unknown> | undefined): Promise<Record<string, unknown>> =>
|
|
802
821
|
this.api('POST', '/session', { ...body, ...(extra ?? {}) })
|
|
803
|
-
|
|
822
|
+
// 历史实现写作 `await (cond) ? a : b`:await 只作用于条件,整个三元表达式的结果是**未 await** 的
|
|
823
|
+
// Promise,故 created?.id 恒为 undefined → sessionId 恒为 String(undefined ?? '') === '' →
|
|
824
|
+
// 必然落到下面的 2.5s 重试循环(真正被使用的会话来自重试那次 createWith(undefined))。
|
|
825
|
+
// 此处逐字保留该运行时语义:同样的 await 让出一次微任务、同样的请求照发、首次结果同样丢弃。
|
|
826
|
+
// 直白的修法是给整个三元表达式加括号 await(会用上带 permission 的首次会话、省掉 2.5s 重试),
|
|
827
|
+
// 但那会改变 opencode 会话的权限策略与启动时序,故本次不改 —— 见报告"未修的缺陷"一节。
|
|
828
|
+
const firstAttempt = await (this.config.permission ?? DEFAULT_PERMISSION)
|
|
829
|
+
void (firstAttempt
|
|
804
830
|
? createWith({ permission: this.config.permission ?? DEFAULT_PERMISSION }).catch(() => createWith(undefined))
|
|
805
|
-
: createWith(undefined)
|
|
806
|
-
this.sessionId =
|
|
831
|
+
: createWith(undefined))
|
|
832
|
+
this.sessionId = ''
|
|
807
833
|
if (!this.sessionId) {
|
|
808
834
|
// 瞬态失败(实例刚起/内部分配竞态/权限规则不兼容)→ 无附加字段重试,最多 3 次
|
|
809
835
|
for (let i = 0; i < 3 && !this.sessionId; i++) {
|
|
@@ -27,7 +27,7 @@ import type {
|
|
|
27
27
|
} from './agent-interface'
|
|
28
28
|
import type { AgentContextStats } from '../types/task'
|
|
29
29
|
import { markHarnessProcessExit, registerHarnessProcess, bindHarnessProcess, killHarnessProcess } from './harness-process'
|
|
30
|
-
import { peerPrompt, systemManual, toolArgsPreview, workerPrompt } from './prompt-builder'
|
|
30
|
+
import { extractJsonArray, peerPrompt, supervisePrompt, systemManual, toolArgsPreview, workerPrompt } from './prompt-builder'
|
|
31
31
|
import { getHitlRegistry } from './hitl-registry'
|
|
32
32
|
import { harnessSettings } from '../settings'
|
|
33
33
|
import { StdioJsonRpcClient, type JsonRpcRequestIncoming } from './adapters/stdio-jsonrpc'
|
|
@@ -111,7 +111,9 @@ export interface QwenAgentConfig {
|
|
|
111
111
|
export class QwenAgentImpl extends BaseAgentImpl {
|
|
112
112
|
private readonly config: QwenAgentConfig
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
// agentRole 由 BaseAgentImpl 持有(protected);同名私有声明会遮蔽基类 identity 角色。
|
|
115
|
+
// 仅收窄可见性声明,运行时代码不变。
|
|
116
|
+
protected override agentRole: 'lead' | 'worker' = 'worker'
|
|
115
117
|
private client: StdioJsonRpcClient | null = null
|
|
116
118
|
private clientStarting: Promise<void> | null = null
|
|
117
119
|
private turnActive = false
|
|
@@ -177,7 +179,7 @@ export class QwenAgentImpl extends BaseAgentImpl {
|
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
/** HITL 应答:requestToolCallConfirmation → outcome allow/reject/cancel(fail-closed) */
|
|
180
|
-
async respondHitl(kind: string, id: string, outcome: {
|
|
182
|
+
override async respondHitl(kind: string, id: string, outcome: {
|
|
181
183
|
confirmed?: boolean
|
|
182
184
|
cancelled?: boolean
|
|
183
185
|
}): Promise<void> {
|
|
@@ -202,7 +204,7 @@ export class QwenAgentImpl extends BaseAgentImpl {
|
|
|
202
204
|
|
|
203
205
|
// ===== run / supervise =====
|
|
204
206
|
|
|
205
|
-
async supervise(snapshot: import('./agent-interface').SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<import('./agent-interface').SupervisionDecision[]> {
|
|
207
|
+
override async supervise(snapshot: import('./agent-interface').SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<import('./agent-interface').SupervisionDecision[]> {
|
|
206
208
|
await this.ensureClient(ctx)
|
|
207
209
|
if (!this.client || !this.sessionStarted) return []
|
|
208
210
|
if (this.supervising) return []
|
|
@@ -216,7 +218,10 @@ export class QwenAgentImpl extends BaseAgentImpl {
|
|
|
216
218
|
})
|
|
217
219
|
this.supervising = true
|
|
218
220
|
try {
|
|
219
|
-
|
|
221
|
+
// 原为 this.collectTurn(...):该类唯一存在的整回合收集实现是 collectTurnEvents
|
|
222
|
+
// (与基类 supervise 调用的同名抽象成员同签名)。原调用在运行时抛 TypeError 并被
|
|
223
|
+
// 本方法的 catch 吞掉 → supervise 恒返回 [],详见报告。
|
|
224
|
+
const events = await this.collectTurnEvents(prompt, this.config.superviseTimeoutMs ?? 150_000, opts?.signal)
|
|
220
225
|
let text = ''
|
|
221
226
|
for (const e of events) {
|
|
222
227
|
if (e.kind === 'artifact') {
|
|
@@ -72,7 +72,9 @@ export function inventory(): AmlInventory {
|
|
|
72
72
|
kind: EntityIssue['kind'],
|
|
73
73
|
rows: Array<{ id: string, path?: string }>,
|
|
74
74
|
baseDir: string,
|
|
75
|
-
contract
|
|
75
|
+
// 非空契约列表:三个调用点都传字面量,且下面按"多选一"语义读 contract[0] 作展示路径,
|
|
76
|
+
// 用非空元组表达"至少一项"这一既有前提(纯类型,运行时零变化)
|
|
77
|
+
contract: readonly [string, ...string[]],
|
|
76
78
|
): number => {
|
|
77
79
|
const ids = new Set(rows.map(r => r.id))
|
|
78
80
|
for (const r of rows) {
|
|
@@ -362,7 +362,8 @@ export async function installUv(rt: AmlRuntime, onLog?: ProgressFn): Promise<{ o
|
|
|
362
362
|
const hit = findUvInDir(rt.toolsDir)
|
|
363
363
|
if (hit) {
|
|
364
364
|
const v = await runCapture(hit, ['--version'], 15_000)
|
|
365
|
-
|
|
365
|
+
// 运行时 `''.split('\n')[0] === ''`,首行恒存在;?? '' 只是 noUncheckedIndexedAccess 下的写法
|
|
366
|
+
const version = (v.out || v.err).trim().split('\n')[0] ?? ''
|
|
366
367
|
writeUvRecord(rt, { uvPath: hit, version, installedAt: new Date().toISOString(), installDir: rt.toolsDir, method: 'official-script' })
|
|
367
368
|
resetProbeCache()
|
|
368
369
|
emit(`安装成功:${version} @ ${hit}`)
|
|
@@ -390,7 +391,7 @@ export async function installUv(rt: AmlRuntime, onLog?: ProgressFn): Promise<{ o
|
|
|
390
391
|
}
|
|
391
392
|
catch { /* Windows 无 x 位 */ }
|
|
392
393
|
const v = await runCapture(hit, ['--version'], 15_000)
|
|
393
|
-
const version = (v.out || v.err).trim().split('\n')[0]
|
|
394
|
+
const version = (v.out || v.err).trim().split('\n')[0] ?? ''
|
|
394
395
|
writeUvRecord(rt, { uvPath: hit, version, installedAt: new Date().toISOString(), installDir: rt.toolsDir, method: 'pip-target' })
|
|
395
396
|
resetProbeCache()
|
|
396
397
|
emit(`安装成功:${version} @ ${hit}`)
|
|
@@ -25,6 +25,10 @@ const TOPIC_WILDCARD = `${TOPIC_ROOT}/+/sample`
|
|
|
25
25
|
/** 断连离线缓冲上限(满丢最旧;补发帧按消费侧乱序防御自然去重) */
|
|
26
26
|
const OFFLINE_CAP = 2000
|
|
27
27
|
|
|
28
|
+
/** MQTT QoS 协议取值(0/1/2;shared/config/schema.json 的 daq.mqtt.qos 声明 min 0 / max 2)。
|
|
29
|
+
* settings 面(settings.ts)把该配置读成 number,这里按协议收窄 —— 运行时原值透传,不做钳制/兜底。 */
|
|
30
|
+
type MqttQos = 0 | 1 | 2
|
|
31
|
+
|
|
28
32
|
export class MqttQueueAdapter implements DaqQueuePort {
|
|
29
33
|
readonly backend = 'mqtt' as const
|
|
30
34
|
private client: MqttClient | null = null
|
|
@@ -48,7 +52,7 @@ export class MqttQueueAdapter implements DaqQueuePort {
|
|
|
48
52
|
const mod = requireMqtt('mqtt') as unknown as { connect: (url: string, opts?: Record<string, unknown>) => MqttClient }
|
|
49
53
|
// 凭据/QoS/TLS 配置驱动(daq.mqtt.*;legacy DAQ_MQTT_* env 别名兼容,DAQ_MQTT_URL 整串覆盖仍最高优先)
|
|
50
54
|
const mqttCfg = daqRuntimeSettings().mqtt
|
|
51
|
-
const qos = mqttCfg.qos
|
|
55
|
+
const qos = mqttCfg.qos as MqttQos
|
|
52
56
|
const opts: Record<string, unknown> = {
|
|
53
57
|
clientId: `aw-daq-${process.pid}-${Math.random().toString(36).slice(2, 6)}`,
|
|
54
58
|
reconnectPeriod: 2000,
|
|
@@ -99,7 +103,7 @@ export class MqttQueueAdapter implements DaqQueuePort {
|
|
|
99
103
|
return
|
|
100
104
|
}
|
|
101
105
|
this.published++
|
|
102
|
-
this.client.publish(TOPIC_SAMPLE(env.nodeId), JSON.stringify(env), { qos: daqRuntimeSettings().mqtt.qos })
|
|
106
|
+
this.client.publish(TOPIC_SAMPLE(env.nodeId), JSON.stringify(env), { qos: daqRuntimeSettings().mqtt.qos as MqttQos })
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
consume(fn: DaqConsumer): () => void {
|
|
@@ -123,8 +127,8 @@ export class MqttQueueAdapter implements DaqQueuePort {
|
|
|
123
127
|
// end() 回调在某些断连路径下不触发,旧 client 的 connect/message/error 监听器
|
|
124
128
|
// 会连同 socket 一起滞留(client 对象被闭包引用,GC 不可达)。
|
|
125
129
|
// rebuildDaqQueue 反复换装时会累积;显式摘除是唯一确定性的清理点。
|
|
126
|
-
try {
|
|
127
|
-
c.removeAllListeners()
|
|
130
|
+
try {
|
|
131
|
+
c.removeAllListeners()
|
|
128
132
|
}
|
|
129
133
|
catch { /* 已销毁等场景:尽力而为 */ }
|
|
130
134
|
}
|
|
@@ -106,6 +106,16 @@ export interface DaqPatchInput {
|
|
|
106
106
|
|
|
107
107
|
type BroadcastFn = (type: string, payload: unknown) => void
|
|
108
108
|
|
|
109
|
+
/** 有界 LRU 的最小泛型面:shared/lru.mjs 是 allowJs 推断出的**非泛型**类(JS 里没有 @template),
|
|
110
|
+
* 直接 `new LruMap<K, V>()` 无处安放类型参数。这里按实际使用面(get/set/delete/size)声明键值类型,
|
|
111
|
+
* 调用点即可拿到准确的读写类型;运行时仍是同一个 LruMap(纯类型声明,零运行时差异)。 */
|
|
112
|
+
interface LruLike<K, V> {
|
|
113
|
+
readonly size: number
|
|
114
|
+
get(key: K): V | undefined
|
|
115
|
+
set(key: K, value: V): unknown
|
|
116
|
+
delete(key: K): unknown
|
|
117
|
+
}
|
|
118
|
+
|
|
109
119
|
/** TSDB 批量写窗口(ms):消费端攒批再落盘 */
|
|
110
120
|
const TSDB_FLUSH_MS = 500
|
|
111
121
|
/** TSDB 攒批缓冲上限(背压:满则丢最旧并计数,防慢库拖爆内存) */
|
|
@@ -416,7 +426,9 @@ class DaqController {
|
|
|
416
426
|
// 指标阈值告警(模板 metrics 规则;alarm 硬限边沿 → 既有告警链路)
|
|
417
427
|
this.evaluateMetricAlarms(node, tpl, metrics)
|
|
418
428
|
if (!allowPublish) return
|
|
419
|
-
|
|
429
|
+
// lineId 是 WS 逐产线扇出的依据(scene-events.payloadLineId 读的就是 payload.lineId,
|
|
430
|
+
// 与 AepDaqReading.lineId 同义);AepDaqFrame 协议类型漏了该字段 —— 见报告。
|
|
431
|
+
const payload: AepDaqFrame & { lineId: string | null } = {
|
|
420
432
|
nodeId: node.id,
|
|
421
433
|
templateRef: node.templateRef,
|
|
422
434
|
kind: f.kind,
|
|
@@ -694,7 +706,7 @@ class DaqController {
|
|
|
694
706
|
|
|
695
707
|
/** 同绑定 siblings 缓存(1s TTL):回写热路径不再逐样本全量 scan,O(N²)→O(N)/周期。
|
|
696
708
|
* 用有界 LRU 而非「超 500 整体 clear()」——后者会造成周期性全量缓存穿透。 */
|
|
697
|
-
private siblingsCache
|
|
709
|
+
private siblingsCache: LruLike<string, { at: number, list: DaqNode[] }> = new LruMap(500)
|
|
698
710
|
|
|
699
711
|
private siblingsOf(bindingId: string): DaqNode[] {
|
|
700
712
|
const hit = this.siblingsCache.get(bindingId)
|
|
@@ -759,7 +771,10 @@ class DaqController {
|
|
|
759
771
|
this.broadcast = fn
|
|
760
772
|
}
|
|
761
773
|
|
|
762
|
-
|
|
774
|
+
/** minIntervalMs / alarmsRaised / framesStored 都是本方法**实际返回**的字段,但 AepDaqControllerState
|
|
775
|
+
* 未收录(协议类型与实现漂移):minIntervalMs 被前端 useDaqStream 消费,alarmsRaised 被
|
|
776
|
+
* server/api/metrics.ts 消费(framesStored 供管线指标展示)。这里按实现补齐返回面 —— 见报告。 */
|
|
777
|
+
controllerState(): AepDaqControllerState & { minIntervalMs: number, alarmsRaised: number, framesStored: number, produced?: number, consumed?: number, dropped?: number, samplesStored?: number, tsdbDropped?: number } {
|
|
763
778
|
// 丢弃 = 队列层真实丢弃(inproc 拥塞/mqtt 断连)+ 消费侧乱序迟到帧(诚实可见)
|
|
764
779
|
const queueLost = g_queueLost()
|
|
765
780
|
// 单次遍历(hardening PERF-1):status 高频路径不再对全表多次 all()
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { applyTransform } from '../../../../shared/daq-protocol'
|
|
13
|
-
import { classifyCommError } from './drivers'
|
|
13
|
+
import { classifyCommError, type DaqFrameSample } from './drivers'
|
|
14
14
|
import type { DaqNode } from './daq-node'
|
|
15
|
-
import type {
|
|
15
|
+
import type { DaqSampleEnvelope } from './bus/queue-port'
|
|
16
16
|
|
|
17
17
|
/** 驱动故障广播节流(ms;每运行时独立计时) */
|
|
18
18
|
const ERR_THROTTLE_MS = 30_000
|
|
@@ -94,7 +94,9 @@ export class DaqNodeRuntime {
|
|
|
94
94
|
if (now < this.lastSampleAt + node.effectiveInterval(defs.intervalMs, defs.minIntervalMs)) return
|
|
95
95
|
this.sampling = true
|
|
96
96
|
try {
|
|
97
|
-
|
|
97
|
+
// 生产面可能返回三种形态:标量 / 驱动原生帧(DaqFrameSample)/ 生产侧已剥离 blob 的帧信封
|
|
98
|
+
// (与 DaqRuntimeHost.sample 的返回面一致 —— 后者不能丢,否则帧信封分支拿不到 kind/points)
|
|
99
|
+
let v: number | DaqFrameSample | { frame: NonNullable<DaqSampleEnvelope['frame']> } | null = null
|
|
98
100
|
try {
|
|
99
101
|
v = await this.host.sample(node, now)
|
|
100
102
|
}
|