agentworkshop 0.7.60 → 0.7.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/{KXQppTXc.js → BTXdYngG.js} +1 -1
- package/.output/public/_nuxt/{Ce5SiMQR2.js → BXbKTAwC2.js} +1 -1
- package/.output/public/_nuxt/B_6yBa_Z.js +1 -0
- package/.output/public/_nuxt/B_ic601Y.js +1 -0
- package/.output/public/_nuxt/{DhSlJyZD2.js → BegV7-FE2.js} +1 -1
- package/.output/public/_nuxt/{D9sgxxsM2.js → BrRXGr472.js} +1 -1
- package/.output/public/_nuxt/{BeNdseTX.js → BtBgrPNT.js} +1 -1
- package/.output/public/_nuxt/{Cyd68Xbv2.js → C5MPzgon2.js} +1 -1
- package/.output/public/_nuxt/{DBdwjOGB2.js → CI5sliIF2.js} +1 -1
- package/.output/public/_nuxt/CI8awYVQ2.js +1 -0
- package/.output/public/_nuxt/{Cfp00Rdo.js → CK2ts9sD.js} +1 -1
- package/.output/public/_nuxt/{BjUpWKS6.js → CPZKwmLQ.js} +1 -1
- package/.output/public/_nuxt/{CjeMxUv8.js → CVUMEGa1.js} +1 -1
- package/.output/public/_nuxt/{p2sDc0tO2.js → CcLFZjCI2.js} +1 -1
- package/.output/public/_nuxt/{C4AICl3l.js → CeEzUIvN.js} +4 -4
- package/.output/public/_nuxt/{C93LpBMF.js → CfIGBe_4.js} +3 -3
- package/.output/public/_nuxt/{DTcsb0fG.js → Ci5kuU1q.js} +1 -1
- package/.output/public/_nuxt/CiyTTgqr.js +106 -0
- package/.output/public/_nuxt/{CgbP5yJk2.js → CkYk8bj02.js} +7 -7
- package/.output/public/_nuxt/Cmiz_VOb2.js +47 -0
- package/.output/public/_nuxt/Cnf1PFhB2.js +1 -0
- package/.output/public/_nuxt/CoTm7jd3.js +28 -0
- package/.output/public/_nuxt/{C0sNwDTK2.js → CsN8RHJ02.js} +1 -1
- package/.output/public/_nuxt/D-jg-SoR.js +1 -0
- package/.output/public/_nuxt/{CEHT9inW.js → D-z6N1Cz.js} +1 -1
- package/.output/public/_nuxt/D3gfSKKi2.js +1 -0
- package/.output/public/_nuxt/D4elH6Bo2.js +1 -0
- package/.output/public/_nuxt/{C5OSTzBh.js → D4tAdwYm.js} +1 -1
- package/.output/public/_nuxt/{BlEJRYAn2.js → DC7WzYCf2.js} +1 -1
- package/.output/public/_nuxt/{VeOVO2sE2.js → DE-qkHRd2.js} +1 -1
- package/.output/public/_nuxt/DE2kUGPK.js +1 -0
- package/.output/public/_nuxt/DI4sdLmu2.js +1 -0
- package/.output/public/_nuxt/DKHA3XxF.js +2 -0
- package/.output/public/_nuxt/{zVupTo2z2.js → DL6fliAT.js} +2 -2
- package/.output/public/_nuxt/{CMDAjShv2.js → DP6tsk912.js} +1 -1
- package/.output/public/_nuxt/DP_e7Vwv.js +24 -0
- package/.output/public/_nuxt/{C8XVZGSZ.js → DR83EvmX.js} +1 -1
- package/.output/public/_nuxt/{BtXwFpv42.js → DSWuWYx_2.js} +1 -1
- package/.output/public/_nuxt/DSdxfFX_.js +1 -0
- package/.output/public/_nuxt/DVS06wUy2.js +13 -0
- package/.output/public/_nuxt/DXlAfhEi.js +3 -0
- package/.output/public/_nuxt/Dc5NeCDq.js +1 -0
- package/.output/public/_nuxt/{B_JLVF30.js → DiHL9ehB.js} +1 -1
- package/.output/public/_nuxt/{Bdq2LNSO.js → DjtDexGg.js} +1 -1
- package/.output/public/_nuxt/DnunMTRD2.js +1 -0
- package/.output/public/_nuxt/{KXvRkBgg.js → Dok0B4Ol.js} +2 -2
- package/.output/public/_nuxt/{BFBysc2M2.js → DqT2_Jtw2.js} +1 -1
- package/.output/public/_nuxt/{B_BYwIf22.js → DtMlAxCm2.js} +1 -1
- package/.output/public/_nuxt/{BplhglEM.js → DwzJpr7P.js} +1 -1
- package/.output/public/_nuxt/J94L7hHq2.js +1 -0
- package/.output/public/_nuxt/LQBLwrYS2.js +1 -0
- package/.output/public/_nuxt/QSY9fE482.js +1 -0
- package/.output/public/_nuxt/{iCvdSYYN2.js → Qa9rS9oK2.js} +2 -2
- package/.output/public/_nuxt/{Cyuxcv5s2.js → R3gBFghJ2.js} +1 -1
- package/.output/public/_nuxt/ZxBwmbs9.js +1 -0
- package/.output/public/_nuxt/{BGFhOMVM.js → _mD4IkJj.js} +2 -2
- package/.output/public/_nuxt/analysis.DfMg76el.css +1 -0
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/eba8574d-1991-47df-944c-18608bb58181.json +1 -0
- package/.output/public/_nuxt/{CZmMgjIK.js → c_nqArmG.js} +1 -1
- package/.output/public/_nuxt/h8ddxY892.js +1 -0
- package/.output/public/_nuxt/i3KBHle7.js +1 -0
- package/.output/public/_nuxt/jmKfTQMN.js +13 -0
- package/.output/public/_nuxt/{59a6cSgj.js → taHLOXkS.js} +1 -1
- package/.output/public/_nuxt/{EQijmkCh2.js → uYP6z4G72.js} +1 -1
- package/.output/public/_nuxt/{D0vmf1z9.js → yuIP6K9s.js} +1 -1
- package/.output/public/_nuxt/{Ddc_Pn7D.js → zWg-9WN6.js} +4 -4
- package/.output/public/_nuxt/zrgcKVTq.js +2 -0
- package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
- package/.output/server/chunks/_/host-bindings.mjs +1 -1
- package/.output/server/chunks/_/nitro.mjs +1158 -1111
- package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
- package/.output/server/chunks/build/{AuthGate-CZYkvPrg.mjs → AuthGate-BK2RqkbD.mjs} +5 -5
- package/.output/server/chunks/build/{AuthGate-CZYkvPrg.mjs.map → AuthGate-BK2RqkbD.mjs.map} +1 -1
- package/.output/server/chunks/build/{FormItemContext-DcWIIAaK.mjs → FormItemContext-BqtgOBDe.mjs} +1 -1
- package/.output/server/chunks/build/{FormItemContext-DcWIIAaK.mjs.map → FormItemContext-BqtgOBDe.mjs.map} +1 -1
- package/.output/server/chunks/build/{OmpTerminalPanel-CtFJ6Kc8.mjs → OmpTerminalPanel-Bun6rpAk.mjs} +4 -4
- package/.output/server/chunks/build/{OmpTerminalPanel-CtFJ6Kc8.mjs.map → OmpTerminalPanel-Bun6rpAk.mjs.map} +1 -1
- package/.output/server/chunks/build/{PluginSlot-BT7kYQgK.mjs → PluginSlot-Do6dX0RE.mjs} +1 -1
- package/.output/server/chunks/build/{PluginSlot-BT7kYQgK.mjs.map → PluginSlot-Do6dX0RE.mjs.map} +1 -1
- package/.output/server/chunks/build/{_wsId_-DOEw9jgZ.mjs → _wsId_-Dp3ACbQ5.mjs} +19 -19
- package/.output/server/chunks/build/{_wsId_-DOEw9jgZ.mjs.map → _wsId_-Dp3ACbQ5.mjs.map} +1 -1
- package/.output/server/chunks/build/{agents-C36wR56A.mjs → agents-BfIoGr_p.mjs} +18 -18
- package/.output/server/chunks/build/{agents-C36wR56A.mjs.map → agents-BfIoGr_p.mjs.map} +1 -1
- package/.output/server/chunks/build/{aml-CBGndvHT.mjs → aml-B5zKrvB3.mjs} +7 -7
- package/.output/server/chunks/build/{aml-CBGndvHT.mjs.map → aml-B5zKrvB3.mjs.map} +1 -1
- package/.output/server/chunks/build/analysis-MVEnlO7A.mjs +531 -0
- package/.output/server/chunks/build/analysis-MVEnlO7A.mjs.map +1 -0
- package/.output/server/chunks/build/{card-Db7OB49d.mjs → card-IyQjdGXA.mjs} +3 -3
- package/.output/server/chunks/build/{card-Db7OB49d.mjs.map → card-IyQjdGXA.mjs.map} +1 -1
- package/.output/server/chunks/build/{channel-templates-BixUrDmU.mjs → channel-templates-Bd8bgBCh.mjs} +11 -11
- package/.output/server/chunks/build/{channel-templates-BixUrDmU.mjs.map → channel-templates-Bd8bgBCh.mjs.map} +1 -1
- package/.output/server/chunks/build/{checkbox-CyF96D30.mjs → checkbox-NnjtOam0.mjs} +2 -2
- package/.output/server/chunks/build/{checkbox-CyF96D30.mjs.map → checkbox-NnjtOam0.mjs.map} +1 -1
- package/.output/server/chunks/build/{daq-DLMLufDq.mjs → daq-mC3-5A0L.mjs} +1 -1
- package/.output/server/chunks/build/{daq-DLMLufDq.mjs.map → daq-mC3-5A0L.mjs.map} +1 -1
- package/.output/server/chunks/build/{default-C7Qmdyz_.mjs → default-flcNWlNg.mjs} +12 -12
- package/.output/server/chunks/build/{default-C7Qmdyz_.mjs.map → default-flcNWlNg.mjs.map} +1 -1
- package/.output/server/chunks/build/{descriptions-1bH81YsZ.mjs → descriptions-DuAefuzp.mjs} +1 -1
- package/.output/server/chunks/build/{descriptions-1bH81YsZ.mjs.map → descriptions-DuAefuzp.mjs.map} +1 -1
- package/.output/server/chunks/build/{drawer-C7shdEHy.mjs → drawer-DEIB1_X6.mjs} +1 -1
- package/.output/server/chunks/build/{drawer-C7shdEHy.mjs.map → drawer-DEIB1_X6.mjs.map} +1 -1
- package/.output/server/chunks/build/{dropdown-BiwcuXDi.mjs → dropdown-BuD1pxH2.mjs} +5 -5
- package/.output/server/chunks/build/{dropdown-BiwcuXDi.mjs.map → dropdown-BuD1pxH2.mjs.map} +1 -1
- package/.output/server/chunks/build/{dropdown-BhLSIp5A.mjs → dropdown-w7qhyN2D.mjs} +2 -2
- package/.output/server/chunks/build/{dropdown-BhLSIp5A.mjs.map → dropdown-w7qhyN2D.mjs.map} +1 -1
- package/.output/server/chunks/build/es-DfgEl5n-.mjs +42 -0
- package/.output/server/chunks/build/es-DfgEl5n-.mjs.map +1 -0
- package/.output/server/chunks/build/{form-nE8C0G8B.mjs → form-CMLL_-Xx.mjs} +6 -6
- package/.output/server/chunks/build/{form-nE8C0G8B.mjs.map → form-CMLL_-Xx.mjs.map} +1 -1
- package/.output/server/chunks/build/{input-DwF72eVI.mjs → input-DZcioTwL.mjs} +3 -3
- package/.output/server/chunks/build/{input-DwF72eVI.mjs.map → input-DZcioTwL.mjs.map} +1 -1
- package/.output/server/chunks/build/{input-number-TSq6ltkz.mjs → input-number-BRnbiKLd.mjs} +5 -5
- package/.output/server/chunks/build/{input-number-TSq6ltkz.mjs.map → input-number-BRnbiKLd.mjs.map} +1 -1
- package/.output/server/chunks/build/{logs-hOEVuxqm.mjs → logs-BYop3JfX.mjs} +2 -2
- package/.output/server/chunks/build/{logs-hOEVuxqm.mjs.map → logs-BYop3JfX.mjs.map} +1 -1
- package/.output/server/chunks/build/{menu-Cy5Nrecn.mjs → menu-DXfhc0qN.mjs} +3 -3
- package/.output/server/chunks/build/{menu-Cy5Nrecn.mjs.map → menu-DXfhc0qN.mjs.map} +1 -1
- package/.output/server/chunks/build/{monitor-CfVoiavp.mjs → monitor-BjBGkUm2.mjs} +19 -19
- package/.output/server/chunks/build/{monitor-CfVoiavp.mjs.map → monitor-BjBGkUm2.mjs.map} +1 -1
- package/.output/server/chunks/build/{permissions-XPtQJSaO.mjs → permissions-u5SZL8Fe.mjs} +14 -14
- package/.output/server/chunks/build/{permissions-XPtQJSaO.mjs.map → permissions-u5SZL8Fe.mjs.map} +1 -1
- package/.output/server/chunks/build/{plugins-DjBSG9pV.mjs → plugins-Cas6KOF-.mjs} +5 -5
- package/.output/server/chunks/build/{plugins-DjBSG9pV.mjs.map → plugins-Cas6KOF-.mjs.map} +1 -1
- package/.output/server/chunks/build/{popconfirm-DKeEbaGd.mjs → popconfirm-BWxt-53K.mjs} +2 -2
- package/.output/server/chunks/build/{popconfirm-DKeEbaGd.mjs.map → popconfirm-BWxt-53K.mjs.map} +1 -1
- package/.output/server/chunks/build/{schedules-PcDLCUWN.mjs → schedules-Ct68Jrvw.mjs} +19 -19
- package/.output/server/chunks/build/{schedules-PcDLCUWN.mjs.map → schedules-Ct68Jrvw.mjs.map} +1 -1
- package/.output/server/chunks/build/{segmented-BdWCdZUM.mjs → segmented-DN62bOFu.mjs} +2 -2
- package/.output/server/chunks/build/{segmented-BdWCdZUM.mjs.map → segmented-DN62bOFu.mjs.map} +1 -1
- package/.output/server/chunks/build/{select-C5yighj8.mjs → select-DQv1DXcW.mjs} +4 -4
- package/.output/server/chunks/build/{select-C5yighj8.mjs.map → select-DQv1DXcW.mjs.map} +1 -1
- package/.output/server/chunks/build/{settings-90zT_h9w.mjs → settings-CQzR1YXR.mjs} +13 -13
- package/.output/server/chunks/build/{settings-90zT_h9w.mjs.map → settings-CQzR1YXR.mjs.map} +1 -1
- package/.output/server/chunks/build/{space-BCffbXIG.mjs → space-6FfG3llN.mjs} +3 -3
- package/.output/server/chunks/build/{space-BCffbXIG.mjs.map → space-6FfG3llN.mjs.map} +1 -1
- package/.output/server/chunks/build/{switch-OG0SM_Px.mjs → switch-CfsCVFQP.mjs} +2 -2
- package/.output/server/chunks/build/{switch-OG0SM_Px.mjs.map → switch-CfsCVFQP.mjs.map} +1 -1
- package/.output/server/chunks/build/{table-UpVzu50c.mjs → table-HOjbB5YY.mjs} +9 -9
- package/.output/server/chunks/build/{table-UpVzu50c.mjs.map → table-HOjbB5YY.mjs.map} +1 -1
- package/.output/server/chunks/build/{tabs-CWwoL33v.mjs → tabs-CC26Rbcw.mjs} +4 -4
- package/.output/server/chunks/build/{tabs-CWwoL33v.mjs.map → tabs-CC26Rbcw.mjs.map} +1 -1
- package/.output/server/chunks/build/{tag-CS7mwrfG.mjs → tag-BtOMjpDx.mjs} +4 -4
- package/.output/server/chunks/build/{tag-CS7mwrfG.mjs.map → tag-BtOMjpDx.mjs.map} +1 -1
- package/.output/server/chunks/build/{teams-BIAFvRw1.mjs → teams-Re0wY2SQ.mjs} +19 -19
- package/.output/server/chunks/build/{teams-BIAFvRw1.mjs.map → teams-Re0wY2SQ.mjs.map} +1 -1
- package/.output/server/chunks/build/{tokens-CLpdrzQ7.mjs → tokens-DLFIUvXE.mjs} +19 -19
- package/.output/server/chunks/build/{tokens-CLpdrzQ7.mjs.map → tokens-DLFIUvXE.mjs.map} +1 -1
- package/.output/server/chunks/build/{tooltip-CJlH_8ZK.mjs → tooltip-BSDwL_LM.mjs} +4 -4
- package/.output/server/chunks/build/{tooltip-CJlH_8ZK.mjs.map → tooltip-BSDwL_LM.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateActions-6VyAHgu5.mjs → useAgentTemplateActions-CjBwCb3u.mjs} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateActions-6VyAHgu5.mjs.map → useAgentTemplateActions-CjBwCb3u.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateForm-DWa-ezNq.mjs → useAgentTemplateForm-BX9_xqj8.mjs} +1 -1
- package/.output/server/chunks/build/{useAgentTemplateForm-DWa-ezNq.mjs.map → useAgentTemplateForm-BX9_xqj8.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlEntities-Co2fgjzh.mjs → useAmlEntities-BrcTqHwa.mjs} +2 -2
- package/.output/server/chunks/build/{useAmlEntities-Co2fgjzh.mjs.map → useAmlEntities-BrcTqHwa.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlEnv-JTiWPrzH.mjs → useAmlEnv-jiGYK790.mjs} +1 -1
- package/.output/server/chunks/build/{useAmlEnv-JTiWPrzH.mjs.map → useAmlEnv-jiGYK790.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlJobs-By4pjOzc.mjs → useAmlJobs-CVZ1btzg.mjs} +1 -1
- package/.output/server/chunks/build/{useAmlJobs-By4pjOzc.mjs.map → useAmlJobs-CVZ1btzg.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlModels-B1_5vjMA.mjs → useAmlModels-DJkQzcCU.mjs} +1 -1
- package/.output/server/chunks/build/{useAmlModels-B1_5vjMA.mjs.map → useAmlModels-DJkQzcCU.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlNotes-5uwvCb3h.mjs → useAmlNotes-DKnx9a8x.mjs} +1 -1
- package/.output/server/chunks/build/{useAmlNotes-5uwvCb3h.mjs.map → useAmlNotes-DKnx9a8x.mjs.map} +1 -1
- package/.output/server/chunks/build/{useAmlPredict-lxUv7lAO.mjs → useAmlPredict-Bp4ehwKw.mjs} +1 -1
- package/.output/server/chunks/build/{useAmlPredict-lxUv7lAO.mjs.map → useAmlPredict-Bp4ehwKw.mjs.map} +1 -1
- package/.output/server/chunks/build/{useLogsManual-BLfiSU3u.mjs → useLogsManual-CElmZuJh.mjs} +1 -1
- package/.output/server/chunks/build/{useLogsManual-BLfiSU3u.mjs.map → useLogsManual-CElmZuJh.mjs.map} +1 -1
- package/.output/server/chunks/build/{useMonitorData-BZ6Z-Sy8.mjs → useMonitorData-DcIfMEiz.mjs} +1 -1
- package/.output/server/chunks/build/{useMonitorData-BZ6Z-Sy8.mjs.map → useMonitorData-DcIfMEiz.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamActions-ahht5J8Y.mjs → useTeamActions-C3_O_AIU.mjs} +1 -1
- package/.output/server/chunks/build/{useTeamActions-ahht5J8Y.mjs.map → useTeamActions-C3_O_AIU.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamAddMemberDialog-DvXxsVy0.mjs → useTeamAddMemberDialog-DWAoZCKd.mjs} +1 -1
- package/.output/server/chunks/build/{useTeamAddMemberDialog-DvXxsVy0.mjs.map → useTeamAddMemberDialog-DWAoZCKd.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamCreateDialog-A_k-XX5B.mjs → useTeamCreateDialog-911mIPWd.mjs} +1 -1
- package/.output/server/chunks/build/{useTeamCreateDialog-A_k-XX5B.mjs.map → useTeamCreateDialog-911mIPWd.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamDeployDialog-CfAFjIr_.mjs → useTeamDeployDialog-D0STROoQ.mjs} +1 -1
- package/.output/server/chunks/build/{useTeamDeployDialog-CfAFjIr_.mjs.map → useTeamDeployDialog-D0STROoQ.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTeamPluginDialog-Djmkk1Nl.mjs → useTeamPluginDialog-Df6-e2OW.mjs} +1 -1
- package/.output/server/chunks/build/{useTeamPluginDialog-Djmkk1Nl.mjs.map → useTeamPluginDialog-Df6-e2OW.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTokenCreate-CkWoxSI-.mjs → useTokenCreate-DOojAhM5.mjs} +1 -1
- package/.output/server/chunks/build/{useTokenCreate-CkWoxSI-.mjs.map → useTokenCreate-DOojAhM5.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTokenRename-BohjnGT0.mjs → useTokenRename-CMA5dLHx.mjs} +1 -1
- package/.output/server/chunks/build/{useTokenRename-BohjnGT0.mjs.map → useTokenRename-CMA5dLHx.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTokenReveal-BBN5iGz7.mjs → useTokenReveal-C19aCKzt.mjs} +1 -1
- package/.output/server/chunks/build/{useTokenReveal-BBN5iGz7.mjs.map → useTokenReveal-C19aCKzt.mjs.map} +1 -1
- package/.output/server/chunks/build/{useTokensList-BQX9WqfT.mjs → useTokensList-D0ZpLOhR.mjs} +1 -1
- package/.output/server/chunks/build/{useTokensList-BQX9WqfT.mjs.map → useTokensList-D0ZpLOhR.mjs.map} +1 -1
- package/.output/server/chunks/build/{useWorkbenchAuth-BTRlS2wZ.mjs → useWorkbenchAuth-CN5E3J5L.mjs} +1 -1
- package/.output/server/chunks/build/{useWorkbenchAuth-BTRlS2wZ.mjs.map → useWorkbenchAuth-CN5E3J5L.mjs.map} +1 -1
- package/.output/server/chunks/build/{useWorkbenchWorkspaces-C6ky7OJH.mjs → useWorkbenchWorkspaces-ChKByQSD.mjs} +1 -1
- package/.output/server/chunks/build/{useWorkbenchWorkspaces-C6ky7OJH.mjs.map → useWorkbenchWorkspaces-ChKByQSD.mjs.map} +1 -1
- package/.output/server/chunks/build/{users-BHOEW3Az.mjs → users-BW4jowK4.mjs} +15 -15
- package/.output/server/chunks/build/{users-BHOEW3Az.mjs.map → users-BW4jowK4.mjs.map} +1 -1
- package/.output/server/chunks/build/{workshop-DyJ1LXwu.mjs → workshop-Bx55czXL.mjs} +11 -11
- package/.output/server/chunks/build/{workshop-DyJ1LXwu.mjs.map → workshop-Bx55czXL.mjs.map} +1 -1
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.get.mjs +3 -2
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.patch.mjs +103 -0
- package/.output/server/chunks/routes/api/workshop/analysis/_id_.patch.mjs.map +1 -0
- package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/channels.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/index7.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.get.mjs +6 -2
- package/.output/server/chunks/routes/api/workshop/index3.get.mjs.map +1 -1
- package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
- package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
- package/.output/server/chunks/routes/renderer.mjs +2 -2
- package/.output/server/chunks/virtual/entry.mjs +533 -529
- package/.output/server/chunks/virtual/entry.mjs.map +1 -1
- package/.output/server/chunks/virtual/precomputed.mjs +1 -1
- package/.output/server/package.json +1 -1
- package/app/components/analysis/AnalysisEditModal.vue +192 -0
- package/app/components/analysis/AnalysisFilterCard.vue +159 -160
- package/app/components/analysis/AnalysisPageHead.vue +47 -47
- package/app/components/analysis/AnalysisTable.vue +322 -306
- package/app/pages/analysis/composables/useAnalysisFeed.ts +85 -85
- package/app/pages/analysis/index.vue +128 -92
- package/app/pages/analysis/types.ts +50 -44
- package/i18n/locales/en.ts +8 -0
- package/i18n/locales/zh-CN.ts +8 -0
- package/package.json +1 -1
- package/server/api/workshop/analysis/[id].delete.ts +30 -30
- package/server/api/workshop/analysis/[id].get.ts +25 -23
- package/server/api/workshop/analysis/[id].patch.ts +100 -0
- package/server/api/workshop/analysis/index.get.ts +39 -33
- package/server/services/workshop/agents/industrial/analysis-tools.ts +242 -242
- package/server/services/workshop/analysis/analysis.repo.ts +241 -189
- package/server/services/workshop/db/database/migrations.ts +10 -0
- package/server/services/workshop/db/database/open.ts +3 -1
- package/server/services/workshop/db/database/schema.ts +6 -2
- package/server/services/workshop/db/schema.sql +6 -2
- package/.output/public/_nuxt/5juo_WO2.js +0 -13
- package/.output/public/_nuxt/B-WTxXEK2.js +0 -1
- package/.output/public/_nuxt/B1BCga5h2.js +0 -13
- package/.output/public/_nuxt/B5lMtA7I2.js +0 -1
- package/.output/public/_nuxt/B6_fJd2X.js +0 -1
- package/.output/public/_nuxt/B7K5B04W2.js +0 -1
- package/.output/public/_nuxt/B7KyS_q2.js +0 -1
- package/.output/public/_nuxt/B8q3BGY5.js +0 -37
- package/.output/public/_nuxt/B9IK8kDl2.js +0 -1
- package/.output/public/_nuxt/BNd2NDxg2.js +0 -1
- package/.output/public/_nuxt/BP629NAi.js +0 -1
- package/.output/public/_nuxt/BVinTfuN.js +0 -1
- package/.output/public/_nuxt/BdE41Y_c.js +0 -28
- package/.output/public/_nuxt/Be_StT8b2.js +0 -1
- package/.output/public/_nuxt/BsYEYxWv.js +0 -24
- package/.output/public/_nuxt/BuNXYpib2.js +0 -1
- package/.output/public/_nuxt/CDaZC0_6.js +0 -3
- package/.output/public/_nuxt/CE43-V_L.js +0 -2
- package/.output/public/_nuxt/CWfBtswB.js +0 -70
- package/.output/public/_nuxt/CYtH1bv2.js +0 -1
- package/.output/public/_nuxt/ChPNKPw_.js +0 -1
- package/.output/public/_nuxt/CktUrk8z.js +0 -1
- package/.output/public/_nuxt/DMCoWgSb2.js +0 -1
- package/.output/public/_nuxt/Dg1iMuZ-.js +0 -1
- package/.output/public/_nuxt/DmwMkvoQ2.js +0 -1
- package/.output/public/_nuxt/LwITbamf2.js +0 -47
- package/.output/public/_nuxt/_jfzcYrl.js +0 -1
- package/.output/public/_nuxt/analysis.D2Pao1rm.css +0 -1
- package/.output/public/_nuxt/builds/meta/f78a1992-e424-494d-ac4b-aa18971ffc10.json +0 -1
- package/.output/server/chunks/build/analysis-tgzvOWmD.mjs +0 -332
- package/.output/server/chunks/build/analysis-tgzvOWmD.mjs.map +0 -1
|
@@ -1,242 +1,242 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 数据分析系统 · 分析报告留痕工具(analysis_save / analysis_query)。
|
|
3
|
-
*
|
|
4
|
-
* 定位:Agent Channel 把分析产出(关键结论/正文/支撑指标)持久化到平台台账,
|
|
5
|
-
* 实现"分析结果可留痕、随时可查回"。台账 append-only —— 本族无更新/删除工具
|
|
6
|
-
* (删仅 REST admin 面),保证留痕不可变。
|
|
7
|
-
*
|
|
8
|
-
* 权限语义(同族只读工具口径):
|
|
9
|
-
* - 目标产线解析:显式 line_id(须在可见范围)→ 频道绑线兜底 → 都没有则拒。
|
|
10
|
-
* - 可见产线 = 节点授权线 ∪ 绑定配方所在线 ∪ 频道绑线(agentOpsScope)。
|
|
11
|
-
* - 不进 WRITE_TOOLS/grant-guard 写族:留痕是台账写入,非产线控制写;
|
|
12
|
-
* 能读该产线数据(≥readonly)的 Agent 才能留痕。
|
|
13
|
-
*/
|
|
14
|
-
import { randomUUID } from 'node:crypto'
|
|
15
|
-
import { agentBadgeLabel } from '../agent-badge'
|
|
16
|
-
import { getDcwController } from '../../dcw/dcw-controller'
|
|
17
|
-
import { getDcwLineRepo } from '../../dcw/dcw-line.repo'
|
|
18
|
-
import { recordOps } from '../../ops/ops'
|
|
19
|
-
import { getAnalysisRepo } from '../../analysis/analysis.repo'
|
|
20
|
-
import { agentOpsScope, channelBoundLineId, fmtAuditAt } from './ops-tools'
|
|
21
|
-
|
|
22
|
-
export interface AnalysisSaveInput {
|
|
23
|
-
title?: string
|
|
24
|
-
summary?: string
|
|
25
|
-
conclusions?: string[] | string
|
|
26
|
-
report?: string
|
|
27
|
-
category?: string
|
|
28
|
-
line_id?: string
|
|
29
|
-
recipe_id?: string
|
|
30
|
-
recipe_version?: string
|
|
31
|
-
window_from?: string
|
|
32
|
-
window_to?: string
|
|
33
|
-
data_sources?: string
|
|
34
|
-
metrics?: Record<string, unknown>
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface AnalysisQueryInput {
|
|
38
|
-
report_id?: string
|
|
39
|
-
line_id?: string
|
|
40
|
-
recipe_id?: string
|
|
41
|
-
category?: string
|
|
42
|
-
q?: string
|
|
43
|
-
from?: string
|
|
44
|
-
to?: string
|
|
45
|
-
limit?: number | string
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** 可见产线全集 = 节点授权线 ∪ 绑定配方所在线 ∪ 频道绑线(去重) */
|
|
49
|
-
function readableLineIdsOf(agentId: string): string[] {
|
|
50
|
-
const bound = channelBoundLineId(agentId)
|
|
51
|
-
const scope = agentOpsScope(agentId)
|
|
52
|
-
if (!scope) return bound ? [bound] : []
|
|
53
|
-
return [...new Set([...scope.lineIds, ...scope.boundLineIds, ...(bound ? [bound] : [])])]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** 目标产线解析:显式 line_id(须可读)→ 频道绑线兜底;返回产线视图或错误文案 */
|
|
57
|
-
function resolveTargetLine(agentId: string, explicitLineId?: string): { lineId: string, lineName: string } | { error: string } {
|
|
58
|
-
const lineRepo = getDcwLineRepo()
|
|
59
|
-
const wanted = String(explicitLineId ?? '').trim() || channelBoundLineId(agentId)
|
|
60
|
-
if (!wanted) {
|
|
61
|
-
return { error: '无法确定目标产线:本频道未绑定产线,且未指定 line_id。请先绑线,或显式传入可见范围内的 line_id。' }
|
|
62
|
-
}
|
|
63
|
-
const line = lineRepo.byId(wanted)
|
|
64
|
-
if (!line) return { error: `产线不存在: ${wanted}` }
|
|
65
|
-
const readable = readableLineIdsOf(agentId)
|
|
66
|
-
if (!readable.includes(wanted)) {
|
|
67
|
-
return { error: `产线「${line.name}」不在你的可见范围(节点授权线/绑定配方线/频道绑线)。只能对可见产线留痕。` }
|
|
68
|
-
}
|
|
69
|
-
return { lineId: line.id, lineName: line.name }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** 时间入参归一:epoch ms 数值串或 ISO 均收,统一出 ISO;无效返回 null(留空=未指明) */
|
|
73
|
-
function normTimeArg(raw: unknown): string | null {
|
|
74
|
-
const s = String(raw ?? '').trim()
|
|
75
|
-
if (!s) return null
|
|
76
|
-
if (/^\d{10,}$/.test(s)) {
|
|
77
|
-
const ms = Number(s)
|
|
78
|
-
return Number.isFinite(ms) ? new Date(ms).toISOString() : null
|
|
79
|
-
}
|
|
80
|
-
const t = Date.parse(s)
|
|
81
|
-
return Number.isNaN(t) ? null : new Date(t).toISOString()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** conclusions 归一:接受 string[] 或换行分隔的整段字符串(LLM 两种形态都常见) */
|
|
85
|
-
function normConclusions(raw: AnalysisSaveInput['conclusions']): string[] {
|
|
86
|
-
if (Array.isArray(raw)) return raw.map(x => String(x).trim()).filter(Boolean)
|
|
87
|
-
return String(raw ?? '')
|
|
88
|
-
.split('\n')
|
|
89
|
-
.map(x => x.replace(/^[-*\d.\s]+/, '').trim())
|
|
90
|
-
.filter(Boolean)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** 频道名快照(归因用;经全局 manager 直读,未装配/直调上下文留空 —— 同 channelBoundLineId 模式) */
|
|
94
|
-
function channelNameOf(channelId?: string): string {
|
|
95
|
-
if (!channelId) return ''
|
|
96
|
-
try {
|
|
97
|
-
const g = globalThis as typeof globalThis & {
|
|
98
|
-
__workshopManager?: { deps: { repos: { channels: { findById(id: string): { name?: string } | undefined } } } }
|
|
99
|
-
}
|
|
100
|
-
return g.__workshopManager?.deps.repos.channels.findById(channelId)?.name ?? ''
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return ''
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** 产线上下文快照:保存瞬间把产品/批次/控制模式固化进台账 */
|
|
108
|
-
function lineContextSnapshot(lineId: string): Record<string, unknown> {
|
|
109
|
-
try {
|
|
110
|
-
const ctrl = getDcwController()
|
|
111
|
-
const st = ctrl.lineState(lineId)
|
|
112
|
-
const line = getDcwLineRepo().byId(lineId)
|
|
113
|
-
return {
|
|
114
|
-
controlMode: line?.controlMode ?? '',
|
|
115
|
-
activeRun: st?.active
|
|
116
|
-
? { runId: st.runId, recipeName: st.recipeName, productName: st.productName, startedAt: st.startedAt }
|
|
117
|
-
: null,
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
return {}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** 工具:analysis_save —— 把本次分析的关键结论与产出持久化到平台分析台账(数据留痕)。 */
|
|
126
|
-
export async function toolAnalysisSave(agentId: string, args: AnalysisSaveInput, channelId?: string): Promise<{ text: string, isError?: boolean }> {
|
|
127
|
-
const title = String(args.title ?? '').trim()
|
|
128
|
-
const summary = String(args.summary ?? '').trim()
|
|
129
|
-
if (!title) return { text: 'title 必填:分析主题(如「BOPET 线膜厚漂移根因分析」),台账列表靠它辨认。', isError: true }
|
|
130
|
-
if (!summary) return { text: 'summary 必填:一句话关键结论 —— 这是留痕的核心产出,人扫一眼列表要能看懂。', isError: true }
|
|
131
|
-
|
|
132
|
-
const line = resolveTargetLine(agentId, args.line_id)
|
|
133
|
-
if ('error' in line) return { text: line.error, isError: true }
|
|
134
|
-
|
|
135
|
-
// 配方联动:校验存在性 + 归属(留痕的 recipe 字段要可信)
|
|
136
|
-
const recipeId = String(args.recipe_id ?? '').trim()
|
|
137
|
-
let recipeVersion = String(args.recipe_version ?? '').trim()
|
|
138
|
-
if (recipeId) {
|
|
139
|
-
const recipe = getDcwController().listRecipes().find(r => r.id === recipeId)
|
|
140
|
-
if (!recipe) return { text: `配方 ${recipeId} 不存在,recipe_id 留痕被拒(可用 line_context 查看当前配方)。`, isError: true }
|
|
141
|
-
if (recipe.lineId && recipe.lineId !== line.lineId) {
|
|
142
|
-
return { text: `配方「${recipe.name}」不属于产线「${line.lineName}」,不能挂到该线的分析报告下。`, isError: true }
|
|
143
|
-
}
|
|
144
|
-
if (!recipeVersion) recipeVersion = String(recipe.version ?? '')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const channelName = channelNameOf(channelId)
|
|
148
|
-
const id = `ar-${randomUUID().replace(/-/g, '').slice(0, 8)}`
|
|
149
|
-
const now = new Date().toISOString()
|
|
150
|
-
const conclusions = normConclusions(args.conclusions)
|
|
151
|
-
const windowFrom = normTimeArg(args.window_from)
|
|
152
|
-
const windowTo = normTimeArg(args.window_to)
|
|
153
|
-
|
|
154
|
-
getAnalysisRepo().insert({
|
|
155
|
-
id,
|
|
156
|
-
lineId: line.lineId,
|
|
157
|
-
lineName: line.lineName,
|
|
158
|
-
title,
|
|
159
|
-
category: String(args.category ?? '').trim() || 'general',
|
|
160
|
-
summary,
|
|
161
|
-
conclusions,
|
|
162
|
-
report: String(args.report ?? ''),
|
|
163
|
-
metrics: (args.metrics && typeof args.metrics === 'object' && !Array.isArray(args.metrics) ? args.metrics : {}) as Record<string, unknown>,
|
|
164
|
-
recipeId,
|
|
165
|
-
recipeVersion,
|
|
166
|
-
windowFrom,
|
|
167
|
-
windowTo,
|
|
168
|
-
dataSources: String(args.data_sources ?? ''),
|
|
169
|
-
context: lineContextSnapshot(line.lineId),
|
|
170
|
-
channelId: channelId ?? '',
|
|
171
|
-
channelName,
|
|
172
|
-
actor: agentId,
|
|
173
|
-
actorName: agentBadgeLabel(agentId),
|
|
174
|
-
createdAt: now,
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
recordOps({
|
|
179
|
-
actor: agentId, actorName: agentBadgeLabel(agentId), actorKind: 'agent',
|
|
180
|
-
action: 'analysis.save', kind: 'analysis', targetKind: 'analysis', targetId: id,
|
|
181
|
-
lineId: line.lineId, recipeId,
|
|
182
|
-
summary: `Agent 留痕分析报告「${title}」:产线「${line.lineName}」${recipeId ? `,配方 ${recipeId}` : ''} — ${summary}`,
|
|
183
|
-
})
|
|
184
|
-
}
|
|
185
|
-
catch { /* 审计失败不影响留痕 */ }
|
|
186
|
-
|
|
187
|
-
const win = windowFrom || windowTo ? `(数据窗 ${windowFrom ?? '?'} ~ ${windowTo ?? '?'})` : ''
|
|
188
|
-
return { text: `分析报告已留痕:${id}。产线「${line.lineName}」${win},结论 ${conclusions.length} 条,配方 ${recipeId || '未关联'}。台账 append-only,不可改删;随时可用 analysis_query(report_id="${id}") 查回全文。` }
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/** 工具:analysis_query —— 查询历史分析报告(report_id 精确查全文;或按线/配方/时间/关键词列表)。 */
|
|
192
|
-
export async function toolAnalysisQuery(agentId: string, args: AnalysisQueryInput): Promise<{ text: string, isError?: boolean }> {
|
|
193
|
-
const readable = readableLineIdsOf(agentId)
|
|
194
|
-
const reportId = String(args.report_id ?? '').trim()
|
|
195
|
-
const repo = getAnalysisRepo()
|
|
196
|
-
|
|
197
|
-
if (reportId) {
|
|
198
|
-
const report = repo.get(reportId)
|
|
199
|
-
if (!report) return { text: `分析报告不存在: ${reportId}(留痕不可变,也没有删除找回;请核对 id)。`, isError: true }
|
|
200
|
-
if (report.lineId && !readable.includes(report.lineId)) {
|
|
201
|
-
return { text: `分析报告 ${reportId} 属于产线「${report.lineName}」,不在你的可见范围。`, isError: true }
|
|
202
|
-
}
|
|
203
|
-
const head = [
|
|
204
|
-
`分析报告 ${report.id}:「${report.title}」(分类 ${report.category})`,
|
|
205
|
-
`产线: ${report.lineName || report.lineId || '-'} | 配方: ${report.recipeId || '-'}${report.recipeVersion ? ` v${report.recipeVersion}` : ''}`,
|
|
206
|
-
`分析时间: ${fmtAuditAt(report.createdAt)} | 数据窗: ${report.windowFrom ? fmtAuditAt(report.windowFrom) : '-'} ~ ${report.windowTo ? fmtAuditAt(report.windowTo) : '-'}`,
|
|
207
|
-
`来源: ${report.actorName || report.actor}${report.channelName ? ` @频道「${report.channelName}」` : ''}`,
|
|
208
|
-
`关键结论: ${report.summary}`,
|
|
209
|
-
...(report.conclusions.length ? [`结论明细:\n${report.conclusions.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}`] : []),
|
|
210
|
-
]
|
|
211
|
-
const body = report.report ? `\n\n— 完整分析正文 —\n${report.report}` : ''
|
|
212
|
-
const metrics = Object.keys(report.metrics ?? {}).length ? `\n\n— 支撑指标 —\n${JSON.stringify(report.metrics, null, 1)}` : ''
|
|
213
|
-
return { text: `${head.join('\n')}${body}${metrics}` }
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const explicitLine = String(args.line_id ?? '').trim()
|
|
217
|
-
if (explicitLine && !readable.includes(explicitLine)) {
|
|
218
|
-
return { text: `产线 ${explicitLine} 不在你的可见范围(节点授权线/绑定配方线/频道绑线)。`, isError: true }
|
|
219
|
-
}
|
|
220
|
-
// 作用域空集 = 不可见任何产线 → 直接空结果,不得落成"不过滤"(防越权列举全量台账)
|
|
221
|
-
if (!explicitLine && readable.length === 0) {
|
|
222
|
-
return { text: '你当前没有任何可见产线(无节点授权、无绑定配方、频道未绑线),暂无可查的分析报告。' }
|
|
223
|
-
}
|
|
224
|
-
const rows = repo.list({
|
|
225
|
-
lineId: explicitLine || undefined,
|
|
226
|
-
lineIds: explicitLine ? undefined : readable,
|
|
227
|
-
recipeId: String(args.recipe_id ?? '').trim() || undefined,
|
|
228
|
-
category: String(args.category ?? '').trim() || undefined,
|
|
229
|
-
q: String(args.q ?? '').trim() || undefined,
|
|
230
|
-
from: normTimeArg(args.from) ?? undefined,
|
|
231
|
-
to: normTimeArg(args.to) ?? undefined,
|
|
232
|
-
limit: Math.min(50, Math.max(1, Number(args.limit) || 20)),
|
|
233
|
-
})
|
|
234
|
-
if (rows.length === 0) {
|
|
235
|
-
return { text: `可见范围内暂无匹配的分析报告${args.q ? `(关键词「${String(args.q)}」)` : ''}。留痕由各频道的 analysis_save 产生;若是刚分析完,确认保存工具已被调用。` }
|
|
236
|
-
}
|
|
237
|
-
const lines = rows.map((r) => {
|
|
238
|
-
const recipe = r.recipeId ? ` | 配方 ${r.recipeId}${r.recipeVersion ? ` v${r.recipeVersion}` : ''}` : ''
|
|
239
|
-
return `[${r.id}] ${fmtAuditAt(r.createdAt)} | ${r.lineName || r.lineId || '-'}${recipe} | ${r.title}(${r.category})\n ${r.summary} —— ${r.actorName || r.actor}${r.channelName ? ` @「${r.channelName}」` : ''}`
|
|
240
|
-
})
|
|
241
|
-
return { text: `共 ${rows.length} 条分析报告(新→旧):\n${lines.join('\n')}\n\n用 analysis_query(report_id="ar-xxxx") 查看单条完整正文与结论明细。` }
|
|
242
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 数据分析系统 · 分析报告留痕工具(analysis_save / analysis_query)。
|
|
3
|
+
*
|
|
4
|
+
* 定位:Agent Channel 把分析产出(关键结论/正文/支撑指标)持久化到平台台账,
|
|
5
|
+
* 实现"分析结果可留痕、随时可查回"。台账 append-only —— 本族无更新/删除工具
|
|
6
|
+
* (删仅 REST admin 面),保证留痕不可变。
|
|
7
|
+
*
|
|
8
|
+
* 权限语义(同族只读工具口径):
|
|
9
|
+
* - 目标产线解析:显式 line_id(须在可见范围)→ 频道绑线兜底 → 都没有则拒。
|
|
10
|
+
* - 可见产线 = 节点授权线 ∪ 绑定配方所在线 ∪ 频道绑线(agentOpsScope)。
|
|
11
|
+
* - 不进 WRITE_TOOLS/grant-guard 写族:留痕是台账写入,非产线控制写;
|
|
12
|
+
* 能读该产线数据(≥readonly)的 Agent 才能留痕。
|
|
13
|
+
*/
|
|
14
|
+
import { randomUUID } from 'node:crypto'
|
|
15
|
+
import { agentBadgeLabel } from '../agent-badge'
|
|
16
|
+
import { getDcwController } from '../../dcw/dcw-controller'
|
|
17
|
+
import { getDcwLineRepo } from '../../dcw/dcw-line.repo'
|
|
18
|
+
import { recordOps } from '../../ops/ops'
|
|
19
|
+
import { getAnalysisRepo } from '../../analysis/analysis.repo'
|
|
20
|
+
import { agentOpsScope, channelBoundLineId, fmtAuditAt } from './ops-tools'
|
|
21
|
+
|
|
22
|
+
export interface AnalysisSaveInput {
|
|
23
|
+
title?: string
|
|
24
|
+
summary?: string
|
|
25
|
+
conclusions?: string[] | string
|
|
26
|
+
report?: string
|
|
27
|
+
category?: string
|
|
28
|
+
line_id?: string
|
|
29
|
+
recipe_id?: string
|
|
30
|
+
recipe_version?: string
|
|
31
|
+
window_from?: string
|
|
32
|
+
window_to?: string
|
|
33
|
+
data_sources?: string
|
|
34
|
+
metrics?: Record<string, unknown>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface AnalysisQueryInput {
|
|
38
|
+
report_id?: string
|
|
39
|
+
line_id?: string
|
|
40
|
+
recipe_id?: string
|
|
41
|
+
category?: string
|
|
42
|
+
q?: string
|
|
43
|
+
from?: string
|
|
44
|
+
to?: string
|
|
45
|
+
limit?: number | string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** 可见产线全集 = 节点授权线 ∪ 绑定配方所在线 ∪ 频道绑线(去重) */
|
|
49
|
+
function readableLineIdsOf(agentId: string): string[] {
|
|
50
|
+
const bound = channelBoundLineId(agentId)
|
|
51
|
+
const scope = agentOpsScope(agentId)
|
|
52
|
+
if (!scope) return bound ? [bound] : []
|
|
53
|
+
return [...new Set([...scope.lineIds, ...scope.boundLineIds, ...(bound ? [bound] : [])])]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 目标产线解析:显式 line_id(须可读)→ 频道绑线兜底;返回产线视图或错误文案 */
|
|
57
|
+
function resolveTargetLine(agentId: string, explicitLineId?: string): { lineId: string, lineName: string } | { error: string } {
|
|
58
|
+
const lineRepo = getDcwLineRepo()
|
|
59
|
+
const wanted = String(explicitLineId ?? '').trim() || channelBoundLineId(agentId)
|
|
60
|
+
if (!wanted) {
|
|
61
|
+
return { error: '无法确定目标产线:本频道未绑定产线,且未指定 line_id。请先绑线,或显式传入可见范围内的 line_id。' }
|
|
62
|
+
}
|
|
63
|
+
const line = lineRepo.byId(wanted)
|
|
64
|
+
if (!line) return { error: `产线不存在: ${wanted}` }
|
|
65
|
+
const readable = readableLineIdsOf(agentId)
|
|
66
|
+
if (!readable.includes(wanted)) {
|
|
67
|
+
return { error: `产线「${line.name}」不在你的可见范围(节点授权线/绑定配方线/频道绑线)。只能对可见产线留痕。` }
|
|
68
|
+
}
|
|
69
|
+
return { lineId: line.id, lineName: line.name }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** 时间入参归一:epoch ms 数值串或 ISO 均收,统一出 ISO;无效返回 null(留空=未指明) */
|
|
73
|
+
function normTimeArg(raw: unknown): string | null {
|
|
74
|
+
const s = String(raw ?? '').trim()
|
|
75
|
+
if (!s) return null
|
|
76
|
+
if (/^\d{10,}$/.test(s)) {
|
|
77
|
+
const ms = Number(s)
|
|
78
|
+
return Number.isFinite(ms) ? new Date(ms).toISOString() : null
|
|
79
|
+
}
|
|
80
|
+
const t = Date.parse(s)
|
|
81
|
+
return Number.isNaN(t) ? null : new Date(t).toISOString()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** conclusions 归一:接受 string[] 或换行分隔的整段字符串(LLM 两种形态都常见) */
|
|
85
|
+
function normConclusions(raw: AnalysisSaveInput['conclusions']): string[] {
|
|
86
|
+
if (Array.isArray(raw)) return raw.map(x => String(x).trim()).filter(Boolean)
|
|
87
|
+
return String(raw ?? '')
|
|
88
|
+
.split('\n')
|
|
89
|
+
.map(x => x.replace(/^[-*\d.\s]+/, '').trim())
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** 频道名快照(归因用;经全局 manager 直读,未装配/直调上下文留空 —— 同 channelBoundLineId 模式) */
|
|
94
|
+
function channelNameOf(channelId?: string): string {
|
|
95
|
+
if (!channelId) return ''
|
|
96
|
+
try {
|
|
97
|
+
const g = globalThis as typeof globalThis & {
|
|
98
|
+
__workshopManager?: { deps: { repos: { channels: { findById(id: string): { name?: string } | undefined } } } }
|
|
99
|
+
}
|
|
100
|
+
return g.__workshopManager?.deps.repos.channels.findById(channelId)?.name ?? ''
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return ''
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** 产线上下文快照:保存瞬间把产品/批次/控制模式固化进台账 */
|
|
108
|
+
function lineContextSnapshot(lineId: string): Record<string, unknown> {
|
|
109
|
+
try {
|
|
110
|
+
const ctrl = getDcwController()
|
|
111
|
+
const st = ctrl.lineState(lineId)
|
|
112
|
+
const line = getDcwLineRepo().byId(lineId)
|
|
113
|
+
return {
|
|
114
|
+
controlMode: line?.controlMode ?? '',
|
|
115
|
+
activeRun: st?.active
|
|
116
|
+
? { runId: st.runId, recipeName: st.recipeName, productName: st.productName, startedAt: st.startedAt }
|
|
117
|
+
: null,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return {}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** 工具:analysis_save —— 把本次分析的关键结论与产出持久化到平台分析台账(数据留痕)。 */
|
|
126
|
+
export async function toolAnalysisSave(agentId: string, args: AnalysisSaveInput, channelId?: string): Promise<{ text: string, isError?: boolean }> {
|
|
127
|
+
const title = String(args.title ?? '').trim()
|
|
128
|
+
const summary = String(args.summary ?? '').trim()
|
|
129
|
+
if (!title) return { text: 'title 必填:分析主题(如「BOPET 线膜厚漂移根因分析」),台账列表靠它辨认。', isError: true }
|
|
130
|
+
if (!summary) return { text: 'summary 必填:一句话关键结论 —— 这是留痕的核心产出,人扫一眼列表要能看懂。', isError: true }
|
|
131
|
+
|
|
132
|
+
const line = resolveTargetLine(agentId, args.line_id)
|
|
133
|
+
if ('error' in line) return { text: line.error, isError: true }
|
|
134
|
+
|
|
135
|
+
// 配方联动:校验存在性 + 归属(留痕的 recipe 字段要可信)
|
|
136
|
+
const recipeId = String(args.recipe_id ?? '').trim()
|
|
137
|
+
let recipeVersion = String(args.recipe_version ?? '').trim()
|
|
138
|
+
if (recipeId) {
|
|
139
|
+
const recipe = getDcwController().listRecipes().find(r => r.id === recipeId)
|
|
140
|
+
if (!recipe) return { text: `配方 ${recipeId} 不存在,recipe_id 留痕被拒(可用 line_context 查看当前配方)。`, isError: true }
|
|
141
|
+
if (recipe.lineId && recipe.lineId !== line.lineId) {
|
|
142
|
+
return { text: `配方「${recipe.name}」不属于产线「${line.lineName}」,不能挂到该线的分析报告下。`, isError: true }
|
|
143
|
+
}
|
|
144
|
+
if (!recipeVersion) recipeVersion = String(recipe.version ?? '')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const channelName = channelNameOf(channelId)
|
|
148
|
+
const id = `ar-${randomUUID().replace(/-/g, '').slice(0, 8)}`
|
|
149
|
+
const now = new Date().toISOString()
|
|
150
|
+
const conclusions = normConclusions(args.conclusions)
|
|
151
|
+
const windowFrom = normTimeArg(args.window_from)
|
|
152
|
+
const windowTo = normTimeArg(args.window_to)
|
|
153
|
+
|
|
154
|
+
getAnalysisRepo().insert({
|
|
155
|
+
id,
|
|
156
|
+
lineId: line.lineId,
|
|
157
|
+
lineName: line.lineName,
|
|
158
|
+
title,
|
|
159
|
+
category: String(args.category ?? '').trim() || 'general',
|
|
160
|
+
summary,
|
|
161
|
+
conclusions,
|
|
162
|
+
report: String(args.report ?? ''),
|
|
163
|
+
metrics: (args.metrics && typeof args.metrics === 'object' && !Array.isArray(args.metrics) ? args.metrics : {}) as Record<string, unknown>,
|
|
164
|
+
recipeId,
|
|
165
|
+
recipeVersion,
|
|
166
|
+
windowFrom,
|
|
167
|
+
windowTo,
|
|
168
|
+
dataSources: String(args.data_sources ?? ''),
|
|
169
|
+
context: lineContextSnapshot(line.lineId),
|
|
170
|
+
channelId: channelId ?? '',
|
|
171
|
+
channelName,
|
|
172
|
+
actor: agentId,
|
|
173
|
+
actorName: agentBadgeLabel(agentId),
|
|
174
|
+
createdAt: now,
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
recordOps({
|
|
179
|
+
actor: agentId, actorName: agentBadgeLabel(agentId), actorKind: 'agent',
|
|
180
|
+
action: 'analysis.save', kind: 'analysis', targetKind: 'analysis', targetId: id,
|
|
181
|
+
lineId: line.lineId, recipeId,
|
|
182
|
+
summary: `Agent 留痕分析报告「${title}」:产线「${line.lineName}」${recipeId ? `,配方 ${recipeId}` : ''} — ${summary}`,
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
catch { /* 审计失败不影响留痕 */ }
|
|
186
|
+
|
|
187
|
+
const win = windowFrom || windowTo ? `(数据窗 ${windowFrom ?? '?'} ~ ${windowTo ?? '?'})` : ''
|
|
188
|
+
return { text: `分析报告已留痕:${id}。产线「${line.lineName}」${win},结论 ${conclusions.length} 条,配方 ${recipeId || '未关联'}。台账 append-only,不可改删;随时可用 analysis_query(report_id="${id}") 查回全文。` }
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** 工具:analysis_query —— 查询历史分析报告(report_id 精确查全文;或按线/配方/时间/关键词列表)。 */
|
|
192
|
+
export async function toolAnalysisQuery(agentId: string, args: AnalysisQueryInput): Promise<{ text: string, isError?: boolean }> {
|
|
193
|
+
const readable = readableLineIdsOf(agentId)
|
|
194
|
+
const reportId = String(args.report_id ?? '').trim()
|
|
195
|
+
const repo = getAnalysisRepo()
|
|
196
|
+
|
|
197
|
+
if (reportId) {
|
|
198
|
+
const report = repo.get(reportId)
|
|
199
|
+
if (!report) return { text: `分析报告不存在: ${reportId}(留痕不可变,也没有删除找回;请核对 id)。`, isError: true }
|
|
200
|
+
if (report.lineId && !readable.includes(report.lineId)) {
|
|
201
|
+
return { text: `分析报告 ${reportId} 属于产线「${report.lineName}」,不在你的可见范围。`, isError: true }
|
|
202
|
+
}
|
|
203
|
+
const head = [
|
|
204
|
+
`分析报告 ${report.id}:「${report.title}」(分类 ${report.category})`,
|
|
205
|
+
`产线: ${report.lineName || report.lineId || '-'} | 配方: ${report.recipeId || '-'}${report.recipeVersion ? ` v${report.recipeVersion}` : ''}`,
|
|
206
|
+
`分析时间: ${fmtAuditAt(report.createdAt)} | 数据窗: ${report.windowFrom ? fmtAuditAt(report.windowFrom) : '-'} ~ ${report.windowTo ? fmtAuditAt(report.windowTo) : '-'}`,
|
|
207
|
+
`来源: ${report.actorName || report.actor}${report.channelName ? ` @频道「${report.channelName}」` : ''}`,
|
|
208
|
+
`关键结论: ${report.summary}`,
|
|
209
|
+
...(report.conclusions.length ? [`结论明细:\n${report.conclusions.map((c, i) => ` ${i + 1}. ${c}`).join('\n')}`] : []),
|
|
210
|
+
]
|
|
211
|
+
const body = report.report ? `\n\n— 完整分析正文 —\n${report.report}` : ''
|
|
212
|
+
const metrics = Object.keys(report.metrics ?? {}).length ? `\n\n— 支撑指标 —\n${JSON.stringify(report.metrics, null, 1)}` : ''
|
|
213
|
+
return { text: `${head.join('\n')}${body}${metrics}` }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const explicitLine = String(args.line_id ?? '').trim()
|
|
217
|
+
if (explicitLine && !readable.includes(explicitLine)) {
|
|
218
|
+
return { text: `产线 ${explicitLine} 不在你的可见范围(节点授权线/绑定配方线/频道绑线)。`, isError: true }
|
|
219
|
+
}
|
|
220
|
+
// 作用域空集 = 不可见任何产线 → 直接空结果,不得落成"不过滤"(防越权列举全量台账)
|
|
221
|
+
if (!explicitLine && readable.length === 0) {
|
|
222
|
+
return { text: '你当前没有任何可见产线(无节点授权、无绑定配方、频道未绑线),暂无可查的分析报告。' }
|
|
223
|
+
}
|
|
224
|
+
const rows = repo.list({
|
|
225
|
+
lineId: explicitLine || undefined,
|
|
226
|
+
lineIds: explicitLine ? undefined : readable,
|
|
227
|
+
recipeId: String(args.recipe_id ?? '').trim() || undefined,
|
|
228
|
+
category: String(args.category ?? '').trim() || undefined,
|
|
229
|
+
q: String(args.q ?? '').trim() || undefined,
|
|
230
|
+
from: normTimeArg(args.from) ?? undefined,
|
|
231
|
+
to: normTimeArg(args.to) ?? undefined,
|
|
232
|
+
limit: Math.min(50, Math.max(1, Number(args.limit) || 20)),
|
|
233
|
+
})
|
|
234
|
+
if (rows.length === 0) {
|
|
235
|
+
return { text: `可见范围内暂无匹配的分析报告${args.q ? `(关键词「${String(args.q)}」)` : ''}。留痕由各频道的 analysis_save 产生;若是刚分析完,确认保存工具已被调用。` }
|
|
236
|
+
}
|
|
237
|
+
const lines = rows.map((r) => {
|
|
238
|
+
const recipe = r.recipeId ? ` | 配方 ${r.recipeId}${r.recipeVersion ? ` v${r.recipeVersion}` : ''}` : ''
|
|
239
|
+
return `[${r.id}] ${fmtAuditAt(r.createdAt)} | ${r.lineName || r.lineId || '-'}${recipe} | ${r.title}(${r.category})\n ${r.summary} —— ${r.actorName || r.actor}${r.channelName ? ` @「${r.channelName}」` : ''}`
|
|
240
|
+
})
|
|
241
|
+
return { text: `共 ${rows.length} 条分析报告(新→旧):\n${lines.join('\n')}\n\n用 analysis_query(report_id="ar-xxxx") 查看单条完整正文与结论明细。` }
|
|
242
|
+
}
|