agentworkshop 0.7.41 → 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 (265) 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/DKySmNPI.js +14 -0
  11. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  12. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  13. package/.output/public/_nuxt/{DGbd-UiG.js → EHlEMRii.js} +1 -1
  14. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  15. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  16. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  17. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  18. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  19. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  20. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  21. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  22. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  23. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  24. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  25. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  26. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  27. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  28. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  29. package/.output/public/_nuxt/builds/latest.json +1 -1
  30. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  31. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  32. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  33. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  34. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  35. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  36. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  37. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  38. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  39. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  40. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  41. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  42. package/.output/server/chunks/_/nitro.mjs +748 -733
  43. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  44. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  45. package/.output/server/chunks/build/{TownView--otsnr_7.mjs → TownView-CJ6IsDCc.mjs} +226 -225
  46. package/.output/server/chunks/build/{TownView--otsnr_7.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  47. package/.output/server/chunks/build/{_id_-Brv-JSvr.mjs → _id_-CVD_H0ir.mjs} +143 -142
  48. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  49. package/.output/server/chunks/build/{_id_-D9pl1OZy.mjs → _id_-CtxMb3qp.mjs} +41 -41
  50. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  51. package/.output/server/chunks/build/{_wsId_-BASfDf0s.mjs → _wsId_-DpY3T-md.mjs} +514 -444
  52. package/.output/server/chunks/build/{_wsId_-BASfDf0s.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  53. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  54. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  55. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  56. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  57. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  58. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  59. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  60. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  61. package/.output/server/chunks/build/{daq-DkMvD8sg.mjs → daq-DWWSKGAV.mjs} +89 -88
  62. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  63. package/.output/server/chunks/build/{dcw-C1jgVJkO.mjs → dcw-CT8k17_E.mjs} +44 -43
  64. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  65. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  66. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  67. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  68. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  69. package/.output/server/chunks/build/{pages-B0bUWnC6.mjs → pages-BHcSBM2D.mjs} +24 -18
  70. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  71. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  72. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  73. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  74. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  75. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  76. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  77. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  78. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  79. package/.output/server/chunks/build/{town-CoQdblbZ.mjs → town-QJWB5wng.mjs} +3 -2
  80. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  81. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  82. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  83. package/.output/server/chunks/routes/renderer.mjs +1 -1
  84. package/.output/server/chunks/virtual/entry.mjs +637 -86
  85. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  86. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  87. package/.output/server/package.json +1 -1
  88. package/README-zh.md +13 -3
  89. package/README.md +13 -3
  90. package/app/components/AppHeader.vue +961 -959
  91. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  92. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  93. package/app/components/workshop/AgentLanesView.vue +998 -998
  94. package/app/components/workshop/ArtifactCard.vue +120 -120
  95. package/app/components/workshop/AssetLibrary.vue +452 -452
  96. package/app/components/workshop/ChannelSessionList.vue +812 -804
  97. package/app/components/workshop/CommandPalette.vue +269 -269
  98. package/app/components/workshop/Composer.vue +827 -827
  99. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  100. package/app/components/workshop/EventBlock.vue +602 -602
  101. package/app/components/workshop/FileSelectorModal.vue +188 -188
  102. package/app/components/workshop/InspectorPanel.vue +301 -301
  103. package/app/components/workshop/MemoryPanel.vue +364 -364
  104. package/app/components/workshop/MultiChannelView.vue +189 -189
  105. package/app/components/workshop/TaskBoardView.vue +686 -686
  106. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  107. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  108. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  109. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  110. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  111. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  112. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  113. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  114. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  115. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  116. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  117. package/app/components/workshop/town/TownView.vue +56 -56
  118. package/app/middleware/locale-cookie.global.ts +22 -0
  119. package/app/pages/aml/index.vue +24 -2
  120. package/app/pages/daq/[id].vue +11 -11
  121. package/app/pages/daq/index.vue +2316 -2316
  122. package/app/pages/dcw/[id].vue +18 -19
  123. package/app/pages/dcw/index.vue +3 -3
  124. package/app/pages/index.vue +987 -981
  125. package/app/pages/plugins/index.vue +317 -311
  126. package/app/pages/settings.vue +1564 -1562
  127. package/app/pages/tokens.vue +15 -15
  128. package/app/pages/workshop/agents.vue +612 -609
  129. package/app/pages/workshop/channel-templates.vue +18 -11
  130. package/app/pages/workshop/index.vue +668 -668
  131. package/app/pages/workshop/teams.vue +743 -740
  132. package/app/pages/workshop/w/[wsId].vue +704 -704
  133. package/app/plugins/locale-restore.client.ts +16 -1
  134. package/app/utils/builtin-catalog.ts +104 -0
  135. package/config.yml +170 -170
  136. package/docs/full-test-plan.md +2 -3
  137. package/i18n/locales/en.ts +293 -35
  138. package/i18n/locales/zh-CN.ts +265 -7
  139. package/package.json +2 -2
  140. package/scripts/_dbg-perms-e2e.mjs +132 -109
  141. package/scripts/_demo-agentteam-capture.mjs +278 -0
  142. package/scripts/_e2e-ui-functional.mjs +371 -0
  143. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  144. package/scripts/_i18n-en-verify.mjs +107 -0
  145. package/scripts/_i18n-extra-checks.mjs +53 -0
  146. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  147. package/scripts/_i18n-verify-keys.mjs +50 -0
  148. package/scripts/_loop-biax-campaign.mjs +15 -9
  149. package/scripts/_sweep-button-contrast.mjs +87 -0
  150. package/scripts/ui/record-demo.mjs +557 -0
  151. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  152. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  153. package/server/services/workshop/daq/drivers.ts +11 -0
  154. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  155. package/.output/public/_nuxt/BN16aRdQ.js +0 -1
  156. package/.output/public/_nuxt/BWVhZntO.js +0 -1
  157. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  158. package/.output/public/_nuxt/BsROmY89.js +0 -1
  159. package/.output/public/_nuxt/C0ZrS1KL.js +0 -19
  160. package/.output/public/_nuxt/C4s_niy-.js +0 -14
  161. package/.output/public/_nuxt/D6mbFA-a.js +0 -1
  162. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  163. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  164. package/.output/public/_nuxt/Dap5PmTL.js +0 -2
  165. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  166. package/.output/public/_nuxt/DvLxILQP.js +0 -1
  167. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  168. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  169. package/.output/public/_nuxt/_id_.D9ymtHB5.css +0 -1
  170. package/.output/public/_nuxt/_id_.jf-_8E_c.css +0 -1
  171. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  172. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  173. package/.output/public/_nuxt/builds/meta/78a295bb-2072-48a4-8b46-6d545fdae743.json +0 -1
  174. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  175. package/.output/public/_nuxt/daq.DjSgY94l.css +0 -1
  176. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  177. package/.output/public/_nuxt/eqq3wWQF.js +0 -18
  178. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  179. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  180. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  181. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  182. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  183. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  184. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  185. package/.output/server/chunks/build/_id_-Brv-JSvr.mjs.map +0 -1
  186. package/.output/server/chunks/build/_id_-D9pl1OZy.mjs.map +0 -1
  187. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  188. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  189. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  190. package/.output/server/chunks/build/daq-DkMvD8sg.mjs.map +0 -1
  191. package/.output/server/chunks/build/dcw-C1jgVJkO.mjs.map +0 -1
  192. package/.output/server/chunks/build/pages-B0bUWnC6.mjs.map +0 -1
  193. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  194. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  195. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  196. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  197. package/.output/server/chunks/build/town-CoQdblbZ.mjs.map +0 -1
  198. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  199. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  200. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  201. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  202. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  203. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  204. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  205. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  206. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  207. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  208. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  209. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  210. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  211. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  212. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  213. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  214. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  215. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  216. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  217. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  218. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  219. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  220. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  221. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  222. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  223. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  224. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  225. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  226. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  227. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  228. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  229. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  230. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  231. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  232. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  233. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  234. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  235. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  236. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  237. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  238. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  239. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  240. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  241. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  242. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  243. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  244. package/scripts/_dbg-minimal-omp.mjs +0 -77
  245. package/scripts/_dbg-mode-nav.mjs +0 -173
  246. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  247. package/scripts/_dbg-team-repro.mjs +0 -76
  248. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  249. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  250. package/scripts/_townview_style.css +0 -1185
  251. package/scripts/_townview_template.html +0 -1215
  252. package/server/data/agent-node-bindings.json +0 -554
  253. package/server/data/daq-templates.json +0 -16
  254. package/server/data/daqs.json +0 -7464
  255. package/server/data/dcw-lines.json +0 -1787
  256. package/server/data/dcw-products.json +0 -1626
  257. package/server/data/dcw-recipes.json +0 -4672
  258. package/server/data/dcw-rollback.json +0 -20754
  259. package/server/data/dcw-runs.json +0 -6354
  260. package/server/data/dcw-templates.json +0 -146
  261. package/server/data/dcw-writes.json +0 -15650
  262. package/server/data/dcws.json +0 -9033
  263. package/server/data/device-twins.json +0 -133
  264. package/server/data/line-runs.json +0 -322
  265. package/server/data/scene-layouts.json +0 -277
@@ -1,364 +1,364 @@
1
- <script setup lang="ts">
2
- /**
3
- * 记忆面板:shared 公共域 / 按成员 private 域切换;
4
- * 混合检索(REST search,与 agent search_memory 工具同源)+ 手动写入 + 删除。
5
- * 身份凭证自动化:REST 记忆端点要求 Bearer agent token,成员列表(用户 token 可读)
6
- * 已含各成员 token → 自动装配;手动填 token 仅作为兜底(默认折叠)。
7
- * 传入 agentId(Agent 抽屉场景)时锁定身份,隐藏身份选择。
8
- */
9
- import { message } from 'ant-design-vue'
10
- import { useEntitiesStore } from '@/app/stores/workshop/entities'
11
- import { useWorkshopApi } from '@/app/composables/workshop/useWorkshopApi'
12
-
13
- const { t } = useI18n()
14
-
15
- const props = defineProps<{ channelId: string, agentId?: string }>()
16
- const entities = useEntitiesStore()
17
- const api = useWorkshopApi()
18
-
19
- const domain = ref<'shared' | 'private'>('shared')
20
- const selectedAgent = ref<string>(props.agentId ?? '')
21
- watch(() => props.agentId, (v) => {
22
- if (v) selectedAgent.value = v
23
- })
24
-
25
- /** 成员身份 → token 自动装配(用户 token 拉成员列表;失败退化为手填) */
26
- const memberTokens = ref<Record<string, string>>({})
27
- const manualToken = ref('')
28
- const effectiveToken = computed(() =>
29
- manualToken.value.trim() || memberTokens.value[selectedAgent.value] || '',
30
- )
31
- const tokenResolved = computed(() => effectiveToken.value.length > 0)
32
-
33
- const loadMembers = async (): Promise<void> => {
34
- try {
35
- const res = await api.listChannelAgents(props.channelId)
36
- const map: Record<string, string> = {}
37
- for (const m of res.data ?? []) {
38
- if (m.token) map[m.id] = m.token
39
- }
40
- memberTokens.value = map
41
- if (!selectedAgent.value) {
42
- // 默认身份:优先 lead(shared 域写入需 lead)
43
- const lead = (res.data ?? []).find(m => m.role === 'lead')
44
- if (lead) selectedAgent.value = lead.id
45
- }
46
- }
47
- catch { /* 拉取失败由手填兜底 */ }
48
- }
49
- onMounted(() => void loadMembers())
50
- watch(() => props.channelId, () => {
51
- memberTokens.value = {}
52
- selectedAgent.value = props.agentId ?? ''
53
- void loadMembers()
54
- })
55
-
56
- const authHeaders = computed<Record<string, string>>(() => {
57
- const h: Record<string, string> = {}
58
- if (effectiveToken.value) h.authorization = `Bearer ${effectiveToken.value}`
59
- return h
60
- })
61
-
62
- const agents = computed(() => entities.agents[props.channelId] ?? [])
63
-
64
- const rows = ref<Array<{ id: string, title: string, content: string, kind: string, importance: number, agentId: string }>>([])
65
- const loading = ref(false)
66
-
67
- const load = async (): Promise<void> => {
68
- loading.value = true
69
- try {
70
- const url = domain.value === 'shared'
71
- ? `/api/workshop/channels/${props.channelId}/memories`
72
- : `/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories`
73
- const res = await fetch(url, { headers: authHeaders.value })
74
- const json = await res.json()
75
- rows.value = json.code === 0 ? json.data : []
76
- if (json.code !== 0) message.warning(json.message ?? t('memoryPanel.k186sctu014'))
77
- }
78
- finally {
79
- loading.value = false
80
- }
81
- }
82
- watch([domain, selectedAgent, effectiveToken], () => {
83
- if (effectiveToken.value && (domain.value === 'shared' || selectedAgent.value)) void load()
84
- })
85
-
86
- const searchText = ref('')
87
- const searchScope = ref<'auto' | 'private' | 'shared'>('auto')
88
- const searchResults = ref<Array<{ id: string, title: string, content: string, score: number, source: string }>>([])
89
- const searching = ref(false)
90
- const doSearch = async (): Promise<void> => {
91
- if (!searchText.value.trim() || !selectedAgent.value || !effectiveToken.value) {
92
- message.warning(t('memoryPanel.k1eh0fbo015'))
93
- return
94
- }
95
- searching.value = true
96
- try {
97
- const res = await fetch(`/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories/search`, {
98
- method: 'POST',
99
- headers: { 'content-type': 'application/json', ...authHeaders.value },
100
- body: JSON.stringify({ query: searchText.value, scope: searchScope.value, limit: 8 }),
101
- })
102
- const json = await res.json()
103
- searchResults.value = json.code === 0 ? json.data : []
104
- }
105
- finally {
106
- searching.value = false
107
- }
108
- }
109
-
110
- const writeOpen = ref(false)
111
- const writeForm = reactive({ title: '', content: '', scope: 'shared' as 'shared' | 'private', importance: 0.8, dedupKey: '' })
112
- const doWrite = async (): Promise<void> => {
113
- if (!writeForm.title || !writeForm.content || !selectedAgent.value || !effectiveToken.value) {
114
- message.warning(t('memoryPanel.k1dpj734016'))
115
- return
116
- }
117
- const res = await fetch(
118
- `/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories`,
119
- {
120
- method: 'POST',
121
- headers: { 'content-type': 'application/json', ...authHeaders.value },
122
- body: JSON.stringify({ ...writeForm, dedupKey: writeForm.dedupKey || undefined }),
123
- },
124
- )
125
- const json = await res.json()
126
- if (json.code === 0) {
127
- message.success(t('memoryPanel.k3n5bat017'))
128
- writeOpen.value = false
129
- writeForm.title = ''
130
- writeForm.content = ''
131
- void load()
132
- }
133
- else {
134
- message.error(json.message ?? t('memoryPanel.k1bb5i1l018'))
135
- }
136
- }
137
- </script>
138
-
139
- <template>
140
- <div class="memory-panel">
141
- <div class="toolbar">
142
- <a-radio-group
143
- v-model:value="domain"
144
- size="small"
145
- button-style="solid"
146
- >
147
- <a-radio-button value="shared">
148
- {{ $t('memoryPanel.k3l2hmp005') }}
149
- </a-radio-button>
150
- <a-radio-button value="private">
151
- {{ $t('memoryPanel.k3rve9a006') }}
152
- </a-radio-button>
153
- </a-radio-group>
154
- <a-select
155
- v-if="!agentId"
156
- v-model:value="selectedAgent"
157
- size="small"
158
- :placeholder="$t('memoryPanel.k1du3379001')"
159
- class="agent-select"
160
- :options="agents.map(a => ({ value: a.agentId, label: a.name }))"
161
- />
162
- <a-tooltip :title="tokenResolved ? '成员 token 已自动装配' : '自动装配失败,可手动填入成员 token'">
163
- <span
164
- class="token-state"
165
- :data-ok="tokenResolved"
166
- ><span class="i-tabler-key" />{{ tokenResolved ? 'auto' : $t('memoryPanel.k3zul4013') }}</span>
167
- </a-tooltip>
168
- </div>
169
- <a-input-password
170
- v-if="!tokenResolved"
171
- v-model:value="manualToken"
172
- size="small"
173
- placeholder="Bearer token(成员身份,兜底手填)"
174
- class="token"
175
- />
176
-
177
- <div class="search-bar">
178
- <a-input-search
179
- v-model:value="searchText"
180
- size="small"
181
- placeholder="混合检索记忆(FTS+向量,与 agent search_memory 同源)…"
182
- :loading="searching"
183
- @search="doSearch"
184
- />
185
- <a-select
186
- v-model:value="searchScope"
187
- size="small"
188
- class="scope"
189
- :options="[{ value: 'auto', label: 'auto' }, { value: 'private', label: 'private' }, { value: 'shared', label: 'shared' }]"
190
- />
191
- </div>
192
- <div
193
- v-if="searchResults.length"
194
- class="search-results"
195
- >
196
- <div
197
- v-for="s in searchResults"
198
- :key="s.id"
199
- class="hit"
200
- :title="s.content.slice(0, 200)"
201
- >
202
- <span
203
- class="src"
204
- :data-source="s.source"
205
- >{{ s.source }}</span>
206
- <span class="score">{{ s.score }}</span>
207
- <span class="hit-title">{{ s.title }}</span>
208
- </div>
209
- </div>
210
-
211
- <div class="list-head">
212
- <span>{{ $t('memoryPanel.k1k7okbe007') }}</span>
213
- <a-space size="small">
214
- <a-button
215
- size="small"
216
- type="text"
217
- @click="load"
218
- >
219
- {{ $t('memoryPanel.k3x1jg008') }}
220
- </a-button>
221
- <a-button
222
- size="small"
223
- type="text"
224
- @click="writeOpen = true"
225
- >
226
- {{ $t('memoryPanel.k3wtib009') }}
227
- </a-button>
228
- </a-space>
229
- </div>
230
- <a-spin :spinning="loading">
231
- <div
232
- v-for="r in rows"
233
- :key="r.id"
234
- class="row"
235
- >
236
- <div class="row-head">
237
- <a-tag class="kind">
238
- {{ r.kind }}
239
- </a-tag>
240
- <span class="row-importance">{{ r.importance.toFixed(2) }}</span>
241
- <span class="row-title">{{ r.title }}</span>
242
- </div>
243
- <div class="row-content">
244
- {{ r.content.slice(0, 140) }}{{ r.content.length > 140 ? '…' : '' }}
245
- </div>
246
- </div>
247
- <div
248
- v-if="rows.length === 0 && !loading"
249
- class="empty"
250
- >
251
- ({{ $t('memoryPanel.k43rxk011') }}
252
- </div>
253
- </a-spin>
254
-
255
- <a-modal
256
- v-model:open="writeOpen"
257
- :title="$t('memoryPanel.k1bbee8p002')"
258
- ok-text="写入"
259
- cancel-text="取消"
260
- @ok="doWrite"
261
- >
262
- <a-form layout="vertical">
263
- <a-form-item label="scope">
264
- <a-radio-group v-model:value="writeForm.scope">
265
- <a-radio value="shared">
266
- {{ $t('memoryPanel.kemjjvq010') }}
267
- </a-radio>
268
- <a-radio value="private">
269
- private({{ $t('memoryPanel.k3onh9w012') }}
270
- </a-radio>
271
- </a-radio-group>
272
- </a-form-item>
273
- <a-form-item :label="$t('memoryPanel.k419s4003')">
274
- <a-input v-model:value="writeForm.title" />
275
- </a-form-item>
276
- <a-form-item :label="$t('memoryPanel.k3wv1f004')">
277
- <a-textarea
278
- v-model:value="writeForm.content"
279
- :rows="4"
280
- />
281
- </a-form-item>
282
- <a-form-item label="importance(0-1)">
283
- <a-input-number
284
- v-model:value="writeForm.importance"
285
- :min="0"
286
- :max="1"
287
- :step="0.1"
288
- />
289
- </a-form-item>
290
- <a-form-item label="dedupKey(可选,幂等)">
291
- <a-input v-model:value="writeForm.dedupKey" />
292
- </a-form-item>
293
- </a-form>
294
- </a-modal>
295
- </div>
296
- </template>
297
-
298
- <style scoped>
299
- .memory-panel { font-size: 12px; }
300
- .toolbar {
301
- display: flex;
302
- gap: 6px;
303
- align-items: center;
304
- margin-bottom: 6px;
305
- }
306
- .agent-select { flex: 1 1 auto; min-width: 90px; }
307
- .token-state {
308
- flex: 0 0 auto;
309
- padding: 0 5px;
310
- font-family: var(--font-mono);
311
- font-size: 10px;
312
- border-radius: var(--radius-chip);
313
- background: color-mix(in srgb, currentColor 8%, transparent);
314
- }
315
- .token-state[data-ok='true'] { color: var(--tone-success-dot); }
316
- .token-state[data-ok='false'] { color: var(--tone-warning-dot); }
317
- .token { margin-bottom: 6px; }
318
- .search-bar {
319
- display: flex;
320
- gap: 6px;
321
- margin-bottom: 6px;
322
- }
323
- .scope { width: 90px; }
324
- .search-results { margin-bottom: 8px; }
325
- .hit {
326
- display: flex;
327
- gap: 6px;
328
- align-items: center;
329
- padding: 2px 4px;
330
- font-family: var(--font-mono);
331
- font-size: 11px;
332
- }
333
- .src {
334
- padding: 0 4px;
335
- color: var(--tone-info-dot);
336
- background: var(--tone-info-bg);
337
- border-radius: var(--radius-chip);
338
- }
339
- .src[data-source='shared'] {
340
- color: var(--tone-retry-dot);
341
- background: var(--tone-retry-bg);
342
- }
343
- .score { opacity: 0.5; }
344
- .hit-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
345
- .list-head {
346
- display: flex;
347
- align-items: center;
348
- justify-content: space-between;
349
- padding: 4px 0;
350
- font-weight: 600;
351
- opacity: 0.7;
352
- }
353
- .row { padding: 4px 0; border-bottom: 1px dashed color-mix(in srgb, currentColor 10%, transparent); }
354
- .row-head { display: flex; gap: 6px; align-items: center; }
355
- .kind { margin-inline-end: 0; font-size: 10px; }
356
- .row-importance { font-family: var(--font-mono); font-size: 10px; opacity: 0.5; }
357
- .row-title { font-weight: 600; font-size: 12px; }
358
- .row-content {
359
- font-size: 11px;
360
- opacity: 0.65;
361
- word-break: break-all;
362
- }
363
- .empty { padding: 8px 0; opacity: 0.4; }
364
- </style>
1
+ <script setup lang="ts">
2
+ /**
3
+ * 记忆面板:shared 公共域 / 按成员 private 域切换;
4
+ * 混合检索(REST search,与 agent search_memory 工具同源)+ 手动写入 + 删除。
5
+ * 身份凭证自动化:REST 记忆端点要求 Bearer agent token,成员列表(用户 token 可读)
6
+ * 已含各成员 token → 自动装配;手动填 token 仅作为兜底(默认折叠)。
7
+ * 传入 agentId(Agent 抽屉场景)时锁定身份,隐藏身份选择。
8
+ */
9
+ import { message } from 'ant-design-vue'
10
+ import { useEntitiesStore } from '@/app/stores/workshop/entities'
11
+ import { useWorkshopApi } from '@/app/composables/workshop/useWorkshopApi'
12
+
13
+ const { t } = useI18n()
14
+
15
+ const props = defineProps<{ channelId: string, agentId?: string }>()
16
+ const entities = useEntitiesStore()
17
+ const api = useWorkshopApi()
18
+
19
+ const domain = ref<'shared' | 'private'>('shared')
20
+ const selectedAgent = ref<string>(props.agentId ?? '')
21
+ watch(() => props.agentId, (v) => {
22
+ if (v) selectedAgent.value = v
23
+ })
24
+
25
+ /** 成员身份 → token 自动装配(用户 token 拉成员列表;失败退化为手填) */
26
+ const memberTokens = ref<Record<string, string>>({})
27
+ const manualToken = ref('')
28
+ const effectiveToken = computed(() =>
29
+ manualToken.value.trim() || memberTokens.value[selectedAgent.value] || '',
30
+ )
31
+ const tokenResolved = computed(() => effectiveToken.value.length > 0)
32
+
33
+ const loadMembers = async (): Promise<void> => {
34
+ try {
35
+ const res = await api.listChannelAgents(props.channelId)
36
+ const map: Record<string, string> = {}
37
+ for (const m of res.data ?? []) {
38
+ if (m.token) map[m.id] = m.token
39
+ }
40
+ memberTokens.value = map
41
+ if (!selectedAgent.value) {
42
+ // 默认身份:优先 lead(shared 域写入需 lead)
43
+ const lead = (res.data ?? []).find(m => m.role === 'lead')
44
+ if (lead) selectedAgent.value = lead.id
45
+ }
46
+ }
47
+ catch { /* 拉取失败由手填兜底 */ }
48
+ }
49
+ onMounted(() => void loadMembers())
50
+ watch(() => props.channelId, () => {
51
+ memberTokens.value = {}
52
+ selectedAgent.value = props.agentId ?? ''
53
+ void loadMembers()
54
+ })
55
+
56
+ const authHeaders = computed<Record<string, string>>(() => {
57
+ const h: Record<string, string> = {}
58
+ if (effectiveToken.value) h.authorization = `Bearer ${effectiveToken.value}`
59
+ return h
60
+ })
61
+
62
+ const agents = computed(() => entities.agents[props.channelId] ?? [])
63
+
64
+ const rows = ref<Array<{ id: string, title: string, content: string, kind: string, importance: number, agentId: string }>>([])
65
+ const loading = ref(false)
66
+
67
+ const load = async (): Promise<void> => {
68
+ loading.value = true
69
+ try {
70
+ const url = domain.value === 'shared'
71
+ ? `/api/workshop/channels/${props.channelId}/memories`
72
+ : `/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories`
73
+ const res = await fetch(url, { headers: authHeaders.value })
74
+ const json = await res.json()
75
+ rows.value = json.code === 0 ? json.data : []
76
+ if (json.code !== 0) message.warning(json.message ?? t('memoryPanel.k186sctu014'))
77
+ }
78
+ finally {
79
+ loading.value = false
80
+ }
81
+ }
82
+ watch([domain, selectedAgent, effectiveToken], () => {
83
+ if (effectiveToken.value && (domain.value === 'shared' || selectedAgent.value)) void load()
84
+ })
85
+
86
+ const searchText = ref('')
87
+ const searchScope = ref<'auto' | 'private' | 'shared'>('auto')
88
+ const searchResults = ref<Array<{ id: string, title: string, content: string, score: number, source: string }>>([])
89
+ const searching = ref(false)
90
+ const doSearch = async (): Promise<void> => {
91
+ if (!searchText.value.trim() || !selectedAgent.value || !effectiveToken.value) {
92
+ message.warning(t('memoryPanel.k1eh0fbo015'))
93
+ return
94
+ }
95
+ searching.value = true
96
+ try {
97
+ const res = await fetch(`/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories/search`, {
98
+ method: 'POST',
99
+ headers: { 'content-type': 'application/json', ...authHeaders.value },
100
+ body: JSON.stringify({ query: searchText.value, scope: searchScope.value, limit: 8 }),
101
+ })
102
+ const json = await res.json()
103
+ searchResults.value = json.code === 0 ? json.data : []
104
+ }
105
+ finally {
106
+ searching.value = false
107
+ }
108
+ }
109
+
110
+ const writeOpen = ref(false)
111
+ const writeForm = reactive({ title: '', content: '', scope: 'shared' as 'shared' | 'private', importance: 0.8, dedupKey: '' })
112
+ const doWrite = async (): Promise<void> => {
113
+ if (!writeForm.title || !writeForm.content || !selectedAgent.value || !effectiveToken.value) {
114
+ message.warning(t('memoryPanel.k1dpj734016'))
115
+ return
116
+ }
117
+ const res = await fetch(
118
+ `/api/workshop/channels/${props.channelId}/agents/${selectedAgent.value}/memories`,
119
+ {
120
+ method: 'POST',
121
+ headers: { 'content-type': 'application/json', ...authHeaders.value },
122
+ body: JSON.stringify({ ...writeForm, dedupKey: writeForm.dedupKey || undefined }),
123
+ },
124
+ )
125
+ const json = await res.json()
126
+ if (json.code === 0) {
127
+ message.success(t('memoryPanel.k3n5bat017'))
128
+ writeOpen.value = false
129
+ writeForm.title = ''
130
+ writeForm.content = ''
131
+ void load()
132
+ }
133
+ else {
134
+ message.error(json.message ?? t('memoryPanel.k1bb5i1l018'))
135
+ }
136
+ }
137
+ </script>
138
+
139
+ <template>
140
+ <div class="memory-panel">
141
+ <div class="toolbar">
142
+ <a-radio-group
143
+ v-model:value="domain"
144
+ size="small"
145
+ button-style="solid"
146
+ >
147
+ <a-radio-button value="shared">
148
+ {{ $t('memoryPanel.k3l2hmp005') }}
149
+ </a-radio-button>
150
+ <a-radio-button value="private">
151
+ {{ $t('memoryPanel.k3rve9a006') }}
152
+ </a-radio-button>
153
+ </a-radio-group>
154
+ <a-select
155
+ v-if="!agentId"
156
+ v-model:value="selectedAgent"
157
+ size="small"
158
+ :placeholder="$t('memoryPanel.k1du3379001')"
159
+ class="agent-select"
160
+ :options="agents.map(a => ({ value: a.agentId, label: a.name }))"
161
+ />
162
+ <a-tooltip :title="tokenResolved ? $t('memoryPanel.tokenAuto') : $t('memoryPanel.tokenManual')">
163
+ <span
164
+ class="token-state"
165
+ :data-ok="tokenResolved"
166
+ ><span class="i-tabler-key" />{{ tokenResolved ? 'auto' : $t('memoryPanel.k3zul4013') }}</span>
167
+ </a-tooltip>
168
+ </div>
169
+ <a-input-password
170
+ v-if="!tokenResolved"
171
+ v-model:value="manualToken"
172
+ size="small"
173
+ :placeholder="$t('memoryPanel.tokenPh')"
174
+ class="token"
175
+ />
176
+
177
+ <div class="search-bar">
178
+ <a-input-search
179
+ v-model:value="searchText"
180
+ size="small"
181
+ :placeholder="$t('memoryPanel.searchPh')"
182
+ :loading="searching"
183
+ @search="doSearch"
184
+ />
185
+ <a-select
186
+ v-model:value="searchScope"
187
+ size="small"
188
+ class="scope"
189
+ :options="[{ value: 'auto', label: 'auto' }, { value: 'private', label: 'private' }, { value: 'shared', label: 'shared' }]"
190
+ />
191
+ </div>
192
+ <div
193
+ v-if="searchResults.length"
194
+ class="search-results"
195
+ >
196
+ <div
197
+ v-for="s in searchResults"
198
+ :key="s.id"
199
+ class="hit"
200
+ :title="s.content.slice(0, 200)"
201
+ >
202
+ <span
203
+ class="src"
204
+ :data-source="s.source"
205
+ >{{ s.source }}</span>
206
+ <span class="score">{{ s.score }}</span>
207
+ <span class="hit-title">{{ s.title }}</span>
208
+ </div>
209
+ </div>
210
+
211
+ <div class="list-head">
212
+ <span>{{ $t('memoryPanel.k1k7okbe007') }}</span>
213
+ <a-space size="small">
214
+ <a-button
215
+ size="small"
216
+ type="text"
217
+ @click="load"
218
+ >
219
+ {{ $t('memoryPanel.k3x1jg008') }}
220
+ </a-button>
221
+ <a-button
222
+ size="small"
223
+ type="text"
224
+ @click="writeOpen = true"
225
+ >
226
+ {{ $t('memoryPanel.k3wtib009') }}
227
+ </a-button>
228
+ </a-space>
229
+ </div>
230
+ <a-spin :spinning="loading">
231
+ <div
232
+ v-for="r in rows"
233
+ :key="r.id"
234
+ class="row"
235
+ >
236
+ <div class="row-head">
237
+ <a-tag class="kind">
238
+ {{ r.kind }}
239
+ </a-tag>
240
+ <span class="row-importance">{{ r.importance.toFixed(2) }}</span>
241
+ <span class="row-title">{{ r.title }}</span>
242
+ </div>
243
+ <div class="row-content">
244
+ {{ r.content.slice(0, 140) }}{{ r.content.length > 140 ? '…' : '' }}
245
+ </div>
246
+ </div>
247
+ <div
248
+ v-if="rows.length === 0 && !loading"
249
+ class="empty"
250
+ >
251
+ ({{ $t('memoryPanel.k43rxk011') }}
252
+ </div>
253
+ </a-spin>
254
+
255
+ <a-modal
256
+ v-model:open="writeOpen"
257
+ :title="$t('memoryPanel.k1bbee8p002')"
258
+ :ok-text="$t('memoryPanel.writeOk')"
259
+ :cancel-text="$t('common.cancel')"
260
+ @ok="doWrite"
261
+ >
262
+ <a-form layout="vertical">
263
+ <a-form-item label="scope">
264
+ <a-radio-group v-model:value="writeForm.scope">
265
+ <a-radio value="shared">
266
+ {{ $t('memoryPanel.kemjjvq010') }}
267
+ </a-radio>
268
+ <a-radio value="private">
269
+ private({{ $t('memoryPanel.k3onh9w012') }}
270
+ </a-radio>
271
+ </a-radio-group>
272
+ </a-form-item>
273
+ <a-form-item :label="$t('memoryPanel.k419s4003')">
274
+ <a-input v-model:value="writeForm.title" />
275
+ </a-form-item>
276
+ <a-form-item :label="$t('memoryPanel.k3wv1f004')">
277
+ <a-textarea
278
+ v-model:value="writeForm.content"
279
+ :rows="4"
280
+ />
281
+ </a-form-item>
282
+ <a-form-item label="importance(0-1)">
283
+ <a-input-number
284
+ v-model:value="writeForm.importance"
285
+ :min="0"
286
+ :max="1"
287
+ :step="0.1"
288
+ />
289
+ </a-form-item>
290
+ <a-form-item :label="$t('memoryPanel.dedupLabel')">
291
+ <a-input v-model:value="writeForm.dedupKey" />
292
+ </a-form-item>
293
+ </a-form>
294
+ </a-modal>
295
+ </div>
296
+ </template>
297
+
298
+ <style scoped>
299
+ .memory-panel { font-size: 12px; }
300
+ .toolbar {
301
+ display: flex;
302
+ gap: 6px;
303
+ align-items: center;
304
+ margin-bottom: 6px;
305
+ }
306
+ .agent-select { flex: 1 1 auto; min-width: 90px; }
307
+ .token-state {
308
+ flex: 0 0 auto;
309
+ padding: 0 5px;
310
+ font-family: var(--font-mono);
311
+ font-size: 10px;
312
+ border-radius: var(--radius-chip);
313
+ background: color-mix(in srgb, currentColor 8%, transparent);
314
+ }
315
+ .token-state[data-ok='true'] { color: var(--tone-success-dot); }
316
+ .token-state[data-ok='false'] { color: var(--tone-warning-dot); }
317
+ .token { margin-bottom: 6px; }
318
+ .search-bar {
319
+ display: flex;
320
+ gap: 6px;
321
+ margin-bottom: 6px;
322
+ }
323
+ .scope { width: 90px; }
324
+ .search-results { margin-bottom: 8px; }
325
+ .hit {
326
+ display: flex;
327
+ gap: 6px;
328
+ align-items: center;
329
+ padding: 2px 4px;
330
+ font-family: var(--font-mono);
331
+ font-size: 11px;
332
+ }
333
+ .src {
334
+ padding: 0 4px;
335
+ color: var(--tone-info-dot);
336
+ background: var(--tone-info-bg);
337
+ border-radius: var(--radius-chip);
338
+ }
339
+ .src[data-source='shared'] {
340
+ color: var(--tone-retry-dot);
341
+ background: var(--tone-retry-bg);
342
+ }
343
+ .score { opacity: 0.5; }
344
+ .hit-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
345
+ .list-head {
346
+ display: flex;
347
+ align-items: center;
348
+ justify-content: space-between;
349
+ padding: 4px 0;
350
+ font-weight: 600;
351
+ opacity: 0.7;
352
+ }
353
+ .row { padding: 4px 0; border-bottom: 1px dashed color-mix(in srgb, currentColor 10%, transparent); }
354
+ .row-head { display: flex; gap: 6px; align-items: center; }
355
+ .kind { margin-inline-end: 0; font-size: 10px; }
356
+ .row-importance { font-family: var(--font-mono); font-size: 10px; opacity: 0.5; }
357
+ .row-title { font-weight: 600; font-size: 12px; }
358
+ .row-content {
359
+ font-size: 11px;
360
+ opacity: 0.65;
361
+ word-break: break-all;
362
+ }
363
+ .empty { padding: 8px 0; opacity: 0.4; }
364
+ </style>