agentworkshop 0.7.40 → 0.7.44

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.
Files changed (327) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/B8uy9iRW.js +1 -0
  3. package/.output/public/_nuxt/BGTYYQH-.js +1 -0
  4. package/.output/public/_nuxt/BUmHEJ77.js +2 -0
  5. package/.output/public/_nuxt/BY7YrV_D.js +1 -0
  6. package/.output/public/_nuxt/Bqcgz95s.js +18 -0
  7. package/.output/public/_nuxt/C7UlqPeD.js +1 -0
  8. package/.output/public/_nuxt/CTmDn-YP.js +1 -0
  9. package/.output/public/_nuxt/Cs8pVeVG.js +1 -0
  10. package/.output/public/_nuxt/{DcsCcxp4.js → D98NH8kG.js} +1 -1
  11. package/.output/public/_nuxt/DKySmNPI.js +14 -0
  12. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  13. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  14. package/.output/public/_nuxt/{C_iYD-EB.js → EHlEMRii.js} +1 -1
  15. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  16. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  17. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  18. package/.output/public/_nuxt/{DZshyNLa.js → IREZ1eC2.js} +1 -1
  19. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  20. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  21. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  22. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  23. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  24. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  25. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  26. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  27. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  28. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  29. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  30. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  31. package/.output/public/_nuxt/builds/latest.json +1 -1
  32. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  33. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  34. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  35. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  36. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  37. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  38. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  39. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  40. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  41. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  42. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  43. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  44. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  45. package/.output/server/chunks/_/nitro.mjs +1058 -830
  46. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  47. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  48. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  49. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs → TownView-CJ6IsDCc.mjs} +229 -228
  50. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  51. package/.output/server/chunks/build/{_id_-BU1wfOID.mjs → _id_-CVD_H0ir.mjs} +149 -147
  52. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  53. package/.output/server/chunks/build/{_id_-BYsEua57.mjs → _id_-CtxMb3qp.mjs} +47 -46
  54. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  55. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs → _wsId_-DpY3T-md.mjs} +516 -446
  56. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  58. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  60. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  61. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  62. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  63. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  64. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  65. package/.output/server/chunks/build/{daq-cgyjKmJu.mjs → daq-DWWSKGAV.mjs} +95 -93
  66. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  67. package/.output/server/chunks/build/{dcw-CoTxBlAZ.mjs → dcw-CT8k17_E.mjs} +46 -45
  68. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  69. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  70. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs → logs--dByNyhw.mjs} +2 -2
  72. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  74. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{pages-DFxjn9Xa.mjs → pages-BHcSBM2D.mjs} +26 -20
  76. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  77. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  78. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  79. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  80. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  81. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  82. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  83. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  84. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  85. package/.output/server/chunks/build/{town-qMPql9Se.mjs → town-QJWB5wng.mjs} +5 -4
  86. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  87. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  88. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  89. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  90. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  91. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  92. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  93. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  108. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  109. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +3 -1
  110. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  111. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  116. package/.output/server/chunks/routes/renderer.mjs +2 -2
  117. package/.output/server/chunks/virtual/entry.mjs +639 -88
  118. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  119. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  120. package/.output/server/package.json +1 -1
  121. package/README-zh.md +16 -6
  122. package/README.md +17 -7
  123. package/app/components/AppHeader.vue +961 -959
  124. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  125. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  126. package/app/components/workshop/AgentLanesView.vue +998 -998
  127. package/app/components/workshop/ArtifactCard.vue +120 -120
  128. package/app/components/workshop/AssetLibrary.vue +452 -452
  129. package/app/components/workshop/ChannelSessionList.vue +812 -804
  130. package/app/components/workshop/CommandPalette.vue +269 -269
  131. package/app/components/workshop/Composer.vue +827 -827
  132. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  133. package/app/components/workshop/EventBlock.vue +602 -602
  134. package/app/components/workshop/FileSelectorModal.vue +188 -188
  135. package/app/components/workshop/InspectorPanel.vue +301 -301
  136. package/app/components/workshop/MemoryPanel.vue +364 -364
  137. package/app/components/workshop/MultiChannelView.vue +189 -189
  138. package/app/components/workshop/TaskBoardView.vue +686 -686
  139. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  140. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  141. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  142. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  143. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  144. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  145. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  146. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  147. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  148. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  149. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  150. package/app/components/workshop/town/TownView.vue +56 -56
  151. package/app/composables/workshop/useDaqStream.ts +7 -4
  152. package/app/composables/workshop/useDcwStream.ts +8 -2
  153. package/app/middleware/locale-cookie.global.ts +22 -0
  154. package/app/pages/aml/index.vue +24 -2
  155. package/app/pages/daq/[id].vue +20 -16
  156. package/app/pages/daq/index.vue +2310 -2307
  157. package/app/pages/dcw/[id].vue +26 -23
  158. package/app/pages/dcw/index.vue +3 -3
  159. package/app/pages/index.vue +987 -981
  160. package/app/pages/plugins/index.vue +317 -311
  161. package/app/pages/settings.vue +1564 -1562
  162. package/app/pages/tokens.vue +15 -15
  163. package/app/pages/workshop/agents.vue +612 -609
  164. package/app/pages/workshop/channel-templates.vue +18 -11
  165. package/app/pages/workshop/index.vue +668 -668
  166. package/app/pages/workshop/teams.vue +743 -740
  167. package/app/pages/workshop/w/[wsId].vue +704 -704
  168. package/app/plugins/locale-restore.client.ts +16 -1
  169. package/app/utils/builtin-catalog.ts +104 -0
  170. package/config.yml +170 -170
  171. package/docs/cli.en.md +2 -2
  172. package/docs/cli.md +2 -2
  173. package/docs/full-test-plan.md +2 -3
  174. package/docs/plugins.en.md +33 -1
  175. package/docs/plugins.md +29 -1
  176. package/docs/sdk.en.md +1 -1
  177. package/docs/sdk.md +1 -1
  178. package/i18n/locales/en.ts +293 -35
  179. package/i18n/locales/zh-CN.ts +265 -7
  180. package/package.json +4 -3
  181. package/scripts/_dbg-perms-e2e.mjs +132 -109
  182. package/scripts/_demo-agentteam-capture.mjs +278 -0
  183. package/scripts/_e2e-ui-functional.mjs +371 -0
  184. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  185. package/scripts/_i18n-en-verify.mjs +107 -0
  186. package/scripts/_i18n-extra-checks.mjs +53 -0
  187. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  188. package/scripts/_i18n-verify-keys.mjs +50 -0
  189. package/scripts/_loop-biax-campaign.mjs +130 -0
  190. package/scripts/_sweep-button-contrast.mjs +87 -0
  191. package/scripts/test-serial-bridge.mjs +418 -0
  192. package/scripts/ui/e2e-interactive.mjs +328 -0
  193. package/scripts/ui/record-demo.mjs +557 -0
  194. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  195. package/server/api/workshop/daq/index.get.ts +3 -1
  196. package/server/api/workshop/dcw/index.get.ts +3 -0
  197. package/server/plugins/aw-plugins.ts +9 -7
  198. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  199. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  200. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  201. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  202. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  203. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  204. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  205. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  206. package/server/services/workshop/daq/daq-controller.ts +7 -2
  207. package/server/services/workshop/daq/drivers.ts +89 -3
  208. package/server/services/workshop/dcw/dcw-controller.ts +5 -1
  209. package/server/services/workshop/dcw/drivers.ts +85 -2
  210. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  211. package/server/services/workshop/plugins/host.mjs +30 -0
  212. package/shared/daq-protocol.ts +15 -0
  213. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  214. package/.output/public/_nuxt/BOt2SP4z.js +0 -1
  215. package/.output/public/_nuxt/BP-NyKVG.js +0 -18
  216. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  217. package/.output/public/_nuxt/BsROmY89.js +0 -1
  218. package/.output/public/_nuxt/ClILjvWH.js +0 -1
  219. package/.output/public/_nuxt/CzOCSGLe.js +0 -1
  220. package/.output/public/_nuxt/D8qvkfyY.js +0 -1
  221. package/.output/public/_nuxt/DCn7QZ5N.js +0 -2
  222. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  223. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  224. package/.output/public/_nuxt/Dihnimlk.js +0 -19
  225. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  226. package/.output/public/_nuxt/Dr9v6C0f.js +0 -14
  227. package/.output/public/_nuxt/Du9ZJtnj.js +0 -1
  228. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  229. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  230. package/.output/public/_nuxt/_id_.CM4bIgKY.css +0 -1
  231. package/.output/public/_nuxt/_id_.bNV69Dtf.css +0 -1
  232. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  233. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  234. package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +0 -1
  235. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  236. package/.output/public/_nuxt/daq.B0D3dPAc.css +0 -1
  237. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  238. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  239. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  240. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  241. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  242. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  243. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  244. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  245. package/.output/server/chunks/build/_id_-BU1wfOID.mjs.map +0 -1
  246. package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +0 -1
  247. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  248. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  249. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  250. package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +0 -1
  251. package/.output/server/chunks/build/dcw-CoTxBlAZ.mjs.map +0 -1
  252. package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +0 -1
  253. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  254. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  255. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  256. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  257. package/.output/server/chunks/build/town-qMPql9Se.mjs.map +0 -1
  258. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  259. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  260. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  261. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  262. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  263. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  264. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  265. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  266. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  267. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  268. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  269. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  270. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  271. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  272. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  273. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  274. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  275. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  276. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  277. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  278. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  279. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  280. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  281. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  282. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  283. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  284. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  285. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  286. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  287. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  288. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  289. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  290. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  291. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  292. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  293. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  294. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  295. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  296. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  297. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  298. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  299. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  300. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  301. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  302. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  303. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  304. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  305. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  306. package/scripts/_dbg-minimal-omp.mjs +0 -77
  307. package/scripts/_dbg-mode-nav.mjs +0 -173
  308. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  309. package/scripts/_dbg-team-repro.mjs +0 -76
  310. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  311. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  312. package/scripts/_townview_style.css +0 -1185
  313. package/scripts/_townview_template.html +0 -1215
  314. package/server/data/agent-node-bindings.json +0 -554
  315. package/server/data/daq-templates.json +0 -16
  316. package/server/data/daqs.json +0 -7464
  317. package/server/data/dcw-lines.json +0 -1787
  318. package/server/data/dcw-products.json +0 -1626
  319. package/server/data/dcw-recipes.json +0 -4672
  320. package/server/data/dcw-rollback.json +0 -20754
  321. package/server/data/dcw-runs.json +0 -6354
  322. package/server/data/dcw-templates.json +0 -146
  323. package/server/data/dcw-writes.json +0 -15650
  324. package/server/data/dcws.json +0 -9033
  325. package/server/data/device-twins.json +0 -133
  326. package/server/data/line-runs.json +0 -322
  327. package/server/data/scene-layouts.json +0 -277
@@ -3,20 +3,18 @@
3
3
  *
4
4
  * 把本地 rag-knowledge 服务(FastAPI 后端 + Nuxt web)集成为 AgentWorkShop 的
5
5
  * 团队知识库:启动即确保「aw-industrial」知识库存在,并向 agent 注入三个工具——
6
- * kb_search(全库检索)/ kb_store(经验沉淀)/ kb_index(文档入库)。
6
+ * kb_agent(知识库 Agent 对话)——检索/入库/经验全部由知识库内部 Agent 处理。
7
7
  * 另开放 /health、/search、/experience 三个插件 API 便于运维探查。
8
8
  * 服务不可达时工具返回 isError 文本(含原因与修复建议),绝不抛异常拖垮宿主。
9
9
  */
10
10
  const KB_NAME = 'aw-industrial'
11
- const CATEGORIES = ['best_practice', 'troubleshooting', 'lesson_learned', 'optimization', 'tip', 'workflow', 'decision']
12
- const SEVERITIES = ['critical', 'important', 'normal', 'tip'] // rag-knowledge ExperienceCreate.severity 枚举
13
11
  const DEFAULT_BASE = 'http://127.0.0.1:8770' // FastAPI 后端
14
12
  const DEFAULT_WEB = 'http://127.0.0.1:6789' // Nuxt web(文档写盘)
15
13
 
16
14
  export default {
17
15
  name: 'rag-bridge',
18
- version: '1.1.0',
19
- description: 'rag-knowledge 知识库桥接:工业知识检索/经验沉淀/文档入库三工具',
16
+ version: '2.1.0',
17
+ description: 'rag-knowledge 知识库桥接 v2.1:kb_agent 对话工具(功能解耦,sync/async 双模式)+ kb_agent_status 异步结果查询',
20
18
  auth: 'user', // 平台转发层按此声明统一校验(缺省 'none' 开放)
21
19
  client: './client.mjs', // 前端面板(插件页注入;i18n 见 i18n.json)
22
20
  // 插件配置分组:插件调用平台 API 增加自己的设置分区(设置页独立成区、可折叠)。
@@ -165,157 +163,92 @@ export default {
165
163
  return null
166
164
  }
167
165
 
168
- // ================= 工具 ×3(omp host 工具,lead/worker 全员可用) =================
166
+ // ================= 工具 ×1(kb_agent —— 功能解耦的唯一入口) =================
167
+ // 外部系统不再拼装检索/入库步骤:一个对话工具把任务原话交给 rag-knowledge
168
+ // 的原生 Agent(claude SDK + QDCVR skill + kb-mcp),检索/入库/经验/图谱全部
169
+ // 由知识库内部 Agent 自主完成,直接返回最终结果。
169
170
 
170
171
  ctx.omp.registerTool({
171
- name: 'kb_search',
172
- label: '全库检索',
173
- description: '检索工业知识库(诊断报告/经验教训/操作规范),作业前先查历史经验,避免重复踩坑。',
172
+ name: 'kb_agent',
173
+ label: '知识库Agent',
174
+ description: '与 rag-knowledge 知识库的原生 Agent 对话(知识库操作唯一入口,功能解耦)。把任务原话交给它:检索问答(知识库侧自动走 QDCVR 全流程,返回带引用的可信答案)、文档入库(给出标题与完整 markdown 正文)、经验沉淀、图谱关联等,全部由知识库内部 Agent 自主处理并返回最终结果。harness/permission 一般留空(默认 claude + 最高权限)。',
174
175
  parameters: {
175
176
  type: 'object',
176
177
  properties: {
177
- query: { type: 'string', description: '检索问题(自然语言,中英文均可)' },
178
- kb_id: { type: 'string', description: '限定知识库 ID(缺省为 aw-industrial)' },
179
- top_k: { type: 'number', description: '返回条数上限(默认 5,经 stage2 精筛)' },
178
+ prompt: { type: 'string', description: '给知识库 Agent 的完整任务原话。检索:要查的问题;入库:目标知识库名(缺省 aw-industrial)+文档标题+完整 markdown 正文;经验:标题/类别/问题/解决方案' },
179
+ mode: { type: 'string', enum: ['sync', 'async'], description: '执行方式(按场景自选):sync 同步等待知识库执行完并返回结果(检索问答用,需要立刻拿到答案);async 异步——立即返回 task_id,知识库在后台完成任务,完成后可用 kb_agent_status 查询该 task 的结果(入库/经验沉淀类用,无需等待)' },
180
+ harness: { type: 'string', description: '可选:知识库侧执行引擎(缺省 claude,一般无需填写)' },
181
+ permission: { type: 'string', description: '可选:权限模式(缺省 bypassPermissions 最高权限,一般无需填写)' },
180
182
  },
181
- required: ['query'],
183
+ required: ['prompt'],
182
184
  },
183
185
  roles: ['lead', 'worker'],
184
186
  handler: async (args) => {
185
187
  if (!state.outbound) {
186
- return { text: `知识库检索不可用:${outboundOff().error}。修复后重启服务。`, isError: true }
188
+ return { text: '知识库 Agent 不可用:' + outboundOff().error + '。修复后重启服务。', isError: true }
187
189
  }
188
- const query = String(args.query ?? '').trim()
189
- if (!query) return { text: 'query 必填(要查什么问题)。', isError: true }
190
- const kb = String(args.kb_id ?? '').trim() || kbId() || undefined
191
- const topK = Math.min(Math.max(Math.round(Number(args.top_k) || 5), 1), 20)
192
- const r = await ragCall('POST', `${base()}/api/v1/search/two-stage`,
193
- { query, kb_id: kb, stage2_top_k: topK }, { timeoutMs: 30000 })
194
- if (!r.ok) {
195
- return { text: `检索失败:${r.error}。请确认 rag 后端(${base()})已启动(rag-knowledge 目录 start.bat / ragctl),稍后重试。`, isError: true }
196
- }
197
- const results = Array.isArray(r.body?.stage2?.results) ? r.body.stage2.results : []
198
- if (results.length === 0) {
199
- return { text: `未检索到相关经验/文档(查询:「${query}」)。可尝试更换关键词,或确认资料是否已用 kb_index 入库。` }
200
- }
201
- const top = results.slice(0, 5)
202
- const lines = top.map((h, i) => {
203
- const score = Number(h?.score ?? 0).toFixed(4)
204
- const path = String(h?.doc_path ?? '(无路径)')
205
- const brief = String(h?.content ?? '').replace(/\s+/g, ' ').trim().slice(0, 160)
206
- return `${i + 1}. [score=${score}] ${path}\n ${brief}${String(h?.content ?? '').length > 160 ? '…' : ''}`
207
- })
208
- return { text: `检索到 ${results.length} 条(展示前 ${top.length} 条):\n${lines.join('\n')}` }
209
- },
210
- })
190
+ const prompt = String(args.prompt ?? '').trim()
191
+ if (!prompt) return { text: 'prompt 必填(把要做的任务完整描述给知识库 Agent)。', isError: true }
192
+ const mode = String(args.mode ?? '').trim().toLowerCase() === 'async' ? 'async' : 'sync'
193
+ const body = { prompt, timeout_ms: 540000, mode }
194
+ const harness = String(args.harness ?? '').trim()
195
+ if (harness) body.harness = harness
196
+ const permission = String(args.permission ?? '').trim()
197
+ if (permission) body.permission = permission
211
198
 
212
- ctx.omp.registerTool({
213
- name: 'kb_store',
214
- label: '经验沉淀',
215
- description: '把本次作业中值得复用的经验(最佳实践/踩坑教训/操作要点)写入知识库,供团队后续检索。',
216
- parameters: {
217
- type: 'object',
218
- properties: {
219
- title: { type: 'string', description: '经验标题(一句话概括)' },
220
- category: { type: 'string', enum: CATEGORIES, description: '经验类别' },
221
- problem: { type: 'string', description: '遇到的问题/场景' },
222
- solution: { type: 'string', description: '解决方案/操作步骤' },
223
- key_lessons: { type: 'array', items: { type: 'string' }, description: '关键教训(条目列表,可选)' },
224
- tags: { type: 'array', items: { type: 'string' }, description: '标签(可选)' },
225
- severity: { type: 'string', enum: SEVERITIES, description: '严重程度(critical/important/normal/tip,可选,缺省 normal)' },
226
- },
227
- required: ['title', 'category'],
228
- },
229
- roles: ['lead', 'worker'],
230
- handler: async (args) => {
231
- if (!state.outbound) {
232
- return { text: `经验沉淀不可用:${outboundOff().error}。修复后重启服务。`, isError: true }
233
- }
234
- const title = String(args.title ?? '').trim()
235
- if (!title) return { text: 'title 必填(经验标题)。', isError: true }
236
- const category = String(args.category ?? '').trim()
237
- if (!CATEGORIES.includes(category)) {
238
- return { text: `category 必须是以下之一:${CATEGORIES.join('/')}`, isError: true }
239
- }
240
- const kb = await requireKbId()
241
- if (!kb) {
242
- return { text: `经验沉淀失败:知识库 ${KB_NAME} 不存在且自动建库失败(检查 web ${web()} 是否启动)。`, isError: true }
243
- }
244
- const body = {
245
- title,
246
- category,
247
- problem: String(args.problem ?? ''),
248
- solution: String(args.solution ?? ''),
249
- }
250
- const lessons = (Array.isArray(args.key_lessons) ? args.key_lessons : []).map(s => String(s).trim()).filter(Boolean)
251
- if (lessons.length) body.key_lessons = lessons
252
- const tags = (Array.isArray(args.tags) ? args.tags : []).map(s => String(s).trim()).filter(Boolean)
253
- if (tags.length) body.tags = tags
254
- const severity = String(args.severity ?? '').trim()
255
- if (severity) {
256
- // rag-knowledge ExperienceCreate.severity 是枚举,非法值会被 422 拒收——先在本侧校验
257
- if (!SEVERITIES.includes(severity)) {
258
- return { text: `severity 必须是以下之一:${SEVERITIES.join('/')}`, isError: true }
199
+ if (mode === 'async') {
200
+ // 异步:立即返回 task_id,知识库后台完成;结果稍后用 kb_agent_status 查询
201
+ const sub = await ragCall('POST', web() + '/api/kb/agent/chat', body, { timeoutMs: 30000, retries: 0 })
202
+ if (!sub.ok) {
203
+ return { text: '知识库异步任务提交失败:' + String(sub.error ?? '').slice(0, 200) + '。请确认 rag-knowledge web(' + web() + ') 已启动后重试。', isError: true }
259
204
  }
260
- body.severity = severity
205
+ const taskId = String(sub.body?.task_id ?? '')
206
+ if (!taskId) return { text: '知识库异步任务提交异常:响应缺少 task_id。', isError: true }
207
+ return { text: '已提交知识库异步任务(后台执行中,无需等待):\ntask_id=' + taskId + '\n任务完成后可调用 kb_agent_status(task_id) 获取该任务的执行结果。' }
261
208
  }
262
- const r = await ragCall('POST', `${base()}/api/v1/experience/${kb}`, body, { timeoutMs: 30000 })
209
+
210
+ const r = await ragCall('POST', web() + '/api/kb/agent/chat', body, { timeoutMs: 580000 })
263
211
  if (!r.ok) {
264
- return { text: `经验沉淀失败:${r.error}。请确认 rag 后端(${base()})已启动后重试。`, isError: true }
212
+ return { text: '知识库 Agent 调用失败:' + String(r.error ?? '').slice(0, 200) + '。请确认 rag-knowledge web(' + web() + ') 已启动后重试。', isError: true }
265
213
  }
266
- const expId = String(r.body?.experience?.id ?? '(未返回 id)')
267
- ctx.kv.bump('store.count')
268
- return { text: `经验已沉淀:${title}(id=${expId},category=${category},kb=${KB_NAME})。` }
214
+ const reply = String(r.body?.reply ?? '').trim()
215
+ return { text: reply || '(知识库 Agent 返回空回复)' }
269
216
  },
270
217
  })
271
218
 
272
219
  ctx.omp.registerTool({
273
- name: 'kb_index',
274
- label: '文档入库',
275
- description: '把一份 markdown 文档写入知识库并建立向量/图谱索引,供 kb_search 日后检索。',
220
+ name: 'kb_agent_status',
221
+ label: '知识库任务状态',
222
+ description: '查询知识库异步任务的执行状态与结果(kb_agent 以 mode=async 提交后,用返回的 task_id 查询;任务完成后返回知识库 Agent 的完整结果)。',
276
223
  parameters: {
277
224
  type: 'object',
278
225
  properties: {
279
- title: { type: 'string', description: '文档标题(同时作为文件名)' },
280
- content: { type: 'string', description: '文档正文(markdown)' },
281
- tags: { type: 'array', items: { type: 'string' }, description: '标签(可选)' },
226
+ task_id: { type: 'string', description: 'kb_agent 异步提交时返回的 task_id' },
282
227
  },
283
- required: ['title', 'content'],
228
+ required: ['task_id'],
284
229
  },
285
230
  roles: ['lead', 'worker'],
286
231
  handler: async (args) => {
287
232
  if (!state.outbound) {
288
- return { text: `文档入库不可用:${outboundOff().error}。修复后重启服务。`, isError: true }
289
- }
290
- const title = String(args.title ?? '').trim()
291
- const content = String(args.content ?? '')
292
- if (!title) return { text: 'title 必填(文档标题)。', isError: true }
293
- if (!content.trim()) return { text: 'content 必填(markdown 正文,不能为空)。', isError: true }
294
- const kb = await requireKbId()
295
- if (!kb) {
296
- return { text: `文档入库失败:知识库 ${KB_NAME} 不存在且自动建库失败(检查 web ${web()} 是否启动)。`, isError: true }
233
+ return { text: '知识库 Agent 不可用:' + outboundOff().error + '。修复后重启服务。', isError: true }
297
234
  }
298
- const tags = (Array.isArray(args.tags) ? args.tags : []).map(s => String(s).trim()).filter(Boolean)
299
- // 第 1 步:web 写盘(响应 {success,document:{path,...}})
300
- const docName = safeFileName(title)
301
- const w = await ragCall('POST', `${web()}/api/kb/documents/create`,
302
- { kbId: kb, name: docName, content, description: title }, { timeoutMs: 30000 })
303
- if (!w.ok) {
304
- return { text: `文档入库卡在第 1 步(web 写盘 ${web()}/api/kb/documents/create):${w.error}。未产生索引,可直接重试。`, isError: true }
235
+ const taskId = String(args.task_id ?? '').trim()
236
+ if (!taskId) return { text: 'task_id 必填(kb_agent 异步提交时返回的 id)。', isError: true }
237
+ const r = await callJson('GET', web() + '/api/kb/agent/tasks/' + encodeURIComponent(taskId), null, { timeoutMs: 15000, retries: 0 })
238
+ if (!r.ok) {
239
+ return { text: '任务查询失败:' + String(r.error ?? '') + '(不存在/已过期 2h/服务重启过,或任务从未提交)。', isError: true }
305
240
  }
306
- const docPath = String(w.body?.document?.path ?? '')
307
- if (!docPath) {
308
- return { text: '文档入库卡在第 1 步:写盘成功但响应缺少 document.path,无法继续索引。', isError: true }
241
+ const body = r.body || {}
242
+ const status = String(body.status ?? 'unknown')
243
+ if (status === 'running') {
244
+ return { text: '任务 ' + taskId + ' 仍在后台执行中(running)。稍后再次查询。' }
309
245
  }
310
- // 第 2 步:backend 索引(content 直传,doc_path 用写盘返回路径)
311
- const r = await ragCall('POST', `${base()}/api/v1/search/index-document`,
312
- { kb_id: kb, doc_path: docPath, doc_name: docName, description: title, content, tags }, { timeoutMs: 60000 })
313
- if (!r.ok) {
314
- return { text: `文档入库卡在第 2 步(backend 索引 ${base()}/api/v1/search/index-document):${r.error}。文档已写盘(${docPath}),服务恢复后可重试入库(同名会生成新文件)。`, isError: true }
246
+ const result = body.result || {}
247
+ const reply = String(result.reply ?? result.partial_text ?? '').trim()
248
+ if (status === 'completed' && reply) {
249
+ return { text: '任务 ' + taskId + ' 已完成。知识库 Agent 结果:\n\n' + reply }
315
250
  }
316
- const chunks = Number(r.body?.vector_index?.total_chunks ?? 0)
317
- ctx.kv.bump('index.count')
318
- return { text: `文档已入库:${docPath}(向量分块 ${chunks},kb=${KB_NAME}),可立即用 kb_search 检索。` }
251
+ return { text: '任务 ' + taskId + ' 状态:' + status + '\n' + String(result.error ?? '').slice(0, 300) + (result.partial_text ? '\n[部分输出]\n' + String(result.partial_text).slice(0, 600) : '') }
319
252
  },
320
253
  })
321
254
 
@@ -407,12 +340,3 @@ export default {
407
340
  function trimSlash(s) {
408
341
  return s.replace(/\/+$/, '')
409
342
  }
410
-
411
- /** 标题 → 安全文件名(剔除路径非法字符;确保 .md 后缀) */
412
- function safeFileName(title) {
413
- // eslint-disable-next-line no-control-regex -- 文件名净化:必须剔除控制字符
414
- let name = String(title).replace(/[\\/:*?"<>|\u0000-\u001f]/g, '-').replace(/\s+/g, ' ').trim().replace(/^[.\s]+|[.\s]+$/g, '')
415
- if (!name) name = 'untitled'
416
- if (name.length > 80) name = name.slice(0, 80).trim()
417
- return name.toLowerCase().endsWith('.md') ? name : `${name}.md`
418
- }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * serial-bridge 客户端面板 —— 注入 'plugins.page' 插槽。
3
+ * 协议栈可用性、系统串口枚举、连接探针(开串口读一次,不落库)、打开链路与串口节点概览。
4
+ * 与 diag-bridge 同范式:30s 自动刷新健康面,语言切换即重渲染。
5
+ */
6
+ export function setup(ctx) {
7
+ const styleId = 'aw-serial-styles'
8
+ if (!document.getElementById(styleId)) {
9
+ document.head.append(ctx.el('style', { id: styleId }, [`
10
+ .aw-serial { display:flex; flex-direction:column; gap:10px; font-size:12px; }
11
+ .aw-serial-badge { display:inline-flex; align-items:center; gap:6px; }
12
+ .aw-serial-dot { width:8px; height:8px; border-radius:50%; display:inline-block; }
13
+ .aw-serial-dot-ok { background:#35e0a0; }
14
+ .aw-serial-dot-bad { background:#e05a5a; }
15
+ .aw-serial-toolbar { display:flex; justify-content:flex-end; }
16
+ .aw-serial-btn { padding:4px 12px; border:1px solid color-mix(in srgb, currentColor 28%, transparent); border-radius:7px; background:transparent; color:inherit; cursor:pointer; }
17
+ .aw-serial-table { width:100%; border-collapse:collapse; }
18
+ .aw-serial-table th, .aw-serial-table td { text-align:left; padding:5px 8px; border-bottom:1px solid color-mix(in srgb, currentColor 10%, transparent); }
19
+ .aw-serial-table th { opacity:.65; font-weight:500; }
20
+ .aw-serial-empty { opacity:.6; padding:6px 0; }
21
+ .aw-serial-form { display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
22
+ .aw-serial-form .aw-serial-inp { width:110px; padding:3px 8px; border:1px solid color-mix(in srgb, currentColor 24%, transparent); border-radius:7px; background:transparent; color:inherit; font:inherit; }
23
+ .aw-serial-form .aw-serial-inp.grow { flex:1 1 140px; }
24
+ .aw-serial-hint { opacity:.6; }
25
+ .aw-serial-result { white-space:pre-wrap; word-break:break-all; padding:6px 8px; border-radius:7px; }
26
+ .aw-serial-result.ok { background:color-mix(in srgb, #35e0a0 12%, transparent); }
27
+ .aw-serial-result.bad { background:color-mix(in srgb, #e05a5a 12%, transparent); }
28
+ .aw-serial-sec { font-weight:600; opacity:.85; margin-top:2px; }
29
+ `]))
30
+ }
31
+
32
+ ctx.ui.registerPanel({
33
+ slot: 'plugins.page',
34
+ name: 'serial-bridge-panel',
35
+ titleKey: 'panel.title',
36
+ order: 30,
37
+ mount(elRoot) {
38
+ const t = k => ctx.t(`panel.${k}`)
39
+ const root = ctx.el('div', { class: 'aw-serial' })
40
+ elRoot.append(root)
41
+
42
+ // ---- 状态徽标 + 刷新 ----
43
+ const badge = ctx.el('span', { class: 'aw-serial-badge' })
44
+ const refreshAll = () => {
45
+ void loadHealth()
46
+ void loadPorts()
47
+ }
48
+ const toolbar = ctx.el('div', { class: 'aw-serial-toolbar' }, [
49
+ ctx.el('button', { class: 'aw-serial-btn', onclick: refreshAll }, [t('refresh')]),
50
+ ])
51
+ root.append(ctx.el('div', {}, [badge]), toolbar)
52
+
53
+ // ---- 系统串口表 ----
54
+ root.append(ctx.el('div', { class: 'aw-serial-sec' }, [t('ports')]))
55
+ const portsWrap = ctx.el('div')
56
+ root.append(portsWrap)
57
+
58
+ // ---- 连接探针 ----
59
+ root.append(ctx.el('div', { class: 'aw-serial-sec' }, [t('probe')]))
60
+ const probeSel = ctx.el('input', { class: 'aw-serial-inp grow', placeholder: 'COM3' })
61
+ const modeSel = ctx.el('select', { class: 'aw-serial-inp' }, [
62
+ ctx.el('option', { value: 'modbus-rtu' }, ['Modbus RTU']),
63
+ ctx.el('option', { value: 'ascii-line' }, ['ASCII']),
64
+ ])
65
+ const baudInp = ctx.el('input', { class: 'aw-serial-inp', type: 'number', value: '9600' })
66
+ const unitInp = ctx.el('input', { class: 'aw-serial-inp', type: 'number', value: '1' })
67
+ const regInp = ctx.el('input', { class: 'aw-serial-inp', type: 'number', placeholder: '40001' })
68
+ const lineInp = ctx.el('input', { class: 'aw-serial-inp grow', placeholder: t('sendLine') })
69
+ const probeBtn = ctx.el('button', { class: 'aw-serial-btn', onclick: () => void runProbe() })
70
+ const result = ctx.el('div', { class: 'aw-serial-hint' }, [t('probe_hint')])
71
+ const form = ctx.el('div', { class: 'aw-serial-form' }, [
72
+ probeSel, modeSel, baudInp, unitInp, regInp, lineInp, probeBtn,
73
+ ])
74
+ root.append(form, result)
75
+
76
+ // ---- 打开的链路 + 串口节点 ----
77
+ root.append(ctx.el('div', { class: 'aw-serial-sec' }, [t('links')]))
78
+ const linksWrap = ctx.el('div')
79
+ root.append(linksWrap, ctx.el('div', { class: 'aw-serial-sec' }, [t('nodes')]))
80
+ const nodesWrap = ctx.el('div')
81
+ root.append(nodesWrap)
82
+
83
+ let probing = false
84
+ function setBtn(label, disabled) {
85
+ probeBtn.textContent = label
86
+ probeBtn.disabled = disabled
87
+ }
88
+
89
+ async function loadHealth() {
90
+ const h = await ctx.fetch('/api/plugins/serial-bridge/health').catch(() => null)
91
+ badge.replaceChildren(
92
+ ctx.el('span', { class: `aw-serial-dot ${h?.available ? 'aw-serial-dot-ok' : 'aw-serial-dot-bad'}` }),
93
+ document.createTextNode(h?.available ? t('available') : t('unavailable')),
94
+ )
95
+ const links = Array.isArray(h?.links) ? h.links : []
96
+ if (!links.length) {
97
+ linksWrap.replaceChildren(ctx.el('div', { class: 'aw-serial-empty' }, [t('nolinks')]))
98
+ }
99
+ else {
100
+ const tbody = ctx.el('tbody')
101
+ for (const l of links) {
102
+ tbody.append(ctx.el('tr', {}, [
103
+ ctx.el('td', {}, [String(l.key ?? '-')]),
104
+ ctx.el('td', {}, [String(l.pending ?? 0)]),
105
+ ctx.el('td', {}, [String(l.errors ?? 0)]),
106
+ ctx.el('td', {}, [l.lastUsedAt ? new Date(l.lastUsedAt).toLocaleTimeString() : '-']),
107
+ ]))
108
+ }
109
+ linksWrap.replaceChildren(ctx.el('table', { class: 'aw-serial-table' }, [
110
+ ctx.el('thead', {}, [ctx.el('tr', {}, [
111
+ ctx.el('th', {}, [t('link')]),
112
+ ctx.el('th', {}, [t('pending')]),
113
+ ctx.el('th', {}, [t('errors')]),
114
+ ctx.el('th', {}, [t('lastUsed')]),
115
+ ])]),
116
+ tbody,
117
+ ]))
118
+ }
119
+ const nodes = Array.isArray(h?.readNodes) ? h.readNodes : []
120
+ nodesWrap.replaceChildren(
121
+ nodes.length
122
+ ? ctx.el('div', {}, [nodes.map(n => `${n.name || n.id} @ ${n.path || '?'}${n.enabled === false ? ' [off]' : ''}`).join(', ')])
123
+ : ctx.el('div', { class: 'aw-serial-empty' }, [t('nonodes')]),
124
+ )
125
+ }
126
+
127
+ async function loadPorts() {
128
+ const r = await ctx.fetch('/api/plugins/serial-bridge/ports').catch(() => null)
129
+ const ports = Array.isArray(r?.ports) ? r.ports : []
130
+ if (!ports.length) {
131
+ portsWrap.replaceChildren(ctx.el('div', { class: 'aw-serial-empty' }, [r?.error ?? t('noports')]))
132
+ return
133
+ }
134
+ const tbody = ctx.el('tbody')
135
+ for (const p of ports) {
136
+ const pickPort = () => void (probeSel.value = p.path)
137
+ const row = ctx.el('tr', { style: 'cursor:pointer', title: p.friendlyName ?? '', onclick: pickPort }, [
138
+ ctx.el('td', {}, [String(p.path ?? '-')]),
139
+ ctx.el('td', {}, [String(p.manufacturer ?? '-')]),
140
+ ctx.el('td', {}, [String(p.serialNumber ?? '-')]),
141
+ ])
142
+ tbody.append(row)
143
+ }
144
+ portsWrap.replaceChildren(ctx.el('table', { class: 'aw-serial-table' }, [
145
+ ctx.el('thead', {}, [ctx.el('tr', {}, [
146
+ ctx.el('th', {}, [t('path')]),
147
+ ctx.el('th', {}, [t('manufacturer')]),
148
+ ctx.el('th', {}, [t('serialNumber')]),
149
+ ])]),
150
+ tbody,
151
+ ]))
152
+ }
153
+
154
+ async function runProbe() {
155
+ if (probing) return
156
+ const path = String(probeSel.value ?? '').trim()
157
+ if (!path) {
158
+ result.className = 'aw-serial-result bad'
159
+ result.textContent = t('noports')
160
+ return
161
+ }
162
+ probing = true
163
+ setBtn(t('probing'), true)
164
+ try {
165
+ // ctx.fetch 会自动 JSON.stringify(body)——这里必须传对象(双重 stringify 会让服务端收到字符串)
166
+ const r = await ctx.fetch('/api/plugins/serial-bridge/probe', {
167
+ method: 'POST',
168
+ body: {
169
+ path,
170
+ mode: modeSel.value,
171
+ baudRate: Number(baudInp.value) || 9600,
172
+ unitId: Number(unitInp.value) || 1,
173
+ register: regInp.value === '' ? undefined : Number(regInp.value),
174
+ sendLine: modeSel.value === 'ascii-line' && lineInp.value ? lineInp.value : undefined,
175
+ },
176
+ })
177
+ const body = r ?? {}
178
+ const ok = body.ok === true
179
+ result.className = `aw-serial-result ${ok ? 'ok' : 'bad'}`
180
+ result.textContent = `${ok ? '✓' : '✗'} ${body.message ?? body.error ?? '-'}${body.latencyMs != null ? ` (${body.latencyMs}ms)` : ''}`
181
+ void loadHealth()
182
+ }
183
+ catch (err) {
184
+ result.className = 'aw-serial-result bad'
185
+ result.textContent = `✗ ${err?.message ?? err}`
186
+ }
187
+ finally {
188
+ probing = false
189
+ setBtn(t('run_probe'), false)
190
+ }
191
+ }
192
+
193
+ setBtn(t('run_probe'), false)
194
+ void loadHealth()
195
+ void loadPorts()
196
+ const timer = setInterval(() => void loadHealth(), 30_000)
197
+ const offLocale = ctx.hooks.on('i18n:changed', () => {
198
+ setBtn(t('run_probe'), false)
199
+ result.className = 'aw-serial-hint'
200
+ result.textContent = t('probe_hint')
201
+ void loadHealth()
202
+ void loadPorts()
203
+ })
204
+ return () => {
205
+ clearInterval(timer)
206
+ offLocale()
207
+ }
208
+ },
209
+ })
210
+ }