@lsamien/yaovi 0.1.3 → 0.1.5
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/build-info.json +22 -3
- package/desktop/main.mjs +1 -1
- package/dist/assets/{AboutDialog-CnNkIRo8.js → AboutDialog-2Zq3b7ma.js} +2 -2
- package/dist/assets/{AboutDialog-CnNkIRo8.js.map → AboutDialog-2Zq3b7ma.js.map} +1 -1
- package/dist/assets/{BotAutomationsView-J9Y7Unoq.js → BotAutomationsView-C4EwHtYy.js} +2 -2
- package/dist/assets/{BotAutomationsView-J9Y7Unoq.js.map → BotAutomationsView-C4EwHtYy.js.map} +1 -1
- package/dist/assets/{BotControlSettingsPanel-CtXD24FZ.js → BotControlSettingsPanel-DJ71O3Kh.js} +2 -2
- package/dist/assets/{BotControlSettingsPanel-CtXD24FZ.js.map → BotControlSettingsPanel-DJ71O3Kh.js.map} +1 -1
- package/dist/assets/BotPluginsDialog-Cgqn4RlP.js +2 -0
- package/dist/assets/{BotPluginsDialog-qRw8dCbX.js.map → BotPluginsDialog-Cgqn4RlP.js.map} +1 -1
- package/dist/assets/{BotSettingsPanel-DbCMOfAW.js → BotSettingsPanel-C_1zAGWJ.js} +3 -3
- package/dist/assets/{BotSettingsPanel-DbCMOfAW.js.map → BotSettingsPanel-C_1zAGWJ.js.map} +1 -1
- package/dist/assets/{ComputerPanel-CI-jDmC3.js → ComputerPanel-CuVl9oX7.js} +2 -2
- package/dist/assets/{ComputerPanel-CI-jDmC3.js.map → ComputerPanel-CuVl9oX7.js.map} +1 -1
- package/dist/assets/{ComputerViewerView-B76D6Fln.js → ComputerViewerView-BoI_aqLr.js} +2 -2
- package/dist/assets/{ComputerViewerView-B76D6Fln.js.map → ComputerViewerView-BoI_aqLr.js.map} +1 -1
- package/dist/assets/ConversationsView-aPMgqa0O.css +1 -0
- package/dist/assets/{ConversationsView-DsuaLKva.js → ConversationsView-kztie5lF.js} +88 -88
- package/dist/assets/ConversationsView-kztie5lF.js.map +1 -0
- package/dist/assets/{LocalVmSettingsPanel-BfXFdMYF.js → LocalVmSettingsPanel-BZ1Jeqqk.js} +4 -4
- package/dist/assets/{LocalVmSettingsPanel-BfXFdMYF.js.map → LocalVmSettingsPanel-BZ1Jeqqk.js.map} +1 -1
- package/dist/assets/{ModelNetworkChoice-DB6cLOBw.js → ModelNetworkChoice-BQ8m2N3V.js} +2 -2
- package/dist/assets/{ModelNetworkChoice-DB6cLOBw.js.map → ModelNetworkChoice-BQ8m2N3V.js.map} +1 -1
- package/dist/assets/{StandaloneDialog-BWUp2Wxo.js → StandaloneDialog-hF3z7bfi.js} +2 -2
- package/dist/assets/{StandaloneDialog-BWUp2Wxo.js.map → StandaloneDialog-hF3z7bfi.js.map} +1 -1
- package/dist/assets/{UpdateCheckDialog-CpZSPlUI.js → UpdateCheckDialog-Bz8JhRh4.js} +2 -2
- package/dist/assets/{UpdateCheckDialog-CpZSPlUI.js.map → UpdateCheckDialog-Bz8JhRh4.js.map} +1 -1
- package/dist/assets/{UsageView-BhiRCw7p.js → UsageView-ZsSbQzIY.js} +3 -3
- package/dist/assets/{UsageView-BhiRCw7p.js.map → UsageView-ZsSbQzIY.js.map} +1 -1
- package/dist/assets/WorkspaceKnowledgePanel-E549Ct1E.js +3 -0
- package/dist/assets/{WorkspaceKnowledgePanel-D34YxglF.js.map → WorkspaceKnowledgePanel-E549Ct1E.js.map} +1 -1
- package/dist/assets/WorkspaceRoutinesPanel-NFWzy1R-.js +2 -0
- package/dist/assets/{WorkspaceRoutinesPanel-Bn-W52Im.js.map → WorkspaceRoutinesPanel-NFWzy1R-.js.map} +1 -1
- package/dist/assets/{WorkstreamsView-CH6qDPvj.js → WorkstreamsView-CxZ8YUvP.js} +2 -2
- package/dist/assets/{WorkstreamsView-CH6qDPvj.js.map → WorkstreamsView-CxZ8YUvP.js.map} +1 -1
- package/dist/assets/index-C-5Gq82f.css +1 -0
- package/dist/assets/{index-DjhQ-RMG.js → index-P_kZCZ2-.js} +18 -18
- package/dist/assets/index-P_kZCZ2-.js.map +1 -0
- package/dist/assets/{pdf-wqiF06Qz.js → pdf-CNS_Rszb.js} +2 -2
- package/dist/assets/{pdf-wqiF06Qz.js.map → pdf-CNS_Rszb.js.map} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/server/remoteAccess/dispatcher.js +5 -1
- package/dist-server/server/workspaceCollaboration.js +9 -12
- package/dist-server/server/workspaceStore.js +3 -1
- package/dist-server/shared/peerExchange.js +26 -0
- package/node_modules/@yaovi/remote-core/index.mjs +13 -10
- package/node_modules/@yaovi/remote-core/package.json +2 -2
- package/node_modules/@yaovi/remote-core/types/remote-core/src/control/recovery.d.ts +1 -1
- package/node_modules/@yaovi/remote-core/types/remote-core/src/control/remote.d.ts +2 -0
- package/node_modules/@yaovi/remote-core/types/remote-core/src/index.d.ts +1 -0
- package/node_modules/@yaovi/remote-core/types/remote-core/src/transport/lan.d.ts +10 -4
- package/node_modules/@yaovi/remote-core/types/remote-core/src/transport/packet.d.ts +2 -2
- package/package.json +2 -2
- package/release.json +3 -3
- package/vendor/yaovi-remote-core-0.2.0-remote.18.tgz +0 -0
- package/dist/assets/BotPluginsDialog-qRw8dCbX.js +0 -2
- package/dist/assets/ConversationsView-DoA0eNiz.css +0 -1
- package/dist/assets/ConversationsView-DsuaLKva.js.map +0 -1
- package/dist/assets/WorkspaceKnowledgePanel-D34YxglF.js +0 -3
- package/dist/assets/WorkspaceRoutinesPanel-Bn-W52Im.js +0 -2
- package/dist/assets/index-DjhQ-RMG.js.map +0 -1
- package/dist/assets/index-DrIgDgnN.css +0 -1
package/build-info.json
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
2
|
+
"commit": "972c92397e66182d2d433e2857fe2a5759689d4e",
|
|
3
3
|
"ancestors": [
|
|
4
|
+
"972c92397e66182d2d433e2857fe2a5759689d4e",
|
|
5
|
+
"60aef5d8672e07635f9aef9a4af09dc4762aeb51",
|
|
6
|
+
"3d5dc3fd7ed01d90565de3c4c6dd06173534436a",
|
|
7
|
+
"421000dad650ea21e2f4230eec545c4258c6ff10",
|
|
8
|
+
"50156cedb9591fc434e6108f182279161ae8c428",
|
|
9
|
+
"7899f2122da4098ef773e4fa603940e2e2665f14",
|
|
10
|
+
"d6a3c609c241a63ff65e8fbef4f40f0b564592a7",
|
|
11
|
+
"ad24b6b44f1ae75eef7ba6c4b58ea9d159fed343",
|
|
12
|
+
"b9f69213221adf82ffe291602120c030f67257d5",
|
|
13
|
+
"626202c5f70db923c671afbd24931ab3e90384b5",
|
|
14
|
+
"a5bbef9b0f5fc0df4e162473acc25fb54d3a66f5",
|
|
15
|
+
"d0d1acf87867fbd3b9e22c576ea87140730f4ba9",
|
|
16
|
+
"375ef941de606fa1a3e94290ee12da847fd7765d",
|
|
17
|
+
"8d0c621af1b267dd4e27dcb8c4e0a488497351f5",
|
|
18
|
+
"d762c715ec276e970b2a422f233e2f28f1c30fc4",
|
|
19
|
+
"2aef2647eaf04e9f576d58978018cbdfe9373f53",
|
|
20
|
+
"f19994ae3336f83f0a5c90cf3702eae5acbaa7ca",
|
|
21
|
+
"c3221ec80eb4dc156a3e24cde6bf8df755db7f60",
|
|
22
|
+
"b8bdbedddbc3e72c46fee9078bd7ad689317ebdb",
|
|
4
23
|
"245a97b3f0c56c521d27bd8cf177dbf67153770d",
|
|
5
24
|
"929948506c5534d9b1db195b8765633e42b7e1c4",
|
|
6
25
|
"e0031940e05b0e9ce3e5c536df8f792de6292f23",
|
|
@@ -455,7 +474,7 @@
|
|
|
455
474
|
"67707c3fdf570f8d457d916e73209203e6c00451",
|
|
456
475
|
"45032257ea429656af610602da25073154f9bb3a"
|
|
457
476
|
],
|
|
458
|
-
"buildNumber":
|
|
477
|
+
"buildNumber": 472,
|
|
459
478
|
"dirty": true,
|
|
460
|
-
"builtAt": "2026-10-
|
|
479
|
+
"builtAt": "2026-10-26T08:41:15.782Z"
|
|
461
480
|
}
|
package/desktop/main.mjs
CHANGED
|
@@ -156,7 +156,7 @@ else {
|
|
|
156
156
|
}
|
|
157
157
|
const trustedUpdate = event => {
|
|
158
158
|
if (event.sender !== window?.webContents || event.senderFrame !== window.webContents.mainFrame) return false
|
|
159
|
-
if (event.senderFrame.url === bootURL) return true
|
|
159
|
+
if (event.senderFrame.url === bootURL || cloudPage(event)) return true
|
|
160
160
|
try { return serviceOrigins().includes(new URL(event.senderFrame.url).origin) }
|
|
161
161
|
catch { return false }
|
|
162
162
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{F as e,Ot as t,W as n,_ as r,b as i,d as a,f as o,st as s,t as c,v as l}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{
|
|
2
|
-
//# sourceMappingURL=AboutDialog-
|
|
1
|
+
import{F as e,Ot as t,W as n,_ as r,b as i,d as a,f as o,st as s,t as c,v as l}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{H as u}from"./index-P_kZCZ2-.js";import{t as d}from"./StandaloneDialog-hF3z7bfi.js";var f=`0.1.5`,p={class:`about-content`},m={class:`about-version`},h=c(i({__name:`AboutDialog`,emits:[`close`],setup(i,{emit:c}){let h=c;return(i,c)=>(e(),o(d,{title:`关于Yaovi`,compact:``,onClose:c[0]||=e=>h(`close`)},{default:n(()=>[a(`section`,p,[l(u,{size:56,label:!1,compact:``,bare:``}),c[1]||=a(`h3`,null,`Yaovi`,-1),a(`p`,m,`版本 `+t(s(f)),1),c[2]||=a(`p`,null,[r(`通过 OpenAI 模型与 Bot 对话、协作完成任务。`),a(`br`),r(`基于 Apache-2.0 许可证开放源代码。`)],-1)])]),_:1}))}}),[[`__scopeId`,`data-v-716bc6cf`]]);export{h as default};
|
|
2
|
+
//# sourceMappingURL=AboutDialog-2Zq3b7ma.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AboutDialog-
|
|
1
|
+
{"version":3,"file":"AboutDialog-2Zq3b7ma.js","names":[],"sources":["../../package.json","../../src/client/components/app/AboutDialog.vue","../../src/client/components/app/AboutDialog.vue"],"sourcesContent":["{\n \"name\": \"@lsamien/yaovi\",\n \"version\": \"0.1.5\",\n \"license\": \"Apache-2.0\",\n \"description\": \"Yaovi:单用户、多 Bot、多设备服务器\",\n \"type\": \"module\",\n \"main\": \"desktop/main.mjs\",\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"bin\": {\n \"yaovi\": \"bin/yaovi-agent.mjs\",\n \"yaovi-agent\": \"bin/yaovi-agent.mjs\"\n },\n \"scripts\": {\n \"dev\": \"cross-env NODE_ENV=development tsx watch src/server/index.ts\",\n \"build\": \"npm run brand:verify && npm run release:verify && vue-tsc -b tsconfig.client.build.json && vite build && node scripts/clean-server.mjs && tsc -p tsconfig.server.json && node scripts/copy-worker.mjs && node scripts/write-build-info.mjs\",\n \"start\": \"node bin/yaovi-agent.mjs start\",\n \"typecheck\": \"vue-tsc -b && tsc --noEmit -p tsconfig.server.json\",\n \"test\": \"vitest run\",\n \"prepack\": \"npm run build\",\n \"test:watch\": \"vitest\",\n \"test:e2e\": \"npm run build && playwright test\",\n \"test:live\": \"cross-env YAOVI_LIVE_TEST=1 vitest run tests/live\",\n \"brand:verify\": \"node scripts/verify-brand.mjs\",\n \"release:verify\": \"node scripts/verify-release.mjs\",\n \"verify:lifecycle\": \"node scripts/verify-lifecycle.mjs\",\n \"test:e2e:workspace\": \"npm run build && playwright test -c playwright.workspace.config.ts\",\n \"test:e2e:desktop-hosts\": \"npm run build && playwright test -c playwright.desktop-hosts.config.ts\",\n \"test:e2e:team-tools\": \"npm run build && playwright test -c playwright.team-tools.config.ts\",\n \"desktop:build\": \"npm run build && node scripts/build-desktop.mjs\",\n \"desktop:build:client\": \"node scripts/write-build-info.mjs && node scripts/build-desktop-client.mjs\",\n \"desktop:dev:client\": \"npm run desktop:build:client && cross-env YAOVI_DESKTOP_CLIENT_ONLY=1 electron .\",\n \"desktop:pack:client\": \"npm run desktop:build:client && electron-builder --config electron-builder.client.yml --mac --arm64 --publish never\",\n \"desktop:dev\": \"npm run desktop:build && cross-env YAOVI_DESKTOP_CLIENT_ONLY=0 electron .\",\n \"desktop:pack\": \"npm run desktop:build && electron-builder --mac --arm64 --publish never\",\n \"desktop:release\": \"npm run desktop:build && node scripts/desktop-release.mjs\",\n \"desktop:test\": \"cross-env YAOVI_DESKTOP_CLIENT_ONLY=0 node --test desktop/*.test.mjs\",\n \"runner\": \"node dist-server/runner/index.js\",\n \"runner:dev\": \"tsx src/runner/index.ts\",\n \"runner:build\": \"node scripts/build-runner.mjs\",\n \"desktop:build:win\": \"npm run build && node scripts/build-windows-desktop.mjs\",\n \"desktop:pack:win\": \"npm run desktop:build:win && node scripts/windows-desktop-release.mjs\",\n \"desktop:test:win\": \"node scripts/test-windows-desktop.mjs\",\n \"agent:setup\": \"node scripts/agent-setup.mjs\",\n \"agent:test\": \".venv/bin/python tests/runtime/test_kernel.py && .venv/bin/python tests/runtime/test_compression.py && (cd tests/runtime && ../../.venv/bin/python test_turn_context.py) && .venv/bin/python tests/runtime/test_backup.py && .venv/bin/python tests/runtime/test_hermes_web.py && .venv/bin/python tests/runtime/test_native_openviking.py && .venv/bin/python tests/runtime/test_native_openviking_config.py && .venv/bin/python tests/runtime/test_vault_env.py && vitest run tests/server/embeddedAgent.test.ts tests/server/singleUserDevices.test.ts tests/server/harnessWeb.test.ts\",\n \"agent:pack\": \"npm run build && node scripts/build-agent-host.mjs\",\n \"postinstall\": \"node scripts/agent-setup.mjs --postinstall\",\n \"desktop:release:client\": \"npm run desktop:build:client && node scripts/client-release.mjs\"\n },\n \"dependencies\": {\n \"@koa/bodyparser\": \"^5.0.0\",\n \"@koa/router\": \"^15.4.0\",\n \"@openviking/sdk\": \"0.1.0\",\n \"@trycua/cua-driver\": \"0.28.2\",\n \"@types/busboy\": \"^1.5.4\",\n \"@types/koa\": \"^2.15.0\",\n \"@types/koa-send\": \"^4.1.6\",\n \"@types/koa-static\": \"^4.0.4\",\n \"@types/markdown-it\": \"^14.1.2\",\n \"@types/mime-types\": \"^2.1.4\",\n \"@types/node\": \"^24.10.0\",\n \"@types/qrcode\": \"^1.5.6\",\n \"@types/ws\": \"^8.18.1\",\n \"@vicons/ionicons5\": \"^0.13.0\",\n \"@vicons/tabler\": \"^0.13.0\",\n \"@vitejs/plugin-vue\": \"^6.0.5\",\n \"@vue/tsconfig\": \"^0.9.1\",\n \"@yaovi/remote-core\": \"file:vendor/yaovi-remote-core-0.2.0-remote.18.tgz\",\n \"bonjour-service\": \"1.4.4\",\n \"busboy\": \"^1.6.0\",\n \"cookie\": \"^1.0.2\",\n \"docx-preview\": \"^0.3.7\",\n \"dompurify\": \"^3.2.6\",\n \"highlight.js\": \"^11.11.1\",\n \"koa\": \"^2.15.3\",\n \"koa-send\": \"^5.0.1\",\n \"koa-static\": \"^5.0.0\",\n \"libsodium-wrappers-sumo\": \"0.8.4\",\n \"markdown-it\": \"^14.1.0\",\n \"mime-types\": \"^3.0.1\",\n \"naive-ui\": \"^2.44.1\",\n \"openid-client\": \"6.8.8\",\n \"pdfjs-dist\": \"6.2.108\",\n \"pinia\": \"^3.0.4\",\n \"pinyin-pro\": \"3.29.5\",\n \"playwright\": \"1.62.1\",\n \"qrcode\": \"^1.5.4\",\n \"read-excel-file\": \"^7.0.3\",\n \"sass\": \"^1.99.0\",\n \"ssh2\": \"1.17.0\",\n \"typescript\": \"~6.0.2\",\n \"undici\": \"7.29.1\",\n \"vite\": \"^8.0.4\",\n \"vue\": \"^3.5.32\",\n \"vue-router\": \"^4.6.4\",\n \"vue-tsc\": \"^3.2.8\",\n \"ws\": \"^8.20.0\",\n \"zod\": \"^4.1.12\"\n },\n \"devDependencies\": {\n \"@playwright/test\": \"^1.60.0\",\n \"@types/jsdom\": \"^21.1.7\",\n \"@types/ssh2\": \"1.15.5\",\n \"@types/supertest\": \"^6.0.3\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"@vue/test-utils\": \"^2.4.6\",\n \"cross-env\": \"^10.1.0\",\n \"electron\": \"43.4.0\",\n \"electron-builder\": \"26.15.3\",\n \"electron-updater\": \"6.8.9\",\n \"esbuild\": \"0.28.2\",\n \"js-yaml\": \"4.3.2\",\n \"jsdom\": \"^27.0.1\",\n \"supertest\": \"^7.1.4\",\n \"tsx\": \"^4.21.0\",\n \"vitest\": \"^3.2.4\"\n },\n \"files\": [\n \"bin\",\n \"dist\",\n \"dist-server\",\n \"licenses\",\n \"LICENSE\",\n \"NOTICE\",\n \"THIRD_PARTY_NOTICES.md\",\n \"release.json\",\n \"build-info.json\",\n \"runtime\",\n \"scripts/agent-backup.py\",\n \"scripts/agent-setup.mjs\",\n \"!runtime/**/__pycache__/**\",\n \"!runtime/**/*.pyc\",\n \"!runtime/**/*.pyo\",\n \"!runtime/**/.env\",\n \"!runtime/**/auth.json\",\n \"vendor\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"bundleDependencies\": [\n \"@yaovi/remote-core\"\n ]\n}\n","<script setup lang=\"ts\">\nimport { version } from '../../../../package.json'\nimport BrandMark from '@/components/common/BrandMark.vue'\nimport StandaloneDialog from '@/components/common/StandaloneDialog.vue'\nconst emit = defineEmits<{ close: [] }>()\n</script>\n<template>\n <StandaloneDialog title=\"关于Yaovi\" compact @close=\"emit('close')\"><section class=\"about-content\">\n <BrandMark :size=\"56\" :label=\"false\" compact bare /><h3>Yaovi</h3><p class=\"about-version\">版本 {{ version }}</p>\n <p>通过 OpenAI 模型与 Bot 对话、协作完成任务。<br />基于 Apache-2.0 许可证开放源代码。</p>\n\n </section></StandaloneDialog>\n</template>\n<style scoped>\n.about-content{display:grid;justify-items:center;gap:12px;text-align:center}.about-content h3{font-size:21px;margin:0}.about-content p{margin:0;color:var(--text-secondary);font-size:13px;line-height:1.8}.about-content .about-version{font-size:12px}.about-content nav{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:8px}.about-content a{padding:10px 8px;color:var(--accent);font-size:13px;text-decoration:none}.about-content a:hover{text-decoration:underline}.about-content a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n","<script setup lang=\"ts\">\nimport { version } from '../../../../package.json'\nimport BrandMark from '@/components/common/BrandMark.vue'\nimport StandaloneDialog from '@/components/common/StandaloneDialog.vue'\nconst emit = defineEmits<{ close: [] }>()\n</script>\n<template>\n <StandaloneDialog title=\"关于Yaovi\" compact @close=\"emit('close')\"><section class=\"about-content\">\n <BrandMark :size=\"56\" :label=\"false\" compact bare /><h3>Yaovi</h3><p class=\"about-version\">版本 {{ version }}</p>\n <p>通过 OpenAI 模型与 Bot 对话、协作完成任务。<br />基于 Apache-2.0 许可证开放源代码。</p>\n\n </section></StandaloneDialog>\n</template>\n<style scoped>\n.about-content{display:grid;justify-items:center;gap:12px;text-align:center}.about-content h3{font-size:21px;margin:0}.about-content p{margin:0;color:var(--text-secondary);font-size:13px;line-height:1.8}.about-content .about-version{font-size:12px}.about-content nav{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:8px}.about-content a{padding:10px 8px;color:var(--accent);font-size:13px;text-decoration:none}.about-content a:hover{text-decoration:underline}.about-content a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n</style>\n"],"mappings":"wVCIA,IAAM,EAAO,gBAGX,EAAA,EAAA,EAI6B,EAAA,CAJX,MAAM,UAAU,QAAA,GAAS,QAAK,AAAA,EAAA,KAAA,GAAE,EAAI,OAAA,IAAW,QAAA,MAIvD,CAJuD,EAIvD,UAJuD,EAIvD,CAHR,EAAoD,EAAA,CAAxC,KAAM,GAAK,MAAO,GAAO,QAAA,GAAQ,KAAA,KAAO,AAAA,EAAA,KAAA,EAAc,KAAA,KAAV,QAAK,EAAA,EAAK,EAA6C,IAA7C,EAAyB,MAAG,EAAG,EAAA,CAAA,CAAO,EAAA,CAAA,EACxG,AAAA,EAAA,KAAA,EAAgE,IAAA,KAAA,CAA7D,EAAA,8BAA4B,EAAA,EAAM,IAAA,EAAA,EAAA,yBAAuB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{A as e,D as t,Et as n,F as r,G as i,L as a,M as o,Ot as s,W as ee,_ as c,a as l,b as te,d as u,et as d,f,m as p,p as m,st as ne,t as h,u as g,v as _,z as re}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{D as ie,I as v,J as ae,Y as oe,at as y,nt as b,o as x,ot as se,rt as S}from"./index-DjhQ-RMG.js";import{t as ce}from"./WorkspaceRoutinesPanel-Bn-W52Im.js";var le={class:`automations-header`},ue={class:`segmented`,role:`tablist`,"aria-label":`自动化页面`},de=[`aria-selected`],fe=[`aria-selected`],pe={key:0,class:`running-count`},me={class:`new-automation`},he=[`disabled`,`aria-expanded`],ge=[`onClick`],_e={class:`automations-body`},ve={class:`automation-sidebar`,"aria-label":`自动化筛选`},ye={class:`date-filter`},be={"aria-label":`按 Bot 筛选`},xe=[`aria-current`],Se=[`aria-current`,`onClick`],Ce={key:0},we={class:`automation-content`},Te={class:`automation-toolbar`},Ee={key:0,class:`segmented`,role:`tablist`,"aria-label":`日程视图`},De=[`aria-selected`],Oe=[`aria-selected`],ke={class:`date-actions`},Ae={class:`range-label`},je=[`aria-label`],Me=[`value`],Ne=[`value`],Pe={key:0,class:`page-error`,role:`alert`},Fe={key:1,class:`loading`,role:`status`},Ie={class:`schedule-week`,"aria-label":`本周自动化日程`},Le=[`aria-label`],Re=[`onClick`],ze={key:0,class:`no-events`},Be={key:3,class:`automation-list`},Ve={key:0,class:`empty`},He=[`onClick`],Ue=[`onClick`],We={key:4,class:`automation-logs`},Ge={key:0,class:`log-scope`},Ke={key:1,class:`empty`},qe={key:0,class:`failure`},Je={key:1},C=h(te({__name:`BotAutomationsView`,setup(te){let h=oe(),C=ae(),w=d([]),T=d([]),E=d([]),D=d(!0),O=d(``),k=d(`all`),A=d(``),j=d(``),M=d(`all`),N=d(`schedule`),P=d(`calendar`),F=d(``),I=d(!1),L=d(``),R=d(),z=e=>`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`,B=d(z(new Date));function V(){let e=new Date(B.value+`T00:00:00`);return Number.isFinite(e.getTime())?e:new Date}let Ye=[`一`,`二`,`三`,`四`,`五`,`六`,`日`],H={queued:`排队中`,running:`执行中`,waiting:`等待处理`,complete:`已完成`,failed:`失败`,interrupted:`已停止`,uncertain:`状态待确认`,skipped:`已跳过`},Xe=g(()=>typeof C.query.from==`string`&&/^\/conversations(?:\/[a-f0-9-]{36})?(?:\?taskId=[a-f0-9-]{36})?$/i.test(C.query.from)?C.query.from:`/conversations`),Ze=g(()=>w.value.filter(e=>e.name.toLowerCase().includes(A.value.trim().toLowerCase()))),U=g(()=>T.value.filter(e=>(k.value===`all`||e.agentId===k.value)&&`${e.name} ${e.prompt}`.toLowerCase().includes(j.value.trim().toLowerCase())).sort((e,t)=>Number(t.enabled)-Number(e.enabled)||(e.nextAt??1/0)-(t.nextAt??1/0))),W=g(()=>E.value.filter(e=>(k.value===`all`||e.agentId===k.value)&&(!F.value||e.routineId===F.value)&&(M.value===`all`||e.status===M.value)&&`${T.value.find(t=>t.id===e.routineId)?.name??``} ${e.error??``}`.toLowerCase().includes(j.value.trim().toLowerCase()))),Qe=g(()=>E.value.filter(e=>[`queued`,`running`,`waiting`,`uncertain`].includes(e.status)).length),G=g(()=>{let e=V();return e.setDate(e.getDate()-(e.getDay()+6)%7),Ye.map((t,n)=>{let r=new Date(e);return r.setDate(r.getDate()+n),{date:r,key:z(r),weekday:t}})}),$e=g(()=>`${G.value[0].date.toLocaleDateString(`zh-CN`)} — ${G.value[6].date.toLocaleDateString(`zh-CN`)}`),et=e=>U.value.filter(t=>t.enabled&&t.nextAt&&z(new Date(t.nextAt))===e),K=e=>w.value.find(t=>t.id===e),tt=e=>e?new Date(e).toLocaleString(`zh-CN`,{hour12:!1}):`—`,nt=e=>e?new Date(e).toLocaleTimeString(`zh-CN`,{hour12:!1,hour:`2-digit`,minute:`2-digit`}):``,rt=e=>e.schedule.kind===`interval`?`每 ${e.schedule.everyMinutes} 分钟`:e.schedule.kind===`once`?`仅一次`:`${e.schedule.kind===`weekly`?`每周 `+(e.schedule.weekdays??[]).map(e=>`日一二三四五六`[e]).join(`、`):`每天`} ${e.schedule.time}`;function q(e){let t=V();t.setDate(t.getDate()+e*7),B.value=z(t)}function it(e){e.target instanceof Element&&!e.target.closest(`.new-automation`)&&(I.value=!1)}function J(e=``){N.value=`logs`,F.value=e,j.value=``,M.value=`all`}async function Y(e,n){I.value=!1,L.value=e,await t(),R.value?.edit(n)}function at(){let e=k.value===`all`?w.value.length===1?w.value[0].id:void 0:k.value;e?Y(e):I.value=!I.value}let X=0,Z=!1,ot;async function Q(){let e=++X;try{let t=await ie(`/api/app/bot-tools/automations`);if(Z||e!==X)return;w.value=t.agents,T.value=t.routines,E.value=t.runs,O.value=``,k.value!==`all`&&!w.value.some(e=>e.id===k.value)&&(k.value=`all`)}catch(t){!Z&&e===X&&(O.value=t instanceof Error?t.message:`无法读取自动化任务`)}finally{!Z&&e===X&&(D.value=!1)}}async function $(){document.hidden||await Q(),Z||(ot=setTimeout($,5e3))}return o($),e(()=>{Z=!0,X++,clearTimeout(ot)}),(e,t)=>{let o=re(`RouterLink`);return r(),p(`main`,{class:`automations-page`,"aria-label":`自动化工作区`,onPointerdown:it,onKeydown:t[16]||=y(e=>I.value=!1,[`esc`])},[u(`header`,le,[u(`button`,{class:`icon-button`,type:`button`,"aria-label":`返回聊天`,onClick:t[0]||=e=>ne(h).push(Xe.value)},[_(v,{name:`chevron-left`,size:20})]),_(v,{name:`calendar`,size:23}),t[19]||=u(`h1`,null,`自动化`,-1),u(`div`,ue,[u(`button`,{role:`tab`,"aria-selected":N.value===`schedule`,onClick:t[1]||=e=>N.value=`schedule`},`日程`,8,de),u(`button`,{role:`tab`,"aria-selected":N.value===`logs`,onClick:t[2]||=e=>J()},`运行日志`,8,fe)]),Qe.value?(r(),p(`span`,pe,s(Qe.value)+` 项执行中`,1)):m(``,!0),u(`div`,me,[u(`button`,{class:`primary`,type:`button`,disabled:!w.value.length,"aria-expanded":I.value,onClick:at},[_(v,{name:`plus`,size:17}),t[17]||=c(`新建自动化`,-1)],8,he),I.value?(r(),p(`div`,{key:0,class:`new-menu`,role:`group`,"aria-label":`选择执行 Bot`,onKeydown:t[3]||=y(se(e=>I.value=!1,[`stop`]),[`esc`])},[t[18]||=u(`p`,null,`选择执行 Bot`,-1),(r(!0),p(l,null,a(w.value,e=>(r(),p(`button`,{key:e.id,type:`button`,onClick:t=>Y(e.id)},[_(x,{name:e.name,avatar:e.avatar,size:24},null,8,[`name`,`avatar`]),c(s(e.name),1)],8,ge))),128))],32)):m(``,!0)])]),u(`div`,_e,[u(`aside`,ve,[u(`label`,ye,[t[20]||=c(`查看日期`,-1),i(u(`input`,{"onUpdate:modelValue":t[4]||=e=>B.value=e,type:`date`},null,512),[[S,B.value]])]),u(`h2`,null,[t[21]||=c(`我的 Bot `,-1),u(`span`,null,s(w.value.length),1)]),i(u(`input`,{"onUpdate:modelValue":t[5]||=e=>A.value=e,type:`search`,"aria-label":`搜索 Bot`,placeholder:`搜索 Bot`},null,512),[[S,A.value]]),u(`nav`,be,[u(`button`,{"aria-current":k.value===`all`?`true`:void 0,onClick:t[6]||=e=>k.value=`all`},[_(v,{name:`users`,size:22}),t[22]||=c(`全部 Bot`,-1),u(`span`,null,s(T.value.length),1)],8,xe),(r(!0),p(l,null,a(Ze.value,e=>(r(),p(`button`,{key:e.id,"aria-current":k.value===e.id?`true`:void 0,onClick:t=>k.value=e.id},[_(x,{name:e.name,avatar:e.avatar,size:26},null,8,[`name`,`avatar`]),u(`strong`,null,s(e.name),1),u(`span`,null,s(T.value.filter(t=>t.agentId===e.id).length),1)],8,Se))),128))]),w.value.length?m(``,!0):(r(),p(`p`,Ce,`创建 Bot 后,即可安排自动执行的任务。`))]),u(`section`,we,[u(`div`,Te,[N.value===`schedule`?(r(),p(`div`,Ee,[u(`button`,{role:`tab`,"aria-selected":P.value===`calendar`,onClick:t[7]||=e=>P.value=`calendar`},`日历`,8,De),u(`button`,{role:`tab`,"aria-selected":P.value===`list`,onClick:t[8]||=e=>P.value=`list`},`任务列表`,8,Oe)])):m(``,!0),N.value===`schedule`&&P.value===`calendar`?(r(),p(l,{key:1},[u(`div`,ke,[u(`button`,{"aria-label":`上一周`,onClick:t[9]||=e=>q(-1)},[_(v,{name:`chevron-left`,size:16})]),u(`button`,{onClick:t[10]||=e=>B.value=z(new Date)},`今天`),u(`button`,{"aria-label":`下一周`,onClick:t[11]||=e=>q(1)},[_(v,{name:`chevron-left`,class:`next-icon`,size:16})])]),u(`span`,Ae,s($e.value),1)],64)):m(``,!0),i(u(`input`,{"onUpdate:modelValue":t[12]||=e=>j.value=e,class:`task-search`,type:`search`,"aria-label":N.value===`logs`?`搜索运行日志`:`搜索自动化任务`,placeholder:`搜索任务`},null,8,je),[[S,j.value]]),i(u(`select`,{"onUpdate:modelValue":t[13]||=e=>k.value=e,class:`mobile-bot-filter`,"aria-label":`筛选执行 Bot`},[t[23]||=u(`option`,{value:`all`},`全部 Bot`,-1),(r(!0),p(l,null,a(w.value,e=>(r(),p(`option`,{key:e.id,value:e.id},s(e.name),9,Me))),128))],512),[[b,k.value]]),N.value===`logs`?i((r(),p(`select`,{key:2,"onUpdate:modelValue":t[14]||=e=>M.value=e,"aria-label":`筛选执行状态`},[t[24]||=u(`option`,{value:`all`},`全部状态`,-1),(r(),p(l,null,a(H,(e,t)=>u(`option`,{key:t,value:t},s(e),9,Ne)),64))],512)),[[b,M.value]]):m(``,!0),u(`button`,{class:`icon-button`,"aria-label":`刷新自动化`,onClick:Q},[_(v,{name:`refresh`,size:17})])]),O.value?(r(),p(`p`,Pe,s(O.value),1)):m(``,!0),D.value?(r(),p(`p`,Fe,`正在读取自动化任务…`)):N.value===`schedule`&&P.value===`calendar`?(r(),p(l,{key:2},[t[25]||=u(`p`,{class:`calendar-note`},`显示每项任务的下次执行时间,按本地时区展示。`,-1),u(`div`,Ie,[(r(!0),p(l,null,a(G.value,e=>(r(),p(`section`,{key:e.key,class:n([`schedule-day`,{today:e.key===z(new Date)}]),"aria-label":e.key},[u(`header`,null,[u(`span`,null,`周`+s(e.weekday),1),u(`h2`,null,s(e.date.getDate()),1)]),(r(!0),p(l,null,a(et(e.key),e=>(r(),p(`button`,{key:e.id,class:`schedule-event`,onClick:t=>Y(e.agentId,e)},[u(`time`,null,s(nt(e.nextAt)),1),u(`strong`,null,s(e.name),1),u(`span`,null,s(K(e.agentId)?.name),1)],8,Re))),128)),et(e.key).length?m(``,!0):(r(),p(`p`,ze,`暂无任务`))],10,Le))),128))])],64)):N.value===`schedule`?(r(),p(`div`,Be,[U.value.length?m(``,!0):(r(),p(`p`,Ve,s(j.value?`没有匹配的任务。`:`还没有自动化任务。点击“新建自动化”安排工作。`),1)),(r(!0),p(l,null,a(U.value,e=>(r(),p(`article`,{key:e.id,class:`automation-card`},[_(x,{name:K(e.agentId)?.name??`Bot`,avatar:K(e.agentId)?.avatar??``,size:32},null,8,[`name`,`avatar`]),u(`button`,{class:`routine-description`,onClick:t=>Y(e.agentId,e)},[u(`h2`,null,s(e.name),1),u(`p`,null,s(K(e.agentId)?.name)+` · `+s(rt(e))+` · `+s(e.schedule.timezone),1),u(`small`,null,s(e.enabled?`下次执行:`+tt(e.nextAt):`已暂停`),1)],8,He),u(`span`,{class:n([`status-pill`,{enabled:e.enabled}])},s(e.enabled?`已启用`:`已暂停`),3),u(`button`,{class:`quiet`,onClick:t=>J(e.id)},`查看日志`,8,Ue)]))),128))])):(r(),p(`div`,We,[F.value?(r(),p(`p`,Ge,[c(`当前任务:`+s(T.value.find(e=>e.id===F.value)?.name??`自动化任务`)+` `,1),u(`button`,{onClick:t[15]||=e=>F.value=``},`显示全部`)])):m(``,!0),W.value.length?m(``,!0):(r(),p(`p`,Ke,`还没有符合条件的运行记录。`)),(r(!0),p(l,null,a(W.value,e=>(r(),p(`details`,{key:e.id,class:`run-card`},[u(`summary`,null,[u(`div`,null,[u(`strong`,null,s(T.value.find(t=>t.id===e.routineId)?.name??`自动化任务`),1),u(`p`,null,s(K(e.agentId)?.name)+` · `+s(tt(e.startedAt))+` · `+s(e.scheduledAt===0?`手动执行`:`定时执行`),1)]),u(`span`,{class:n({failure:e.status===`failed`,success:e.status===`complete`})},s(H[e.status]),3)]),e.error?(r(),p(`p`,qe,s(e.error),1)):(r(),p(`p`,Je,s(e.status===`complete`?`结果已发送到 Bot 聊天。`:`执行进度会自动更新。`),1)),e.conversationId?(r(),f(o,{key:2,to:`/conversations/`+e.conversationId},{default:ee(()=>[...t[26]||=[c(`查看聊天结果 ↗`,-1)]]),_:1},8,[`to`])):m(``,!0)]))),128))]))])]),L.value?(r(),f(ce,{key:L.value,ref_key:`editor`,ref:R,"agent-id":L.value,"editor-only":``,onChanged:Q,onExecuted:J},null,8,[`agent-id`])):m(``,!0)],32)}}}),[[`__scopeId`,`data-v-751789b5`]]);export{C as default};
|
|
2
|
-
//# sourceMappingURL=BotAutomationsView-
|
|
1
|
+
import{A as e,D as t,Et as n,F as r,G as i,L as a,M as o,Ot as s,W as ee,_ as c,a as l,b as te,d as u,et as d,f,m as p,p as m,st as ne,t as h,u as g,v as _,z as re}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{B as v,Q as ie,Z as ae,at as y,ct as b,j as oe,lt as se,o as x,ot as S}from"./index-P_kZCZ2-.js";import{t as ce}from"./WorkspaceRoutinesPanel-NFWzy1R-.js";var le={class:`automations-header`},ue={class:`segmented`,role:`tablist`,"aria-label":`自动化页面`},de=[`aria-selected`],fe=[`aria-selected`],pe={key:0,class:`running-count`},me={class:`new-automation`},he=[`disabled`,`aria-expanded`],ge=[`onClick`],_e={class:`automations-body`},ve={class:`automation-sidebar`,"aria-label":`自动化筛选`},ye={class:`date-filter`},be={"aria-label":`按 Bot 筛选`},xe=[`aria-current`],Se=[`aria-current`,`onClick`],Ce={key:0},we={class:`automation-content`},Te={class:`automation-toolbar`},Ee={key:0,class:`segmented`,role:`tablist`,"aria-label":`日程视图`},De=[`aria-selected`],Oe=[`aria-selected`],ke={class:`date-actions`},Ae={class:`range-label`},je=[`aria-label`],Me=[`value`],Ne=[`value`],Pe={key:0,class:`page-error`,role:`alert`},Fe={key:1,class:`loading`,role:`status`},Ie={class:`schedule-week`,"aria-label":`本周自动化日程`},Le=[`aria-label`],Re=[`onClick`],ze={key:0,class:`no-events`},Be={key:3,class:`automation-list`},Ve={key:0,class:`empty`},He=[`onClick`],Ue=[`onClick`],We={key:4,class:`automation-logs`},Ge={key:0,class:`log-scope`},Ke={key:1,class:`empty`},qe={key:0,class:`failure`},Je={key:1},C=h(te({__name:`BotAutomationsView`,setup(te){let h=ie(),C=ae(),w=d([]),T=d([]),E=d([]),D=d(!0),O=d(``),k=d(`all`),A=d(``),j=d(``),M=d(`all`),N=d(`schedule`),P=d(`calendar`),F=d(``),I=d(!1),L=d(``),R=d(),z=e=>`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`,B=d(z(new Date));function V(){let e=new Date(B.value+`T00:00:00`);return Number.isFinite(e.getTime())?e:new Date}let Ye=[`一`,`二`,`三`,`四`,`五`,`六`,`日`],H={queued:`排队中`,running:`执行中`,waiting:`等待处理`,complete:`已完成`,failed:`失败`,interrupted:`已停止`,uncertain:`状态待确认`,skipped:`已跳过`},Xe=g(()=>typeof C.query.from==`string`&&/^\/conversations(?:\/[a-f0-9-]{36})?(?:\?taskId=[a-f0-9-]{36})?$/i.test(C.query.from)?C.query.from:`/conversations`),Ze=g(()=>w.value.filter(e=>e.name.toLowerCase().includes(A.value.trim().toLowerCase()))),U=g(()=>T.value.filter(e=>(k.value===`all`||e.agentId===k.value)&&`${e.name} ${e.prompt}`.toLowerCase().includes(j.value.trim().toLowerCase())).sort((e,t)=>Number(t.enabled)-Number(e.enabled)||(e.nextAt??1/0)-(t.nextAt??1/0))),W=g(()=>E.value.filter(e=>(k.value===`all`||e.agentId===k.value)&&(!F.value||e.routineId===F.value)&&(M.value===`all`||e.status===M.value)&&`${T.value.find(t=>t.id===e.routineId)?.name??``} ${e.error??``}`.toLowerCase().includes(j.value.trim().toLowerCase()))),Qe=g(()=>E.value.filter(e=>[`queued`,`running`,`waiting`,`uncertain`].includes(e.status)).length),G=g(()=>{let e=V();return e.setDate(e.getDate()-(e.getDay()+6)%7),Ye.map((t,n)=>{let r=new Date(e);return r.setDate(r.getDate()+n),{date:r,key:z(r),weekday:t}})}),$e=g(()=>`${G.value[0].date.toLocaleDateString(`zh-CN`)} — ${G.value[6].date.toLocaleDateString(`zh-CN`)}`),et=e=>U.value.filter(t=>t.enabled&&t.nextAt&&z(new Date(t.nextAt))===e),K=e=>w.value.find(t=>t.id===e),tt=e=>e?new Date(e).toLocaleString(`zh-CN`,{hour12:!1}):`—`,nt=e=>e?new Date(e).toLocaleTimeString(`zh-CN`,{hour12:!1,hour:`2-digit`,minute:`2-digit`}):``,rt=e=>e.schedule.kind===`interval`?`每 ${e.schedule.everyMinutes} 分钟`:e.schedule.kind===`once`?`仅一次`:`${e.schedule.kind===`weekly`?`每周 `+(e.schedule.weekdays??[]).map(e=>`日一二三四五六`[e]).join(`、`):`每天`} ${e.schedule.time}`;function q(e){let t=V();t.setDate(t.getDate()+e*7),B.value=z(t)}function it(e){e.target instanceof Element&&!e.target.closest(`.new-automation`)&&(I.value=!1)}function J(e=``){N.value=`logs`,F.value=e,j.value=``,M.value=`all`}async function Y(e,n){I.value=!1,L.value=e,await t(),R.value?.edit(n)}function at(){let e=k.value===`all`?w.value.length===1?w.value[0].id:void 0:k.value;e?Y(e):I.value=!I.value}let X=0,Z=!1,ot;async function Q(){let e=++X;try{let t=await oe(`/api/app/bot-tools/automations`);if(Z||e!==X)return;w.value=t.agents,T.value=t.routines,E.value=t.runs,O.value=``,k.value!==`all`&&!w.value.some(e=>e.id===k.value)&&(k.value=`all`)}catch(t){!Z&&e===X&&(O.value=t instanceof Error?t.message:`无法读取自动化任务`)}finally{!Z&&e===X&&(D.value=!1)}}async function $(){document.hidden||await Q(),Z||(ot=setTimeout($,5e3))}return o($),e(()=>{Z=!0,X++,clearTimeout(ot)}),(e,t)=>{let o=re(`RouterLink`);return r(),p(`main`,{class:`automations-page`,"aria-label":`自动化工作区`,onPointerdown:it,onKeydown:t[16]||=b(e=>I.value=!1,[`esc`])},[u(`header`,le,[u(`button`,{class:`icon-button`,type:`button`,"aria-label":`返回聊天`,onClick:t[0]||=e=>ne(h).push(Xe.value)},[_(v,{name:`chevron-left`,size:20})]),_(v,{name:`calendar`,size:23}),t[19]||=u(`h1`,null,`自动化`,-1),u(`div`,ue,[u(`button`,{role:`tab`,"aria-selected":N.value===`schedule`,onClick:t[1]||=e=>N.value=`schedule`},`日程`,8,de),u(`button`,{role:`tab`,"aria-selected":N.value===`logs`,onClick:t[2]||=e=>J()},`运行日志`,8,fe)]),Qe.value?(r(),p(`span`,pe,s(Qe.value)+` 项执行中`,1)):m(``,!0),u(`div`,me,[u(`button`,{class:`primary`,type:`button`,disabled:!w.value.length,"aria-expanded":I.value,onClick:at},[_(v,{name:`plus`,size:17}),t[17]||=c(`新建自动化`,-1)],8,he),I.value?(r(),p(`div`,{key:0,class:`new-menu`,role:`group`,"aria-label":`选择执行 Bot`,onKeydown:t[3]||=b(se(e=>I.value=!1,[`stop`]),[`esc`])},[t[18]||=u(`p`,null,`选择执行 Bot`,-1),(r(!0),p(l,null,a(w.value,e=>(r(),p(`button`,{key:e.id,type:`button`,onClick:t=>Y(e.id)},[_(x,{name:e.name,avatar:e.avatar,size:24},null,8,[`name`,`avatar`]),c(s(e.name),1)],8,ge))),128))],32)):m(``,!0)])]),u(`div`,_e,[u(`aside`,ve,[u(`label`,ye,[t[20]||=c(`查看日期`,-1),i(u(`input`,{"onUpdate:modelValue":t[4]||=e=>B.value=e,type:`date`},null,512),[[S,B.value]])]),u(`h2`,null,[t[21]||=c(`我的 Bot `,-1),u(`span`,null,s(w.value.length),1)]),i(u(`input`,{"onUpdate:modelValue":t[5]||=e=>A.value=e,type:`search`,"aria-label":`搜索 Bot`,placeholder:`搜索 Bot`},null,512),[[S,A.value]]),u(`nav`,be,[u(`button`,{"aria-current":k.value===`all`?`true`:void 0,onClick:t[6]||=e=>k.value=`all`},[_(v,{name:`users`,size:22}),t[22]||=c(`全部 Bot`,-1),u(`span`,null,s(T.value.length),1)],8,xe),(r(!0),p(l,null,a(Ze.value,e=>(r(),p(`button`,{key:e.id,"aria-current":k.value===e.id?`true`:void 0,onClick:t=>k.value=e.id},[_(x,{name:e.name,avatar:e.avatar,size:26},null,8,[`name`,`avatar`]),u(`strong`,null,s(e.name),1),u(`span`,null,s(T.value.filter(t=>t.agentId===e.id).length),1)],8,Se))),128))]),w.value.length?m(``,!0):(r(),p(`p`,Ce,`创建 Bot 后,即可安排自动执行的任务。`))]),u(`section`,we,[u(`div`,Te,[N.value===`schedule`?(r(),p(`div`,Ee,[u(`button`,{role:`tab`,"aria-selected":P.value===`calendar`,onClick:t[7]||=e=>P.value=`calendar`},`日历`,8,De),u(`button`,{role:`tab`,"aria-selected":P.value===`list`,onClick:t[8]||=e=>P.value=`list`},`任务列表`,8,Oe)])):m(``,!0),N.value===`schedule`&&P.value===`calendar`?(r(),p(l,{key:1},[u(`div`,ke,[u(`button`,{"aria-label":`上一周`,onClick:t[9]||=e=>q(-1)},[_(v,{name:`chevron-left`,size:16})]),u(`button`,{onClick:t[10]||=e=>B.value=z(new Date)},`今天`),u(`button`,{"aria-label":`下一周`,onClick:t[11]||=e=>q(1)},[_(v,{name:`chevron-left`,class:`next-icon`,size:16})])]),u(`span`,Ae,s($e.value),1)],64)):m(``,!0),i(u(`input`,{"onUpdate:modelValue":t[12]||=e=>j.value=e,class:`task-search`,type:`search`,"aria-label":N.value===`logs`?`搜索运行日志`:`搜索自动化任务`,placeholder:`搜索任务`},null,8,je),[[S,j.value]]),i(u(`select`,{"onUpdate:modelValue":t[13]||=e=>k.value=e,class:`mobile-bot-filter`,"aria-label":`筛选执行 Bot`},[t[23]||=u(`option`,{value:`all`},`全部 Bot`,-1),(r(!0),p(l,null,a(w.value,e=>(r(),p(`option`,{key:e.id,value:e.id},s(e.name),9,Me))),128))],512),[[y,k.value]]),N.value===`logs`?i((r(),p(`select`,{key:2,"onUpdate:modelValue":t[14]||=e=>M.value=e,"aria-label":`筛选执行状态`},[t[24]||=u(`option`,{value:`all`},`全部状态`,-1),(r(),p(l,null,a(H,(e,t)=>u(`option`,{key:t,value:t},s(e),9,Ne)),64))],512)),[[y,M.value]]):m(``,!0),u(`button`,{class:`icon-button`,"aria-label":`刷新自动化`,onClick:Q},[_(v,{name:`refresh`,size:17})])]),O.value?(r(),p(`p`,Pe,s(O.value),1)):m(``,!0),D.value?(r(),p(`p`,Fe,`正在读取自动化任务…`)):N.value===`schedule`&&P.value===`calendar`?(r(),p(l,{key:2},[t[25]||=u(`p`,{class:`calendar-note`},`显示每项任务的下次执行时间,按本地时区展示。`,-1),u(`div`,Ie,[(r(!0),p(l,null,a(G.value,e=>(r(),p(`section`,{key:e.key,class:n([`schedule-day`,{today:e.key===z(new Date)}]),"aria-label":e.key},[u(`header`,null,[u(`span`,null,`周`+s(e.weekday),1),u(`h2`,null,s(e.date.getDate()),1)]),(r(!0),p(l,null,a(et(e.key),e=>(r(),p(`button`,{key:e.id,class:`schedule-event`,onClick:t=>Y(e.agentId,e)},[u(`time`,null,s(nt(e.nextAt)),1),u(`strong`,null,s(e.name),1),u(`span`,null,s(K(e.agentId)?.name),1)],8,Re))),128)),et(e.key).length?m(``,!0):(r(),p(`p`,ze,`暂无任务`))],10,Le))),128))])],64)):N.value===`schedule`?(r(),p(`div`,Be,[U.value.length?m(``,!0):(r(),p(`p`,Ve,s(j.value?`没有匹配的任务。`:`还没有自动化任务。点击“新建自动化”安排工作。`),1)),(r(!0),p(l,null,a(U.value,e=>(r(),p(`article`,{key:e.id,class:`automation-card`},[_(x,{name:K(e.agentId)?.name??`Bot`,avatar:K(e.agentId)?.avatar??``,size:32},null,8,[`name`,`avatar`]),u(`button`,{class:`routine-description`,onClick:t=>Y(e.agentId,e)},[u(`h2`,null,s(e.name),1),u(`p`,null,s(K(e.agentId)?.name)+` · `+s(rt(e))+` · `+s(e.schedule.timezone),1),u(`small`,null,s(e.enabled?`下次执行:`+tt(e.nextAt):`已暂停`),1)],8,He),u(`span`,{class:n([`status-pill`,{enabled:e.enabled}])},s(e.enabled?`已启用`:`已暂停`),3),u(`button`,{class:`quiet`,onClick:t=>J(e.id)},`查看日志`,8,Ue)]))),128))])):(r(),p(`div`,We,[F.value?(r(),p(`p`,Ge,[c(`当前任务:`+s(T.value.find(e=>e.id===F.value)?.name??`自动化任务`)+` `,1),u(`button`,{onClick:t[15]||=e=>F.value=``},`显示全部`)])):m(``,!0),W.value.length?m(``,!0):(r(),p(`p`,Ke,`还没有符合条件的运行记录。`)),(r(!0),p(l,null,a(W.value,e=>(r(),p(`details`,{key:e.id,class:`run-card`},[u(`summary`,null,[u(`div`,null,[u(`strong`,null,s(T.value.find(t=>t.id===e.routineId)?.name??`自动化任务`),1),u(`p`,null,s(K(e.agentId)?.name)+` · `+s(tt(e.startedAt))+` · `+s(e.scheduledAt===0?`手动执行`:`定时执行`),1)]),u(`span`,{class:n({failure:e.status===`failed`,success:e.status===`complete`})},s(H[e.status]),3)]),e.error?(r(),p(`p`,qe,s(e.error),1)):(r(),p(`p`,Je,s(e.status===`complete`?`结果已发送到 Bot 聊天。`:`执行进度会自动更新。`),1)),e.conversationId?(r(),f(o,{key:2,to:`/conversations/`+e.conversationId},{default:ee(()=>[...t[26]||=[c(`查看聊天结果 ↗`,-1)]]),_:1},8,[`to`])):m(``,!0)]))),128))]))])]),L.value?(r(),f(ce,{key:L.value,ref_key:`editor`,ref:R,"agent-id":L.value,"editor-only":``,onChanged:Q,onExecuted:J},null,8,[`agent-id`])):m(``,!0)],32)}}}),[[`__scopeId`,`data-v-751789b5`]]);export{C as default};
|
|
2
|
+
//# sourceMappingURL=BotAutomationsView-C4EwHtYy.js.map
|
package/dist/assets/{BotAutomationsView-J9Y7Unoq.js.map → BotAutomationsView-C4EwHtYy.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BotAutomationsView-J9Y7Unoq.js","names":[],"sources":["../../src/client/views/BotAutomationsView.vue","../../src/client/views/BotAutomationsView.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { apiRequest } from '@/api/client'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport WorkspaceRoutinesPanel from '@/components/workspace/WorkspaceRoutinesPanel.vue'\nimport type { WorkspaceAgent } from '@shared/workspace'\nimport type { WorkspaceRoutine, WorkspaceRoutineRun } from '@shared/workspacePanels'\n\ntype Bot = Pick<WorkspaceAgent, 'id' | 'name' | 'avatar'>\nconst router = useRouter(), route = useRoute()\nconst agents = ref<Bot[]>([]), routines = ref<WorkspaceRoutine[]>([]), runs = ref<WorkspaceRoutineRun[]>([])\nconst loading = ref(true), error = ref(''), botFilter = ref('all'), botQuery = ref(''), query = ref(''), stateFilter = ref('all')\nconst section = ref<'schedule' | 'logs'>('schedule'), view = ref<'calendar' | 'list'>('calendar'), routineFilter = ref(''), newMenu = ref(false)\nconst editorAgent = ref(''), editor = ref<InstanceType<typeof WorkspaceRoutinesPanel>>()\nconst dateKey = (date: Date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`\nconst anchor = ref(dateKey(new Date()))\nfunction anchorDate() { const date = new Date(anchor.value + 'T00:00:00'); return Number.isFinite(date.getTime()) ? date : new Date() }\nconst weekdays = ['一', '二', '三', '四', '五', '六', '日']\nconst status: Record<string, string> = { queued: '排队中', running: '执行中', waiting: '等待处理', complete: '已完成', failed: '失败', interrupted: '已停止', uncertain: '状态待确认', skipped: '已跳过' }\nconst backPath = computed(() => typeof route.query.from === 'string' && /^\\/conversations(?:\\/[a-f0-9-]{36})?(?:\\?taskId=[a-f0-9-]{36})?$/i.test(route.query.from) ? route.query.from : '/conversations')\nconst sidebarBots = computed(() => agents.value.filter(a => a.name.toLowerCase().includes(botQuery.value.trim().toLowerCase())))\nconst visibleRoutines = computed(() => routines.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && `${r.name} ${r.prompt}`.toLowerCase().includes(query.value.trim().toLowerCase())).sort((a, b) => Number(b.enabled) - Number(a.enabled) || (a.nextAt ?? Infinity) - (b.nextAt ?? Infinity)))\nconst visibleRuns = computed(() => runs.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && (!routineFilter.value || r.routineId === routineFilter.value) && (stateFilter.value === 'all' || r.status === stateFilter.value) && `${routines.value.find(t => t.id === r.routineId)?.name ?? ''} ${r.error ?? ''}`.toLowerCase().includes(query.value.trim().toLowerCase())))\nconst running = computed(() => runs.value.filter(r => ['queued', 'running', 'waiting', 'uncertain'].includes(r.status)).length)\nconst days = computed(() => {\n const first = anchorDate()\n first.setDate(first.getDate() - (first.getDay() + 6) % 7)\n return weekdays.map((weekday, offset) => { const date = new Date(first); date.setDate(date.getDate() + offset); return { date, key: dateKey(date), weekday } })\n})\nconst rangeLabel = computed(() => `${days.value[0]!.date.toLocaleDateString('zh-CN')} — ${days.value[6]!.date.toLocaleDateString('zh-CN')}`)\nconst scheduled = (key: string) => visibleRoutines.value.filter(r => r.enabled && r.nextAt && dateKey(new Date(r.nextAt)) === key)\nconst agent = (id: string) => agents.value.find(a => a.id === id)\nconst date = (at?: number) => at ? new Date(at).toLocaleString('zh-CN', { hour12: false }) : '—'\nconst time = (at?: number) => at ? new Date(at).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit' }) : ''\nconst schedule = (r: WorkspaceRoutine) => r.schedule.kind === 'interval' ? `每 ${r.schedule.everyMinutes} 分钟` : r.schedule.kind === 'once' ? '仅一次' : `${r.schedule.kind === 'weekly' ? '每周 ' + (r.schedule.weekdays ?? []).map(i => '日一二三四五六'[i]).join('、') : '每天'} ${r.schedule.time}`\nfunction moveWeek(direction: number) { const date = anchorDate(); date.setDate(date.getDate() + direction * 7); anchor.value = dateKey(date) }\nfunction closeNewMenu(event: PointerEvent) { if (event.target instanceof Element && !event.target.closest('.new-automation')) newMenu.value = false }\nfunction showLogs(id = '') { section.value = 'logs'; routineFilter.value = id; query.value = ''; stateFilter.value = 'all' }\nasync function openEditor(botId: string, routine?: WorkspaceRoutine) {\n newMenu.value = false; editorAgent.value = botId\n await nextTick(); editor.value?.edit(routine)\n}\nfunction create() {\n const target = botFilter.value !== 'all' ? botFilter.value : agents.value.length === 1 ? agents.value[0]!.id : undefined\n if (target) void openEditor(target)\n else newMenu.value = !newMenu.value\n}\nlet generation = 0, closed = false, timer: ReturnType<typeof setTimeout> | undefined\nasync function load() {\n const current = ++generation\n try {\n const result = await apiRequest<{ agents: Bot[]; routines: WorkspaceRoutine[]; runs: WorkspaceRoutineRun[] }>('/api/app/bot-tools/automations')\n if (closed || current !== generation) return\n agents.value = result.agents; routines.value = result.routines; runs.value = result.runs; error.value = ''\n if (botFilter.value !== 'all' && !agents.value.some(a => a.id === botFilter.value)) botFilter.value = 'all'\n } catch (e) { if (!closed && current === generation) error.value = e instanceof Error ? e.message : '无法读取自动化任务' }\n finally { if (!closed && current === generation) loading.value = false }\n}\nasync function poll() { if (!document.hidden) await load(); if (!closed) timer = setTimeout(poll, 5000) }\nonMounted(poll)\nonBeforeUnmount(() => { closed = true; generation++; clearTimeout(timer) })\n</script>\n\n<template>\n <main class=\"automations-page\" aria-label=\"自动化工作区\" @pointerdown=\"closeNewMenu\" @keydown.esc=\"newMenu = false\">\n <header class=\"automations-header\">\n <button class=\"icon-button\" type=\"button\" aria-label=\"返回聊天\" @click=\"router.push(backPath)\"><AppIcon name=\"chevron-left\" :size=\"20\" /></button>\n <AppIcon name=\"calendar\" :size=\"23\" /><h1>自动化</h1>\n <div class=\"segmented\" role=\"tablist\" aria-label=\"自动化页面\"><button role=\"tab\" :aria-selected=\"section === 'schedule'\" @click=\"section = 'schedule'\">日程</button><button role=\"tab\" :aria-selected=\"section === 'logs'\" @click=\"showLogs()\">运行日志</button></div>\n <span v-if=\"running\" class=\"running-count\">{{ running }} 项执行中</span>\n <div class=\"new-automation\"><button class=\"primary\" type=\"button\" :disabled=\"!agents.length\" :aria-expanded=\"newMenu\" @click=\"create\"><AppIcon name=\"plus\" :size=\"17\" />新建自动化</button><div v-if=\"newMenu\" class=\"new-menu\" role=\"group\" aria-label=\"选择执行 Bot\" @keydown.esc.stop=\"newMenu = false\"><p>选择执行 Bot</p><button v-for=\"bot in agents\" :key=\"bot.id\" type=\"button\" @click=\"openEditor(bot.id)\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"24\" />{{ bot.name }}</button></div></div>\n </header>\n <div class=\"automations-body\">\n <aside class=\"automation-sidebar\" aria-label=\"自动化筛选\">\n <label class=\"date-filter\">查看日期<input v-model=\"anchor\" type=\"date\" /></label>\n <h2>我的 Bot <span>{{ agents.length }}</span></h2><input v-model=\"botQuery\" type=\"search\" aria-label=\"搜索 Bot\" placeholder=\"搜索 Bot\" />\n <nav aria-label=\"按 Bot 筛选\"><button :aria-current=\"botFilter === 'all' ? 'true' : undefined\" @click=\"botFilter = 'all'\"><AppIcon name=\"users\" :size=\"22\" />全部 Bot<span>{{ routines.length }}</span></button><button v-for=\"bot in sidebarBots\" :key=\"bot.id\" :aria-current=\"botFilter === bot.id ? 'true' : undefined\" @click=\"botFilter = bot.id\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"26\" /><strong>{{ bot.name }}</strong><span>{{ routines.filter(r => r.agentId === bot.id).length }}</span></button></nav>\n <p v-if=\"!agents.length\">创建 Bot 后,即可安排自动执行的任务。</p>\n </aside>\n <section class=\"automation-content\">\n <div class=\"automation-toolbar\">\n <div v-if=\"section === 'schedule'\" class=\"segmented\" role=\"tablist\" aria-label=\"日程视图\"><button role=\"tab\" :aria-selected=\"view === 'calendar'\" @click=\"view = 'calendar'\">日历</button><button role=\"tab\" :aria-selected=\"view === 'list'\" @click=\"view = 'list'\">任务列表</button></div>\n <template v-if=\"section === 'schedule' && view === 'calendar'\"><div class=\"date-actions\"><button aria-label=\"上一周\" @click=\"moveWeek(-1)\"><AppIcon name=\"chevron-left\" :size=\"16\" /></button><button @click=\"anchor = dateKey(new Date())\">今天</button><button aria-label=\"下一周\" @click=\"moveWeek(1)\"><AppIcon name=\"chevron-left\" class=\"next-icon\" :size=\"16\" /></button></div><span class=\"range-label\">{{ rangeLabel }}</span></template>\n <input v-model=\"query\" class=\"task-search\" type=\"search\" :aria-label=\"section === 'logs' ? '搜索运行日志' : '搜索自动化任务'\" placeholder=\"搜索任务\" />\n <select v-model=\"botFilter\" class=\"mobile-bot-filter\" aria-label=\"筛选执行 Bot\"><option value=\"all\">全部 Bot</option><option v-for=\"bot in agents\" :key=\"bot.id\" :value=\"bot.id\">{{ bot.name }}</option></select>\n <select v-if=\"section === 'logs'\" v-model=\"stateFilter\" aria-label=\"筛选执行状态\"><option value=\"all\">全部状态</option><option v-for=\"(label, key) in status\" :key=\"key\" :value=\"key\">{{ label }}</option></select>\n <button class=\"icon-button\" aria-label=\"刷新自动化\" @click=\"load\"><AppIcon name=\"refresh\" :size=\"17\" /></button>\n </div>\n <p v-if=\"error\" class=\"page-error\" role=\"alert\">{{ error }}</p><p v-if=\"loading\" class=\"loading\" role=\"status\">正在读取自动化任务…</p>\n <template v-else-if=\"section === 'schedule' && view === 'calendar'\">\n <p class=\"calendar-note\">显示每项任务的下次执行时间,按本地时区展示。</p>\n <div class=\"schedule-week\" aria-label=\"本周自动化日程\"><section v-for=\"day in days\" :key=\"day.key\" class=\"schedule-day\" :class=\"{ today: day.key === dateKey(new Date()) }\" :aria-label=\"day.key\"><header><span>周{{ day.weekday }}</span><h2>{{ day.date.getDate() }}</h2></header><button v-for=\"routine in scheduled(day.key)\" :key=\"routine.id\" class=\"schedule-event\" @click=\"openEditor(routine.agentId, routine)\"><time>{{ time(routine.nextAt) }}</time><strong>{{ routine.name }}</strong><span>{{ agent(routine.agentId)?.name }}</span></button><p v-if=\"!scheduled(day.key).length\" class=\"no-events\">暂无任务</p></section></div>\n </template>\n <div v-else-if=\"section === 'schedule'\" class=\"automation-list\">\n <p v-if=\"!visibleRoutines.length\" class=\"empty\">{{ query ? '没有匹配的任务。' : '还没有自动化任务。点击“新建自动化”安排工作。' }}</p>\n <article v-for=\"routine in visibleRoutines\" :key=\"routine.id\" class=\"automation-card\"><AgentAvatar :name=\"agent(routine.agentId)?.name ?? 'Bot'\" :avatar=\"agent(routine.agentId)?.avatar ?? ''\" :size=\"32\" /><button class=\"routine-description\" @click=\"openEditor(routine.agentId, routine)\"><h2>{{ routine.name }}</h2><p>{{ agent(routine.agentId)?.name }} · {{ schedule(routine) }} · {{ routine.schedule.timezone }}</p><small>{{ routine.enabled ? '下次执行:' + date(routine.nextAt) : '已暂停' }}</small></button><span class=\"status-pill\" :class=\"{ enabled: routine.enabled }\">{{ routine.enabled ? '已启用' : '已暂停' }}</span><button class=\"quiet\" @click=\"showLogs(routine.id)\">查看日志</button></article>\n </div>\n <div v-else class=\"automation-logs\">\n <p v-if=\"routineFilter\" class=\"log-scope\">当前任务:{{ routines.find(r => r.id === routineFilter)?.name ?? '自动化任务' }} <button @click=\"routineFilter = ''\">显示全部</button></p>\n <p v-if=\"!visibleRuns.length\" class=\"empty\">还没有符合条件的运行记录。</p>\n <details v-for=\"run in visibleRuns\" :key=\"run.id\" class=\"run-card\"><summary><div><strong>{{ routines.find(r => r.id === run.routineId)?.name ?? '自动化任务' }}</strong><p>{{ agent(run.agentId)?.name }} · {{ date(run.startedAt) }} · {{ run.scheduledAt === 0 ? '手动执行' : '定时执行' }}</p></div><span :class=\"{ failure: run.status === 'failed', success: run.status === 'complete' }\">{{ status[run.status] }}</span></summary><p v-if=\"run.error\" class=\"failure\">{{ run.error }}</p><p v-else>{{ run.status === 'complete' ? '结果已发送到 Bot 聊天。' : '执行进度会自动更新。' }}</p><RouterLink v-if=\"run.conversationId\" :to=\"'/conversations/' + run.conversationId\">查看聊天结果 ↗</RouterLink></details>\n </div>\n </section>\n </div>\n <WorkspaceRoutinesPanel v-if=\"editorAgent\" :key=\"editorAgent\" ref=\"editor\" :agent-id=\"editorAgent\" editor-only @changed=\"load\" @executed=\"showLogs\" />\n </main>\n</template>\n\n<style scoped>\n.automations-page{height:100dvh;display:flex;flex-direction:column;background:var(--canvas);color:var(--text-primary);min-width:0}.automations-header{display:flex;align-items:center;gap:12px;min-height:72px;box-sizing:border-box;padding:12px 24px;border-bottom:1px solid var(--line);background:var(--surface)}h1{font-size:20px;margin:0 20px 0 0;letter-spacing:-.02em}.automations-page button,.automations-page input,.automations-page select{font:inherit;font-size:13px;color:inherit;border:1px solid var(--line);border-radius:9px;background:var(--surface);padding:8px 11px;min-height:40px;box-sizing:border-box}.automations-page button{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px}.automations-page button:hover{background:var(--surface-hover)}.automations-page button:disabled{opacity:.45;cursor:not-allowed}.automations-page :is(button,input,select,a,summary):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.automations-page .icon-button{padding:8px;width:40px;flex-shrink:0}.automations-page .primary{background:var(--accent);border-color:var(--accent);color:var(--text-on-solid);font-weight:600}.segmented{display:flex;gap:3px;border:1px solid var(--line);border-radius:10px;padding:3px;background:var(--surface)}.segmented button{min-height:32px;border:0;background:transparent;white-space:nowrap}.segmented button[aria-selected=true]{background:var(--surface-soft);font-weight:600}.new-automation{margin-left:auto;position:relative}.new-menu{position:absolute;right:0;top:calc(100% + 8px);z-index:10;width:250px;max-height:340px;overflow:auto;padding:8px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-float)}.new-menu p{font-size:12px;color:var(--text-muted);margin:5px 8px}.new-menu button{width:100%;justify-content:flex-start;border:0}.running-count{font-size:12px;color:var(--accent)}.automations-body{display:flex;flex:1;min-height:0}.automation-sidebar{width:224px;flex-shrink:0;box-sizing:border-box;padding:24px 16px;border-right:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;gap:12px;overflow:auto}.date-filter{display:grid;gap:8px;font-size:12px;color:var(--text-secondary);padding-bottom:20px;border-bottom:1px solid var(--line)}.automation-sidebar h2{display:flex;justify-content:space-between;font-size:13px;margin:8px 2px 0}.automation-sidebar h2 span{color:var(--text-muted);font-weight:400}.automation-sidebar input{width:100%;min-width:0}.automation-sidebar nav{display:grid;gap:4px}.automation-sidebar nav button{width:100%;justify-content:flex-start;border:0;text-align:left;min-width:0}.automation-sidebar nav button[aria-current]{background:var(--surface-soft)}.automation-sidebar nav strong{font-size:13px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.automation-sidebar nav span{margin-left:auto;font-size:12px;color:var(--text-muted)}.automation-sidebar>p{font-size:12px;color:var(--text-secondary);line-height:1.7}.automation-content{flex:1;min-width:0;overflow:auto;padding:20px 24px}.automation-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px}.date-actions{display:flex;gap:3px}.date-actions button{border:0;background:transparent}.next-icon{transform:rotate(180deg)}.range-label{font-size:13px;font-weight:550}.task-search{margin-left:auto;width:170px;min-width:100px}.mobile-bot-filter{display:none}.calendar-note{font-size:12px;color:var(--text-muted);margin:0 0 14px}.schedule-week{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));min-height:450px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--surface)}.schedule-day{min-width:0;border-right:1px solid var(--line);padding:10px 7px}.schedule-day:last-child{border-right:0}.schedule-day>header{display:grid;justify-items:center;gap:6px;padding:8px 0 16px}.schedule-day>header span{font-size:12px;color:var(--text-muted)}.schedule-day h2{font-size:22px;margin:0;font-weight:500}.schedule-day.today{background:color-mix(in srgb,var(--accent) 4%,var(--surface))}.schedule-day.today h2{color:var(--accent);font-weight:650}.automations-page .schedule-event{display:grid;justify-content:stretch;gap:7px;width:100%;text-align:left;align-items:start;margin-bottom:8px;padding:10px 9px;background:color-mix(in srgb,var(--accent) 7%,var(--surface));border-color:color-mix(in srgb,var(--accent) 25%,var(--line));overflow-wrap:anywhere}.schedule-event time{font-size:11px;color:var(--accent)}.schedule-event strong{font-size:12px;line-height:1.5}.schedule-event span{font-size:11px;color:var(--text-secondary)}.no-events{font-size:11px;color:var(--text-muted);text-align:center;padding:24px 0}.automation-list,.automation-logs{display:grid;gap:12px}.automation-card{display:flex;align-items:center;gap:14px;padding:18px;border:1px solid var(--line);border-radius:14px;background:var(--surface);min-width:0}.automations-page .routine-description{display:block;flex:1;min-width:0;padding:0;text-align:left;background:transparent;border:0}.routine-description h2{margin:0 0 7px;font-size:15px;font-weight:600}.routine-description p{margin:0 0 6px;font-size:12px;color:var(--text-secondary);line-height:1.6}.routine-description small{font-size:12px;color:var(--text-muted)}.status-pill{font-size:11px;color:var(--text-muted);white-space:nowrap;padding:5px 8px;border-radius:99px;background:var(--surface-soft)}.status-pill.enabled{color:var(--accent)}.automations-page .quiet{border:0;background:transparent;white-space:nowrap}.run-card{padding:18px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-size:13px;line-height:1.7}.run-card summary{display:flex;justify-content:space-between;gap:16px;cursor:pointer;list-style:none;min-height:44px}.run-card summary::-webkit-details-marker{display:none}.run-card p{font-size:12px;color:var(--text-secondary);margin:5px 0}.run-card a{color:var(--accent)}.run-card summary>span{white-space:nowrap}.failure,.page-error{color:var(--danger)!important}.success{color:var(--accent)}.page-error{padding:12px;border-radius:9px;background:var(--surface);font-size:13px}.empty,.loading{padding:50px 20px;text-align:center;color:var(--text-secondary);font-size:13px;line-height:1.8}.log-scope{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary)}@media(max-width:1000px){.automations-header{padding:12px 16px;flex-wrap:wrap;gap:8px}h1{margin-right:8px}.automation-sidebar{width:190px}.automation-content{padding:18px 16px}.range-label{order:3;width:100%}.schedule-week{grid-template-columns:repeat(7,minmax(0,1fr))}.schedule-day{padding:8px 4px}}@media(max-width:760px){.automation-sidebar{display:none}.mobile-bot-filter{display:block;max-width:160px}.automations-page button{min-height:44px}.automations-header{padding:10px 12px}.automations-header .segmented{order:3}.running-count{display:none}.automations-body{display:block;overflow:hidden}.automation-content{height:100%;box-sizing:border-box;padding:16px 12px}.schedule-week{grid-template-columns:1fr;min-height:0;border:0;border-radius:0;background:transparent;gap:10px}.schedule-day{display:grid;grid-template-columns:56px minmax(0,1fr);align-items:start;padding:12px;border:1px solid var(--line)!important;border-radius:12px;background:var(--surface)}.schedule-day>header{grid-row:1 / span 50;padding:2px 8px 0 0}.schedule-event{grid-column:2}.no-events{text-align:left;padding:10px;margin:0}.task-search{flex:1;width:130px}.range-label{font-size:12px}.automation-card{flex-wrap:wrap;padding:14px;gap:10px}.automation-card>.routine-description{flex-basis:calc(100% - 48px)}.automation-card>.status-pill{margin-left:42px}.automation-card>.quiet{margin-left:auto}.automation-toolbar{gap:8px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { apiRequest } from '@/api/client'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport WorkspaceRoutinesPanel from '@/components/workspace/WorkspaceRoutinesPanel.vue'\nimport type { WorkspaceAgent } from '@shared/workspace'\nimport type { WorkspaceRoutine, WorkspaceRoutineRun } from '@shared/workspacePanels'\n\ntype Bot = Pick<WorkspaceAgent, 'id' | 'name' | 'avatar'>\nconst router = useRouter(), route = useRoute()\nconst agents = ref<Bot[]>([]), routines = ref<WorkspaceRoutine[]>([]), runs = ref<WorkspaceRoutineRun[]>([])\nconst loading = ref(true), error = ref(''), botFilter = ref('all'), botQuery = ref(''), query = ref(''), stateFilter = ref('all')\nconst section = ref<'schedule' | 'logs'>('schedule'), view = ref<'calendar' | 'list'>('calendar'), routineFilter = ref(''), newMenu = ref(false)\nconst editorAgent = ref(''), editor = ref<InstanceType<typeof WorkspaceRoutinesPanel>>()\nconst dateKey = (date: Date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`\nconst anchor = ref(dateKey(new Date()))\nfunction anchorDate() { const date = new Date(anchor.value + 'T00:00:00'); return Number.isFinite(date.getTime()) ? date : new Date() }\nconst weekdays = ['一', '二', '三', '四', '五', '六', '日']\nconst status: Record<string, string> = { queued: '排队中', running: '执行中', waiting: '等待处理', complete: '已完成', failed: '失败', interrupted: '已停止', uncertain: '状态待确认', skipped: '已跳过' }\nconst backPath = computed(() => typeof route.query.from === 'string' && /^\\/conversations(?:\\/[a-f0-9-]{36})?(?:\\?taskId=[a-f0-9-]{36})?$/i.test(route.query.from) ? route.query.from : '/conversations')\nconst sidebarBots = computed(() => agents.value.filter(a => a.name.toLowerCase().includes(botQuery.value.trim().toLowerCase())))\nconst visibleRoutines = computed(() => routines.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && `${r.name} ${r.prompt}`.toLowerCase().includes(query.value.trim().toLowerCase())).sort((a, b) => Number(b.enabled) - Number(a.enabled) || (a.nextAt ?? Infinity) - (b.nextAt ?? Infinity)))\nconst visibleRuns = computed(() => runs.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && (!routineFilter.value || r.routineId === routineFilter.value) && (stateFilter.value === 'all' || r.status === stateFilter.value) && `${routines.value.find(t => t.id === r.routineId)?.name ?? ''} ${r.error ?? ''}`.toLowerCase().includes(query.value.trim().toLowerCase())))\nconst running = computed(() => runs.value.filter(r => ['queued', 'running', 'waiting', 'uncertain'].includes(r.status)).length)\nconst days = computed(() => {\n const first = anchorDate()\n first.setDate(first.getDate() - (first.getDay() + 6) % 7)\n return weekdays.map((weekday, offset) => { const date = new Date(first); date.setDate(date.getDate() + offset); return { date, key: dateKey(date), weekday } })\n})\nconst rangeLabel = computed(() => `${days.value[0]!.date.toLocaleDateString('zh-CN')} — ${days.value[6]!.date.toLocaleDateString('zh-CN')}`)\nconst scheduled = (key: string) => visibleRoutines.value.filter(r => r.enabled && r.nextAt && dateKey(new Date(r.nextAt)) === key)\nconst agent = (id: string) => agents.value.find(a => a.id === id)\nconst date = (at?: number) => at ? new Date(at).toLocaleString('zh-CN', { hour12: false }) : '—'\nconst time = (at?: number) => at ? new Date(at).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit' }) : ''\nconst schedule = (r: WorkspaceRoutine) => r.schedule.kind === 'interval' ? `每 ${r.schedule.everyMinutes} 分钟` : r.schedule.kind === 'once' ? '仅一次' : `${r.schedule.kind === 'weekly' ? '每周 ' + (r.schedule.weekdays ?? []).map(i => '日一二三四五六'[i]).join('、') : '每天'} ${r.schedule.time}`\nfunction moveWeek(direction: number) { const date = anchorDate(); date.setDate(date.getDate() + direction * 7); anchor.value = dateKey(date) }\nfunction closeNewMenu(event: PointerEvent) { if (event.target instanceof Element && !event.target.closest('.new-automation')) newMenu.value = false }\nfunction showLogs(id = '') { section.value = 'logs'; routineFilter.value = id; query.value = ''; stateFilter.value = 'all' }\nasync function openEditor(botId: string, routine?: WorkspaceRoutine) {\n newMenu.value = false; editorAgent.value = botId\n await nextTick(); editor.value?.edit(routine)\n}\nfunction create() {\n const target = botFilter.value !== 'all' ? botFilter.value : agents.value.length === 1 ? agents.value[0]!.id : undefined\n if (target) void openEditor(target)\n else newMenu.value = !newMenu.value\n}\nlet generation = 0, closed = false, timer: ReturnType<typeof setTimeout> | undefined\nasync function load() {\n const current = ++generation\n try {\n const result = await apiRequest<{ agents: Bot[]; routines: WorkspaceRoutine[]; runs: WorkspaceRoutineRun[] }>('/api/app/bot-tools/automations')\n if (closed || current !== generation) return\n agents.value = result.agents; routines.value = result.routines; runs.value = result.runs; error.value = ''\n if (botFilter.value !== 'all' && !agents.value.some(a => a.id === botFilter.value)) botFilter.value = 'all'\n } catch (e) { if (!closed && current === generation) error.value = e instanceof Error ? e.message : '无法读取自动化任务' }\n finally { if (!closed && current === generation) loading.value = false }\n}\nasync function poll() { if (!document.hidden) await load(); if (!closed) timer = setTimeout(poll, 5000) }\nonMounted(poll)\nonBeforeUnmount(() => { closed = true; generation++; clearTimeout(timer) })\n</script>\n\n<template>\n <main class=\"automations-page\" aria-label=\"自动化工作区\" @pointerdown=\"closeNewMenu\" @keydown.esc=\"newMenu = false\">\n <header class=\"automations-header\">\n <button class=\"icon-button\" type=\"button\" aria-label=\"返回聊天\" @click=\"router.push(backPath)\"><AppIcon name=\"chevron-left\" :size=\"20\" /></button>\n <AppIcon name=\"calendar\" :size=\"23\" /><h1>自动化</h1>\n <div class=\"segmented\" role=\"tablist\" aria-label=\"自动化页面\"><button role=\"tab\" :aria-selected=\"section === 'schedule'\" @click=\"section = 'schedule'\">日程</button><button role=\"tab\" :aria-selected=\"section === 'logs'\" @click=\"showLogs()\">运行日志</button></div>\n <span v-if=\"running\" class=\"running-count\">{{ running }} 项执行中</span>\n <div class=\"new-automation\"><button class=\"primary\" type=\"button\" :disabled=\"!agents.length\" :aria-expanded=\"newMenu\" @click=\"create\"><AppIcon name=\"plus\" :size=\"17\" />新建自动化</button><div v-if=\"newMenu\" class=\"new-menu\" role=\"group\" aria-label=\"选择执行 Bot\" @keydown.esc.stop=\"newMenu = false\"><p>选择执行 Bot</p><button v-for=\"bot in agents\" :key=\"bot.id\" type=\"button\" @click=\"openEditor(bot.id)\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"24\" />{{ bot.name }}</button></div></div>\n </header>\n <div class=\"automations-body\">\n <aside class=\"automation-sidebar\" aria-label=\"自动化筛选\">\n <label class=\"date-filter\">查看日期<input v-model=\"anchor\" type=\"date\" /></label>\n <h2>我的 Bot <span>{{ agents.length }}</span></h2><input v-model=\"botQuery\" type=\"search\" aria-label=\"搜索 Bot\" placeholder=\"搜索 Bot\" />\n <nav aria-label=\"按 Bot 筛选\"><button :aria-current=\"botFilter === 'all' ? 'true' : undefined\" @click=\"botFilter = 'all'\"><AppIcon name=\"users\" :size=\"22\" />全部 Bot<span>{{ routines.length }}</span></button><button v-for=\"bot in sidebarBots\" :key=\"bot.id\" :aria-current=\"botFilter === bot.id ? 'true' : undefined\" @click=\"botFilter = bot.id\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"26\" /><strong>{{ bot.name }}</strong><span>{{ routines.filter(r => r.agentId === bot.id).length }}</span></button></nav>\n <p v-if=\"!agents.length\">创建 Bot 后,即可安排自动执行的任务。</p>\n </aside>\n <section class=\"automation-content\">\n <div class=\"automation-toolbar\">\n <div v-if=\"section === 'schedule'\" class=\"segmented\" role=\"tablist\" aria-label=\"日程视图\"><button role=\"tab\" :aria-selected=\"view === 'calendar'\" @click=\"view = 'calendar'\">日历</button><button role=\"tab\" :aria-selected=\"view === 'list'\" @click=\"view = 'list'\">任务列表</button></div>\n <template v-if=\"section === 'schedule' && view === 'calendar'\"><div class=\"date-actions\"><button aria-label=\"上一周\" @click=\"moveWeek(-1)\"><AppIcon name=\"chevron-left\" :size=\"16\" /></button><button @click=\"anchor = dateKey(new Date())\">今天</button><button aria-label=\"下一周\" @click=\"moveWeek(1)\"><AppIcon name=\"chevron-left\" class=\"next-icon\" :size=\"16\" /></button></div><span class=\"range-label\">{{ rangeLabel }}</span></template>\n <input v-model=\"query\" class=\"task-search\" type=\"search\" :aria-label=\"section === 'logs' ? '搜索运行日志' : '搜索自动化任务'\" placeholder=\"搜索任务\" />\n <select v-model=\"botFilter\" class=\"mobile-bot-filter\" aria-label=\"筛选执行 Bot\"><option value=\"all\">全部 Bot</option><option v-for=\"bot in agents\" :key=\"bot.id\" :value=\"bot.id\">{{ bot.name }}</option></select>\n <select v-if=\"section === 'logs'\" v-model=\"stateFilter\" aria-label=\"筛选执行状态\"><option value=\"all\">全部状态</option><option v-for=\"(label, key) in status\" :key=\"key\" :value=\"key\">{{ label }}</option></select>\n <button class=\"icon-button\" aria-label=\"刷新自动化\" @click=\"load\"><AppIcon name=\"refresh\" :size=\"17\" /></button>\n </div>\n <p v-if=\"error\" class=\"page-error\" role=\"alert\">{{ error }}</p><p v-if=\"loading\" class=\"loading\" role=\"status\">正在读取自动化任务…</p>\n <template v-else-if=\"section === 'schedule' && view === 'calendar'\">\n <p class=\"calendar-note\">显示每项任务的下次执行时间,按本地时区展示。</p>\n <div class=\"schedule-week\" aria-label=\"本周自动化日程\"><section v-for=\"day in days\" :key=\"day.key\" class=\"schedule-day\" :class=\"{ today: day.key === dateKey(new Date()) }\" :aria-label=\"day.key\"><header><span>周{{ day.weekday }}</span><h2>{{ day.date.getDate() }}</h2></header><button v-for=\"routine in scheduled(day.key)\" :key=\"routine.id\" class=\"schedule-event\" @click=\"openEditor(routine.agentId, routine)\"><time>{{ time(routine.nextAt) }}</time><strong>{{ routine.name }}</strong><span>{{ agent(routine.agentId)?.name }}</span></button><p v-if=\"!scheduled(day.key).length\" class=\"no-events\">暂无任务</p></section></div>\n </template>\n <div v-else-if=\"section === 'schedule'\" class=\"automation-list\">\n <p v-if=\"!visibleRoutines.length\" class=\"empty\">{{ query ? '没有匹配的任务。' : '还没有自动化任务。点击“新建自动化”安排工作。' }}</p>\n <article v-for=\"routine in visibleRoutines\" :key=\"routine.id\" class=\"automation-card\"><AgentAvatar :name=\"agent(routine.agentId)?.name ?? 'Bot'\" :avatar=\"agent(routine.agentId)?.avatar ?? ''\" :size=\"32\" /><button class=\"routine-description\" @click=\"openEditor(routine.agentId, routine)\"><h2>{{ routine.name }}</h2><p>{{ agent(routine.agentId)?.name }} · {{ schedule(routine) }} · {{ routine.schedule.timezone }}</p><small>{{ routine.enabled ? '下次执行:' + date(routine.nextAt) : '已暂停' }}</small></button><span class=\"status-pill\" :class=\"{ enabled: routine.enabled }\">{{ routine.enabled ? '已启用' : '已暂停' }}</span><button class=\"quiet\" @click=\"showLogs(routine.id)\">查看日志</button></article>\n </div>\n <div v-else class=\"automation-logs\">\n <p v-if=\"routineFilter\" class=\"log-scope\">当前任务:{{ routines.find(r => r.id === routineFilter)?.name ?? '自动化任务' }} <button @click=\"routineFilter = ''\">显示全部</button></p>\n <p v-if=\"!visibleRuns.length\" class=\"empty\">还没有符合条件的运行记录。</p>\n <details v-for=\"run in visibleRuns\" :key=\"run.id\" class=\"run-card\"><summary><div><strong>{{ routines.find(r => r.id === run.routineId)?.name ?? '自动化任务' }}</strong><p>{{ agent(run.agentId)?.name }} · {{ date(run.startedAt) }} · {{ run.scheduledAt === 0 ? '手动执行' : '定时执行' }}</p></div><span :class=\"{ failure: run.status === 'failed', success: run.status === 'complete' }\">{{ status[run.status] }}</span></summary><p v-if=\"run.error\" class=\"failure\">{{ run.error }}</p><p v-else>{{ run.status === 'complete' ? '结果已发送到 Bot 聊天。' : '执行进度会自动更新。' }}</p><RouterLink v-if=\"run.conversationId\" :to=\"'/conversations/' + run.conversationId\">查看聊天结果 ↗</RouterLink></details>\n </div>\n </section>\n </div>\n <WorkspaceRoutinesPanel v-if=\"editorAgent\" :key=\"editorAgent\" ref=\"editor\" :agent-id=\"editorAgent\" editor-only @changed=\"load\" @executed=\"showLogs\" />\n </main>\n</template>\n\n<style scoped>\n.automations-page{height:100dvh;display:flex;flex-direction:column;background:var(--canvas);color:var(--text-primary);min-width:0}.automations-header{display:flex;align-items:center;gap:12px;min-height:72px;box-sizing:border-box;padding:12px 24px;border-bottom:1px solid var(--line);background:var(--surface)}h1{font-size:20px;margin:0 20px 0 0;letter-spacing:-.02em}.automations-page button,.automations-page input,.automations-page select{font:inherit;font-size:13px;color:inherit;border:1px solid var(--line);border-radius:9px;background:var(--surface);padding:8px 11px;min-height:40px;box-sizing:border-box}.automations-page button{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px}.automations-page button:hover{background:var(--surface-hover)}.automations-page button:disabled{opacity:.45;cursor:not-allowed}.automations-page :is(button,input,select,a,summary):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.automations-page .icon-button{padding:8px;width:40px;flex-shrink:0}.automations-page .primary{background:var(--accent);border-color:var(--accent);color:var(--text-on-solid);font-weight:600}.segmented{display:flex;gap:3px;border:1px solid var(--line);border-radius:10px;padding:3px;background:var(--surface)}.segmented button{min-height:32px;border:0;background:transparent;white-space:nowrap}.segmented button[aria-selected=true]{background:var(--surface-soft);font-weight:600}.new-automation{margin-left:auto;position:relative}.new-menu{position:absolute;right:0;top:calc(100% + 8px);z-index:10;width:250px;max-height:340px;overflow:auto;padding:8px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-float)}.new-menu p{font-size:12px;color:var(--text-muted);margin:5px 8px}.new-menu button{width:100%;justify-content:flex-start;border:0}.running-count{font-size:12px;color:var(--accent)}.automations-body{display:flex;flex:1;min-height:0}.automation-sidebar{width:224px;flex-shrink:0;box-sizing:border-box;padding:24px 16px;border-right:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;gap:12px;overflow:auto}.date-filter{display:grid;gap:8px;font-size:12px;color:var(--text-secondary);padding-bottom:20px;border-bottom:1px solid var(--line)}.automation-sidebar h2{display:flex;justify-content:space-between;font-size:13px;margin:8px 2px 0}.automation-sidebar h2 span{color:var(--text-muted);font-weight:400}.automation-sidebar input{width:100%;min-width:0}.automation-sidebar nav{display:grid;gap:4px}.automation-sidebar nav button{width:100%;justify-content:flex-start;border:0;text-align:left;min-width:0}.automation-sidebar nav button[aria-current]{background:var(--surface-soft)}.automation-sidebar nav strong{font-size:13px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.automation-sidebar nav span{margin-left:auto;font-size:12px;color:var(--text-muted)}.automation-sidebar>p{font-size:12px;color:var(--text-secondary);line-height:1.7}.automation-content{flex:1;min-width:0;overflow:auto;padding:20px 24px}.automation-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px}.date-actions{display:flex;gap:3px}.date-actions button{border:0;background:transparent}.next-icon{transform:rotate(180deg)}.range-label{font-size:13px;font-weight:550}.task-search{margin-left:auto;width:170px;min-width:100px}.mobile-bot-filter{display:none}.calendar-note{font-size:12px;color:var(--text-muted);margin:0 0 14px}.schedule-week{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));min-height:450px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--surface)}.schedule-day{min-width:0;border-right:1px solid var(--line);padding:10px 7px}.schedule-day:last-child{border-right:0}.schedule-day>header{display:grid;justify-items:center;gap:6px;padding:8px 0 16px}.schedule-day>header span{font-size:12px;color:var(--text-muted)}.schedule-day h2{font-size:22px;margin:0;font-weight:500}.schedule-day.today{background:color-mix(in srgb,var(--accent) 4%,var(--surface))}.schedule-day.today h2{color:var(--accent);font-weight:650}.automations-page .schedule-event{display:grid;justify-content:stretch;gap:7px;width:100%;text-align:left;align-items:start;margin-bottom:8px;padding:10px 9px;background:color-mix(in srgb,var(--accent) 7%,var(--surface));border-color:color-mix(in srgb,var(--accent) 25%,var(--line));overflow-wrap:anywhere}.schedule-event time{font-size:11px;color:var(--accent)}.schedule-event strong{font-size:12px;line-height:1.5}.schedule-event span{font-size:11px;color:var(--text-secondary)}.no-events{font-size:11px;color:var(--text-muted);text-align:center;padding:24px 0}.automation-list,.automation-logs{display:grid;gap:12px}.automation-card{display:flex;align-items:center;gap:14px;padding:18px;border:1px solid var(--line);border-radius:14px;background:var(--surface);min-width:0}.automations-page .routine-description{display:block;flex:1;min-width:0;padding:0;text-align:left;background:transparent;border:0}.routine-description h2{margin:0 0 7px;font-size:15px;font-weight:600}.routine-description p{margin:0 0 6px;font-size:12px;color:var(--text-secondary);line-height:1.6}.routine-description small{font-size:12px;color:var(--text-muted)}.status-pill{font-size:11px;color:var(--text-muted);white-space:nowrap;padding:5px 8px;border-radius:99px;background:var(--surface-soft)}.status-pill.enabled{color:var(--accent)}.automations-page .quiet{border:0;background:transparent;white-space:nowrap}.run-card{padding:18px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-size:13px;line-height:1.7}.run-card summary{display:flex;justify-content:space-between;gap:16px;cursor:pointer;list-style:none;min-height:44px}.run-card summary::-webkit-details-marker{display:none}.run-card p{font-size:12px;color:var(--text-secondary);margin:5px 0}.run-card a{color:var(--accent)}.run-card summary>span{white-space:nowrap}.failure,.page-error{color:var(--danger)!important}.success{color:var(--accent)}.page-error{padding:12px;border-radius:9px;background:var(--surface);font-size:13px}.empty,.loading{padding:50px 20px;text-align:center;color:var(--text-secondary);font-size:13px;line-height:1.8}.log-scope{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary)}@media(max-width:1000px){.automations-header{padding:12px 16px;flex-wrap:wrap;gap:8px}h1{margin-right:8px}.automation-sidebar{width:190px}.automation-content{padding:18px 16px}.range-label{order:3;width:100%}.schedule-week{grid-template-columns:repeat(7,minmax(0,1fr))}.schedule-day{padding:8px 4px}}@media(max-width:760px){.automation-sidebar{display:none}.mobile-bot-filter{display:block;max-width:160px}.automations-page button{min-height:44px}.automations-header{padding:10px 12px}.automations-header .segmented{order:3}.running-count{display:none}.automations-body{display:block;overflow:hidden}.automation-content{height:100%;box-sizing:border-box;padding:16px 12px}.schedule-week{grid-template-columns:1fr;min-height:0;border:0;border-radius:0;background:transparent;gap:10px}.schedule-day{display:grid;grid-template-columns:56px minmax(0,1fr);align-items:start;padding:12px;border:1px solid var(--line)!important;border-radius:12px;background:var(--surface)}.schedule-day>header{grid-row:1 / span 50;padding:2px 8px 0 0}.schedule-event{grid-column:2}.no-events{text-align:left;padding:10px;margin:0}.task-search{flex:1;width:130px}.range-label{font-size:12px}.automation-card{flex-wrap:wrap;padding:14px;gap:10px}.automation-card>.routine-description{flex-basis:calc(100% - 48px)}.automation-card>.status-pill{margin-left:42px}.automation-card>.quiet{margin-left:auto}.automation-toolbar{gap:8px}}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BotAutomationsView-C4EwHtYy.js","names":[],"sources":["../../src/client/views/BotAutomationsView.vue","../../src/client/views/BotAutomationsView.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { apiRequest } from '@/api/client'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport WorkspaceRoutinesPanel from '@/components/workspace/WorkspaceRoutinesPanel.vue'\nimport type { WorkspaceAgent } from '@shared/workspace'\nimport type { WorkspaceRoutine, WorkspaceRoutineRun } from '@shared/workspacePanels'\n\ntype Bot = Pick<WorkspaceAgent, 'id' | 'name' | 'avatar'>\nconst router = useRouter(), route = useRoute()\nconst agents = ref<Bot[]>([]), routines = ref<WorkspaceRoutine[]>([]), runs = ref<WorkspaceRoutineRun[]>([])\nconst loading = ref(true), error = ref(''), botFilter = ref('all'), botQuery = ref(''), query = ref(''), stateFilter = ref('all')\nconst section = ref<'schedule' | 'logs'>('schedule'), view = ref<'calendar' | 'list'>('calendar'), routineFilter = ref(''), newMenu = ref(false)\nconst editorAgent = ref(''), editor = ref<InstanceType<typeof WorkspaceRoutinesPanel>>()\nconst dateKey = (date: Date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`\nconst anchor = ref(dateKey(new Date()))\nfunction anchorDate() { const date = new Date(anchor.value + 'T00:00:00'); return Number.isFinite(date.getTime()) ? date : new Date() }\nconst weekdays = ['一', '二', '三', '四', '五', '六', '日']\nconst status: Record<string, string> = { queued: '排队中', running: '执行中', waiting: '等待处理', complete: '已完成', failed: '失败', interrupted: '已停止', uncertain: '状态待确认', skipped: '已跳过' }\nconst backPath = computed(() => typeof route.query.from === 'string' && /^\\/conversations(?:\\/[a-f0-9-]{36})?(?:\\?taskId=[a-f0-9-]{36})?$/i.test(route.query.from) ? route.query.from : '/conversations')\nconst sidebarBots = computed(() => agents.value.filter(a => a.name.toLowerCase().includes(botQuery.value.trim().toLowerCase())))\nconst visibleRoutines = computed(() => routines.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && `${r.name} ${r.prompt}`.toLowerCase().includes(query.value.trim().toLowerCase())).sort((a, b) => Number(b.enabled) - Number(a.enabled) || (a.nextAt ?? Infinity) - (b.nextAt ?? Infinity)))\nconst visibleRuns = computed(() => runs.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && (!routineFilter.value || r.routineId === routineFilter.value) && (stateFilter.value === 'all' || r.status === stateFilter.value) && `${routines.value.find(t => t.id === r.routineId)?.name ?? ''} ${r.error ?? ''}`.toLowerCase().includes(query.value.trim().toLowerCase())))\nconst running = computed(() => runs.value.filter(r => ['queued', 'running', 'waiting', 'uncertain'].includes(r.status)).length)\nconst days = computed(() => {\n const first = anchorDate()\n first.setDate(first.getDate() - (first.getDay() + 6) % 7)\n return weekdays.map((weekday, offset) => { const date = new Date(first); date.setDate(date.getDate() + offset); return { date, key: dateKey(date), weekday } })\n})\nconst rangeLabel = computed(() => `${days.value[0]!.date.toLocaleDateString('zh-CN')} — ${days.value[6]!.date.toLocaleDateString('zh-CN')}`)\nconst scheduled = (key: string) => visibleRoutines.value.filter(r => r.enabled && r.nextAt && dateKey(new Date(r.nextAt)) === key)\nconst agent = (id: string) => agents.value.find(a => a.id === id)\nconst date = (at?: number) => at ? new Date(at).toLocaleString('zh-CN', { hour12: false }) : '—'\nconst time = (at?: number) => at ? new Date(at).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit' }) : ''\nconst schedule = (r: WorkspaceRoutine) => r.schedule.kind === 'interval' ? `每 ${r.schedule.everyMinutes} 分钟` : r.schedule.kind === 'once' ? '仅一次' : `${r.schedule.kind === 'weekly' ? '每周 ' + (r.schedule.weekdays ?? []).map(i => '日一二三四五六'[i]).join('、') : '每天'} ${r.schedule.time}`\nfunction moveWeek(direction: number) { const date = anchorDate(); date.setDate(date.getDate() + direction * 7); anchor.value = dateKey(date) }\nfunction closeNewMenu(event: PointerEvent) { if (event.target instanceof Element && !event.target.closest('.new-automation')) newMenu.value = false }\nfunction showLogs(id = '') { section.value = 'logs'; routineFilter.value = id; query.value = ''; stateFilter.value = 'all' }\nasync function openEditor(botId: string, routine?: WorkspaceRoutine) {\n newMenu.value = false; editorAgent.value = botId\n await nextTick(); editor.value?.edit(routine)\n}\nfunction create() {\n const target = botFilter.value !== 'all' ? botFilter.value : agents.value.length === 1 ? agents.value[0]!.id : undefined\n if (target) void openEditor(target)\n else newMenu.value = !newMenu.value\n}\nlet generation = 0, closed = false, timer: ReturnType<typeof setTimeout> | undefined\nasync function load() {\n const current = ++generation\n try {\n const result = await apiRequest<{ agents: Bot[]; routines: WorkspaceRoutine[]; runs: WorkspaceRoutineRun[] }>('/api/app/bot-tools/automations')\n if (closed || current !== generation) return\n agents.value = result.agents; routines.value = result.routines; runs.value = result.runs; error.value = ''\n if (botFilter.value !== 'all' && !agents.value.some(a => a.id === botFilter.value)) botFilter.value = 'all'\n } catch (e) { if (!closed && current === generation) error.value = e instanceof Error ? e.message : '无法读取自动化任务' }\n finally { if (!closed && current === generation) loading.value = false }\n}\nasync function poll() { if (!document.hidden) await load(); if (!closed) timer = setTimeout(poll, 5000) }\nonMounted(poll)\nonBeforeUnmount(() => { closed = true; generation++; clearTimeout(timer) })\n</script>\n\n<template>\n <main class=\"automations-page\" aria-label=\"自动化工作区\" @pointerdown=\"closeNewMenu\" @keydown.esc=\"newMenu = false\">\n <header class=\"automations-header\">\n <button class=\"icon-button\" type=\"button\" aria-label=\"返回聊天\" @click=\"router.push(backPath)\"><AppIcon name=\"chevron-left\" :size=\"20\" /></button>\n <AppIcon name=\"calendar\" :size=\"23\" /><h1>自动化</h1>\n <div class=\"segmented\" role=\"tablist\" aria-label=\"自动化页面\"><button role=\"tab\" :aria-selected=\"section === 'schedule'\" @click=\"section = 'schedule'\">日程</button><button role=\"tab\" :aria-selected=\"section === 'logs'\" @click=\"showLogs()\">运行日志</button></div>\n <span v-if=\"running\" class=\"running-count\">{{ running }} 项执行中</span>\n <div class=\"new-automation\"><button class=\"primary\" type=\"button\" :disabled=\"!agents.length\" :aria-expanded=\"newMenu\" @click=\"create\"><AppIcon name=\"plus\" :size=\"17\" />新建自动化</button><div v-if=\"newMenu\" class=\"new-menu\" role=\"group\" aria-label=\"选择执行 Bot\" @keydown.esc.stop=\"newMenu = false\"><p>选择执行 Bot</p><button v-for=\"bot in agents\" :key=\"bot.id\" type=\"button\" @click=\"openEditor(bot.id)\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"24\" />{{ bot.name }}</button></div></div>\n </header>\n <div class=\"automations-body\">\n <aside class=\"automation-sidebar\" aria-label=\"自动化筛选\">\n <label class=\"date-filter\">查看日期<input v-model=\"anchor\" type=\"date\" /></label>\n <h2>我的 Bot <span>{{ agents.length }}</span></h2><input v-model=\"botQuery\" type=\"search\" aria-label=\"搜索 Bot\" placeholder=\"搜索 Bot\" />\n <nav aria-label=\"按 Bot 筛选\"><button :aria-current=\"botFilter === 'all' ? 'true' : undefined\" @click=\"botFilter = 'all'\"><AppIcon name=\"users\" :size=\"22\" />全部 Bot<span>{{ routines.length }}</span></button><button v-for=\"bot in sidebarBots\" :key=\"bot.id\" :aria-current=\"botFilter === bot.id ? 'true' : undefined\" @click=\"botFilter = bot.id\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"26\" /><strong>{{ bot.name }}</strong><span>{{ routines.filter(r => r.agentId === bot.id).length }}</span></button></nav>\n <p v-if=\"!agents.length\">创建 Bot 后,即可安排自动执行的任务。</p>\n </aside>\n <section class=\"automation-content\">\n <div class=\"automation-toolbar\">\n <div v-if=\"section === 'schedule'\" class=\"segmented\" role=\"tablist\" aria-label=\"日程视图\"><button role=\"tab\" :aria-selected=\"view === 'calendar'\" @click=\"view = 'calendar'\">日历</button><button role=\"tab\" :aria-selected=\"view === 'list'\" @click=\"view = 'list'\">任务列表</button></div>\n <template v-if=\"section === 'schedule' && view === 'calendar'\"><div class=\"date-actions\"><button aria-label=\"上一周\" @click=\"moveWeek(-1)\"><AppIcon name=\"chevron-left\" :size=\"16\" /></button><button @click=\"anchor = dateKey(new Date())\">今天</button><button aria-label=\"下一周\" @click=\"moveWeek(1)\"><AppIcon name=\"chevron-left\" class=\"next-icon\" :size=\"16\" /></button></div><span class=\"range-label\">{{ rangeLabel }}</span></template>\n <input v-model=\"query\" class=\"task-search\" type=\"search\" :aria-label=\"section === 'logs' ? '搜索运行日志' : '搜索自动化任务'\" placeholder=\"搜索任务\" />\n <select v-model=\"botFilter\" class=\"mobile-bot-filter\" aria-label=\"筛选执行 Bot\"><option value=\"all\">全部 Bot</option><option v-for=\"bot in agents\" :key=\"bot.id\" :value=\"bot.id\">{{ bot.name }}</option></select>\n <select v-if=\"section === 'logs'\" v-model=\"stateFilter\" aria-label=\"筛选执行状态\"><option value=\"all\">全部状态</option><option v-for=\"(label, key) in status\" :key=\"key\" :value=\"key\">{{ label }}</option></select>\n <button class=\"icon-button\" aria-label=\"刷新自动化\" @click=\"load\"><AppIcon name=\"refresh\" :size=\"17\" /></button>\n </div>\n <p v-if=\"error\" class=\"page-error\" role=\"alert\">{{ error }}</p><p v-if=\"loading\" class=\"loading\" role=\"status\">正在读取自动化任务…</p>\n <template v-else-if=\"section === 'schedule' && view === 'calendar'\">\n <p class=\"calendar-note\">显示每项任务的下次执行时间,按本地时区展示。</p>\n <div class=\"schedule-week\" aria-label=\"本周自动化日程\"><section v-for=\"day in days\" :key=\"day.key\" class=\"schedule-day\" :class=\"{ today: day.key === dateKey(new Date()) }\" :aria-label=\"day.key\"><header><span>周{{ day.weekday }}</span><h2>{{ day.date.getDate() }}</h2></header><button v-for=\"routine in scheduled(day.key)\" :key=\"routine.id\" class=\"schedule-event\" @click=\"openEditor(routine.agentId, routine)\"><time>{{ time(routine.nextAt) }}</time><strong>{{ routine.name }}</strong><span>{{ agent(routine.agentId)?.name }}</span></button><p v-if=\"!scheduled(day.key).length\" class=\"no-events\">暂无任务</p></section></div>\n </template>\n <div v-else-if=\"section === 'schedule'\" class=\"automation-list\">\n <p v-if=\"!visibleRoutines.length\" class=\"empty\">{{ query ? '没有匹配的任务。' : '还没有自动化任务。点击“新建自动化”安排工作。' }}</p>\n <article v-for=\"routine in visibleRoutines\" :key=\"routine.id\" class=\"automation-card\"><AgentAvatar :name=\"agent(routine.agentId)?.name ?? 'Bot'\" :avatar=\"agent(routine.agentId)?.avatar ?? ''\" :size=\"32\" /><button class=\"routine-description\" @click=\"openEditor(routine.agentId, routine)\"><h2>{{ routine.name }}</h2><p>{{ agent(routine.agentId)?.name }} · {{ schedule(routine) }} · {{ routine.schedule.timezone }}</p><small>{{ routine.enabled ? '下次执行:' + date(routine.nextAt) : '已暂停' }}</small></button><span class=\"status-pill\" :class=\"{ enabled: routine.enabled }\">{{ routine.enabled ? '已启用' : '已暂停' }}</span><button class=\"quiet\" @click=\"showLogs(routine.id)\">查看日志</button></article>\n </div>\n <div v-else class=\"automation-logs\">\n <p v-if=\"routineFilter\" class=\"log-scope\">当前任务:{{ routines.find(r => r.id === routineFilter)?.name ?? '自动化任务' }} <button @click=\"routineFilter = ''\">显示全部</button></p>\n <p v-if=\"!visibleRuns.length\" class=\"empty\">还没有符合条件的运行记录。</p>\n <details v-for=\"run in visibleRuns\" :key=\"run.id\" class=\"run-card\"><summary><div><strong>{{ routines.find(r => r.id === run.routineId)?.name ?? '自动化任务' }}</strong><p>{{ agent(run.agentId)?.name }} · {{ date(run.startedAt) }} · {{ run.scheduledAt === 0 ? '手动执行' : '定时执行' }}</p></div><span :class=\"{ failure: run.status === 'failed', success: run.status === 'complete' }\">{{ status[run.status] }}</span></summary><p v-if=\"run.error\" class=\"failure\">{{ run.error }}</p><p v-else>{{ run.status === 'complete' ? '结果已发送到 Bot 聊天。' : '执行进度会自动更新。' }}</p><RouterLink v-if=\"run.conversationId\" :to=\"'/conversations/' + run.conversationId\">查看聊天结果 ↗</RouterLink></details>\n </div>\n </section>\n </div>\n <WorkspaceRoutinesPanel v-if=\"editorAgent\" :key=\"editorAgent\" ref=\"editor\" :agent-id=\"editorAgent\" editor-only @changed=\"load\" @executed=\"showLogs\" />\n </main>\n</template>\n\n<style scoped>\n.automations-page{height:100dvh;display:flex;flex-direction:column;background:var(--canvas);color:var(--text-primary);min-width:0}.automations-header{display:flex;align-items:center;gap:12px;min-height:72px;box-sizing:border-box;padding:12px 24px;border-bottom:1px solid var(--line);background:var(--surface)}h1{font-size:20px;margin:0 20px 0 0;letter-spacing:-.02em}.automations-page button,.automations-page input,.automations-page select{font:inherit;font-size:13px;color:inherit;border:1px solid var(--line);border-radius:9px;background:var(--surface);padding:8px 11px;min-height:40px;box-sizing:border-box}.automations-page button{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px}.automations-page button:hover{background:var(--surface-hover)}.automations-page button:disabled{opacity:.45;cursor:not-allowed}.automations-page :is(button,input,select,a,summary):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.automations-page .icon-button{padding:8px;width:40px;flex-shrink:0}.automations-page .primary{background:var(--accent);border-color:var(--accent);color:var(--text-on-solid);font-weight:600}.segmented{display:flex;gap:3px;border:1px solid var(--line);border-radius:10px;padding:3px;background:var(--surface)}.segmented button{min-height:32px;border:0;background:transparent;white-space:nowrap}.segmented button[aria-selected=true]{background:var(--surface-soft);font-weight:600}.new-automation{margin-left:auto;position:relative}.new-menu{position:absolute;right:0;top:calc(100% + 8px);z-index:10;width:250px;max-height:340px;overflow:auto;padding:8px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-float)}.new-menu p{font-size:12px;color:var(--text-muted);margin:5px 8px}.new-menu button{width:100%;justify-content:flex-start;border:0}.running-count{font-size:12px;color:var(--accent)}.automations-body{display:flex;flex:1;min-height:0}.automation-sidebar{width:224px;flex-shrink:0;box-sizing:border-box;padding:24px 16px;border-right:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;gap:12px;overflow:auto}.date-filter{display:grid;gap:8px;font-size:12px;color:var(--text-secondary);padding-bottom:20px;border-bottom:1px solid var(--line)}.automation-sidebar h2{display:flex;justify-content:space-between;font-size:13px;margin:8px 2px 0}.automation-sidebar h2 span{color:var(--text-muted);font-weight:400}.automation-sidebar input{width:100%;min-width:0}.automation-sidebar nav{display:grid;gap:4px}.automation-sidebar nav button{width:100%;justify-content:flex-start;border:0;text-align:left;min-width:0}.automation-sidebar nav button[aria-current]{background:var(--surface-soft)}.automation-sidebar nav strong{font-size:13px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.automation-sidebar nav span{margin-left:auto;font-size:12px;color:var(--text-muted)}.automation-sidebar>p{font-size:12px;color:var(--text-secondary);line-height:1.7}.automation-content{flex:1;min-width:0;overflow:auto;padding:20px 24px}.automation-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px}.date-actions{display:flex;gap:3px}.date-actions button{border:0;background:transparent}.next-icon{transform:rotate(180deg)}.range-label{font-size:13px;font-weight:550}.task-search{margin-left:auto;width:170px;min-width:100px}.mobile-bot-filter{display:none}.calendar-note{font-size:12px;color:var(--text-muted);margin:0 0 14px}.schedule-week{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));min-height:450px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--surface)}.schedule-day{min-width:0;border-right:1px solid var(--line);padding:10px 7px}.schedule-day:last-child{border-right:0}.schedule-day>header{display:grid;justify-items:center;gap:6px;padding:8px 0 16px}.schedule-day>header span{font-size:12px;color:var(--text-muted)}.schedule-day h2{font-size:22px;margin:0;font-weight:500}.schedule-day.today{background:color-mix(in srgb,var(--accent) 4%,var(--surface))}.schedule-day.today h2{color:var(--accent);font-weight:650}.automations-page .schedule-event{display:grid;justify-content:stretch;gap:7px;width:100%;text-align:left;align-items:start;margin-bottom:8px;padding:10px 9px;background:color-mix(in srgb,var(--accent) 7%,var(--surface));border-color:color-mix(in srgb,var(--accent) 25%,var(--line));overflow-wrap:anywhere}.schedule-event time{font-size:11px;color:var(--accent)}.schedule-event strong{font-size:12px;line-height:1.5}.schedule-event span{font-size:11px;color:var(--text-secondary)}.no-events{font-size:11px;color:var(--text-muted);text-align:center;padding:24px 0}.automation-list,.automation-logs{display:grid;gap:12px}.automation-card{display:flex;align-items:center;gap:14px;padding:18px;border:1px solid var(--line);border-radius:14px;background:var(--surface);min-width:0}.automations-page .routine-description{display:block;flex:1;min-width:0;padding:0;text-align:left;background:transparent;border:0}.routine-description h2{margin:0 0 7px;font-size:15px;font-weight:600}.routine-description p{margin:0 0 6px;font-size:12px;color:var(--text-secondary);line-height:1.6}.routine-description small{font-size:12px;color:var(--text-muted)}.status-pill{font-size:11px;color:var(--text-muted);white-space:nowrap;padding:5px 8px;border-radius:99px;background:var(--surface-soft)}.status-pill.enabled{color:var(--accent)}.automations-page .quiet{border:0;background:transparent;white-space:nowrap}.run-card{padding:18px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-size:13px;line-height:1.7}.run-card summary{display:flex;justify-content:space-between;gap:16px;cursor:pointer;list-style:none;min-height:44px}.run-card summary::-webkit-details-marker{display:none}.run-card p{font-size:12px;color:var(--text-secondary);margin:5px 0}.run-card a{color:var(--accent)}.run-card summary>span{white-space:nowrap}.failure,.page-error{color:var(--danger)!important}.success{color:var(--accent)}.page-error{padding:12px;border-radius:9px;background:var(--surface);font-size:13px}.empty,.loading{padding:50px 20px;text-align:center;color:var(--text-secondary);font-size:13px;line-height:1.8}.log-scope{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary)}@media(max-width:1000px){.automations-header{padding:12px 16px;flex-wrap:wrap;gap:8px}h1{margin-right:8px}.automation-sidebar{width:190px}.automation-content{padding:18px 16px}.range-label{order:3;width:100%}.schedule-week{grid-template-columns:repeat(7,minmax(0,1fr))}.schedule-day{padding:8px 4px}}@media(max-width:760px){.automation-sidebar{display:none}.mobile-bot-filter{display:block;max-width:160px}.automations-page button{min-height:44px}.automations-header{padding:10px 12px}.automations-header .segmented{order:3}.running-count{display:none}.automations-body{display:block;overflow:hidden}.automation-content{height:100%;box-sizing:border-box;padding:16px 12px}.schedule-week{grid-template-columns:1fr;min-height:0;border:0;border-radius:0;background:transparent;gap:10px}.schedule-day{display:grid;grid-template-columns:56px minmax(0,1fr);align-items:start;padding:12px;border:1px solid var(--line)!important;border-radius:12px;background:var(--surface)}.schedule-day>header{grid-row:1 / span 50;padding:2px 8px 0 0}.schedule-event{grid-column:2}.no-events{text-align:left;padding:10px;margin:0}.task-search{flex:1;width:130px}.range-label{font-size:12px}.automation-card{flex-wrap:wrap;padding:14px;gap:10px}.automation-card>.routine-description{flex-basis:calc(100% - 48px)}.automation-card>.status-pill{margin-left:42px}.automation-card>.quiet{margin-left:auto}.automation-toolbar{gap:8px}}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { apiRequest } from '@/api/client'\nimport AppIcon from '@/components/common/AppIcon.vue'\nimport AgentAvatar from '@/components/common/AgentAvatar.vue'\nimport WorkspaceRoutinesPanel from '@/components/workspace/WorkspaceRoutinesPanel.vue'\nimport type { WorkspaceAgent } from '@shared/workspace'\nimport type { WorkspaceRoutine, WorkspaceRoutineRun } from '@shared/workspacePanels'\n\ntype Bot = Pick<WorkspaceAgent, 'id' | 'name' | 'avatar'>\nconst router = useRouter(), route = useRoute()\nconst agents = ref<Bot[]>([]), routines = ref<WorkspaceRoutine[]>([]), runs = ref<WorkspaceRoutineRun[]>([])\nconst loading = ref(true), error = ref(''), botFilter = ref('all'), botQuery = ref(''), query = ref(''), stateFilter = ref('all')\nconst section = ref<'schedule' | 'logs'>('schedule'), view = ref<'calendar' | 'list'>('calendar'), routineFilter = ref(''), newMenu = ref(false)\nconst editorAgent = ref(''), editor = ref<InstanceType<typeof WorkspaceRoutinesPanel>>()\nconst dateKey = (date: Date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`\nconst anchor = ref(dateKey(new Date()))\nfunction anchorDate() { const date = new Date(anchor.value + 'T00:00:00'); return Number.isFinite(date.getTime()) ? date : new Date() }\nconst weekdays = ['一', '二', '三', '四', '五', '六', '日']\nconst status: Record<string, string> = { queued: '排队中', running: '执行中', waiting: '等待处理', complete: '已完成', failed: '失败', interrupted: '已停止', uncertain: '状态待确认', skipped: '已跳过' }\nconst backPath = computed(() => typeof route.query.from === 'string' && /^\\/conversations(?:\\/[a-f0-9-]{36})?(?:\\?taskId=[a-f0-9-]{36})?$/i.test(route.query.from) ? route.query.from : '/conversations')\nconst sidebarBots = computed(() => agents.value.filter(a => a.name.toLowerCase().includes(botQuery.value.trim().toLowerCase())))\nconst visibleRoutines = computed(() => routines.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && `${r.name} ${r.prompt}`.toLowerCase().includes(query.value.trim().toLowerCase())).sort((a, b) => Number(b.enabled) - Number(a.enabled) || (a.nextAt ?? Infinity) - (b.nextAt ?? Infinity)))\nconst visibleRuns = computed(() => runs.value.filter(r => (botFilter.value === 'all' || r.agentId === botFilter.value) && (!routineFilter.value || r.routineId === routineFilter.value) && (stateFilter.value === 'all' || r.status === stateFilter.value) && `${routines.value.find(t => t.id === r.routineId)?.name ?? ''} ${r.error ?? ''}`.toLowerCase().includes(query.value.trim().toLowerCase())))\nconst running = computed(() => runs.value.filter(r => ['queued', 'running', 'waiting', 'uncertain'].includes(r.status)).length)\nconst days = computed(() => {\n const first = anchorDate()\n first.setDate(first.getDate() - (first.getDay() + 6) % 7)\n return weekdays.map((weekday, offset) => { const date = new Date(first); date.setDate(date.getDate() + offset); return { date, key: dateKey(date), weekday } })\n})\nconst rangeLabel = computed(() => `${days.value[0]!.date.toLocaleDateString('zh-CN')} — ${days.value[6]!.date.toLocaleDateString('zh-CN')}`)\nconst scheduled = (key: string) => visibleRoutines.value.filter(r => r.enabled && r.nextAt && dateKey(new Date(r.nextAt)) === key)\nconst agent = (id: string) => agents.value.find(a => a.id === id)\nconst date = (at?: number) => at ? new Date(at).toLocaleString('zh-CN', { hour12: false }) : '—'\nconst time = (at?: number) => at ? new Date(at).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit' }) : ''\nconst schedule = (r: WorkspaceRoutine) => r.schedule.kind === 'interval' ? `每 ${r.schedule.everyMinutes} 分钟` : r.schedule.kind === 'once' ? '仅一次' : `${r.schedule.kind === 'weekly' ? '每周 ' + (r.schedule.weekdays ?? []).map(i => '日一二三四五六'[i]).join('、') : '每天'} ${r.schedule.time}`\nfunction moveWeek(direction: number) { const date = anchorDate(); date.setDate(date.getDate() + direction * 7); anchor.value = dateKey(date) }\nfunction closeNewMenu(event: PointerEvent) { if (event.target instanceof Element && !event.target.closest('.new-automation')) newMenu.value = false }\nfunction showLogs(id = '') { section.value = 'logs'; routineFilter.value = id; query.value = ''; stateFilter.value = 'all' }\nasync function openEditor(botId: string, routine?: WorkspaceRoutine) {\n newMenu.value = false; editorAgent.value = botId\n await nextTick(); editor.value?.edit(routine)\n}\nfunction create() {\n const target = botFilter.value !== 'all' ? botFilter.value : agents.value.length === 1 ? agents.value[0]!.id : undefined\n if (target) void openEditor(target)\n else newMenu.value = !newMenu.value\n}\nlet generation = 0, closed = false, timer: ReturnType<typeof setTimeout> | undefined\nasync function load() {\n const current = ++generation\n try {\n const result = await apiRequest<{ agents: Bot[]; routines: WorkspaceRoutine[]; runs: WorkspaceRoutineRun[] }>('/api/app/bot-tools/automations')\n if (closed || current !== generation) return\n agents.value = result.agents; routines.value = result.routines; runs.value = result.runs; error.value = ''\n if (botFilter.value !== 'all' && !agents.value.some(a => a.id === botFilter.value)) botFilter.value = 'all'\n } catch (e) { if (!closed && current === generation) error.value = e instanceof Error ? e.message : '无法读取自动化任务' }\n finally { if (!closed && current === generation) loading.value = false }\n}\nasync function poll() { if (!document.hidden) await load(); if (!closed) timer = setTimeout(poll, 5000) }\nonMounted(poll)\nonBeforeUnmount(() => { closed = true; generation++; clearTimeout(timer) })\n</script>\n\n<template>\n <main class=\"automations-page\" aria-label=\"自动化工作区\" @pointerdown=\"closeNewMenu\" @keydown.esc=\"newMenu = false\">\n <header class=\"automations-header\">\n <button class=\"icon-button\" type=\"button\" aria-label=\"返回聊天\" @click=\"router.push(backPath)\"><AppIcon name=\"chevron-left\" :size=\"20\" /></button>\n <AppIcon name=\"calendar\" :size=\"23\" /><h1>自动化</h1>\n <div class=\"segmented\" role=\"tablist\" aria-label=\"自动化页面\"><button role=\"tab\" :aria-selected=\"section === 'schedule'\" @click=\"section = 'schedule'\">日程</button><button role=\"tab\" :aria-selected=\"section === 'logs'\" @click=\"showLogs()\">运行日志</button></div>\n <span v-if=\"running\" class=\"running-count\">{{ running }} 项执行中</span>\n <div class=\"new-automation\"><button class=\"primary\" type=\"button\" :disabled=\"!agents.length\" :aria-expanded=\"newMenu\" @click=\"create\"><AppIcon name=\"plus\" :size=\"17\" />新建自动化</button><div v-if=\"newMenu\" class=\"new-menu\" role=\"group\" aria-label=\"选择执行 Bot\" @keydown.esc.stop=\"newMenu = false\"><p>选择执行 Bot</p><button v-for=\"bot in agents\" :key=\"bot.id\" type=\"button\" @click=\"openEditor(bot.id)\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"24\" />{{ bot.name }}</button></div></div>\n </header>\n <div class=\"automations-body\">\n <aside class=\"automation-sidebar\" aria-label=\"自动化筛选\">\n <label class=\"date-filter\">查看日期<input v-model=\"anchor\" type=\"date\" /></label>\n <h2>我的 Bot <span>{{ agents.length }}</span></h2><input v-model=\"botQuery\" type=\"search\" aria-label=\"搜索 Bot\" placeholder=\"搜索 Bot\" />\n <nav aria-label=\"按 Bot 筛选\"><button :aria-current=\"botFilter === 'all' ? 'true' : undefined\" @click=\"botFilter = 'all'\"><AppIcon name=\"users\" :size=\"22\" />全部 Bot<span>{{ routines.length }}</span></button><button v-for=\"bot in sidebarBots\" :key=\"bot.id\" :aria-current=\"botFilter === bot.id ? 'true' : undefined\" @click=\"botFilter = bot.id\"><AgentAvatar :name=\"bot.name\" :avatar=\"bot.avatar\" :size=\"26\" /><strong>{{ bot.name }}</strong><span>{{ routines.filter(r => r.agentId === bot.id).length }}</span></button></nav>\n <p v-if=\"!agents.length\">创建 Bot 后,即可安排自动执行的任务。</p>\n </aside>\n <section class=\"automation-content\">\n <div class=\"automation-toolbar\">\n <div v-if=\"section === 'schedule'\" class=\"segmented\" role=\"tablist\" aria-label=\"日程视图\"><button role=\"tab\" :aria-selected=\"view === 'calendar'\" @click=\"view = 'calendar'\">日历</button><button role=\"tab\" :aria-selected=\"view === 'list'\" @click=\"view = 'list'\">任务列表</button></div>\n <template v-if=\"section === 'schedule' && view === 'calendar'\"><div class=\"date-actions\"><button aria-label=\"上一周\" @click=\"moveWeek(-1)\"><AppIcon name=\"chevron-left\" :size=\"16\" /></button><button @click=\"anchor = dateKey(new Date())\">今天</button><button aria-label=\"下一周\" @click=\"moveWeek(1)\"><AppIcon name=\"chevron-left\" class=\"next-icon\" :size=\"16\" /></button></div><span class=\"range-label\">{{ rangeLabel }}</span></template>\n <input v-model=\"query\" class=\"task-search\" type=\"search\" :aria-label=\"section === 'logs' ? '搜索运行日志' : '搜索自动化任务'\" placeholder=\"搜索任务\" />\n <select v-model=\"botFilter\" class=\"mobile-bot-filter\" aria-label=\"筛选执行 Bot\"><option value=\"all\">全部 Bot</option><option v-for=\"bot in agents\" :key=\"bot.id\" :value=\"bot.id\">{{ bot.name }}</option></select>\n <select v-if=\"section === 'logs'\" v-model=\"stateFilter\" aria-label=\"筛选执行状态\"><option value=\"all\">全部状态</option><option v-for=\"(label, key) in status\" :key=\"key\" :value=\"key\">{{ label }}</option></select>\n <button class=\"icon-button\" aria-label=\"刷新自动化\" @click=\"load\"><AppIcon name=\"refresh\" :size=\"17\" /></button>\n </div>\n <p v-if=\"error\" class=\"page-error\" role=\"alert\">{{ error }}</p><p v-if=\"loading\" class=\"loading\" role=\"status\">正在读取自动化任务…</p>\n <template v-else-if=\"section === 'schedule' && view === 'calendar'\">\n <p class=\"calendar-note\">显示每项任务的下次执行时间,按本地时区展示。</p>\n <div class=\"schedule-week\" aria-label=\"本周自动化日程\"><section v-for=\"day in days\" :key=\"day.key\" class=\"schedule-day\" :class=\"{ today: day.key === dateKey(new Date()) }\" :aria-label=\"day.key\"><header><span>周{{ day.weekday }}</span><h2>{{ day.date.getDate() }}</h2></header><button v-for=\"routine in scheduled(day.key)\" :key=\"routine.id\" class=\"schedule-event\" @click=\"openEditor(routine.agentId, routine)\"><time>{{ time(routine.nextAt) }}</time><strong>{{ routine.name }}</strong><span>{{ agent(routine.agentId)?.name }}</span></button><p v-if=\"!scheduled(day.key).length\" class=\"no-events\">暂无任务</p></section></div>\n </template>\n <div v-else-if=\"section === 'schedule'\" class=\"automation-list\">\n <p v-if=\"!visibleRoutines.length\" class=\"empty\">{{ query ? '没有匹配的任务。' : '还没有自动化任务。点击“新建自动化”安排工作。' }}</p>\n <article v-for=\"routine in visibleRoutines\" :key=\"routine.id\" class=\"automation-card\"><AgentAvatar :name=\"agent(routine.agentId)?.name ?? 'Bot'\" :avatar=\"agent(routine.agentId)?.avatar ?? ''\" :size=\"32\" /><button class=\"routine-description\" @click=\"openEditor(routine.agentId, routine)\"><h2>{{ routine.name }}</h2><p>{{ agent(routine.agentId)?.name }} · {{ schedule(routine) }} · {{ routine.schedule.timezone }}</p><small>{{ routine.enabled ? '下次执行:' + date(routine.nextAt) : '已暂停' }}</small></button><span class=\"status-pill\" :class=\"{ enabled: routine.enabled }\">{{ routine.enabled ? '已启用' : '已暂停' }}</span><button class=\"quiet\" @click=\"showLogs(routine.id)\">查看日志</button></article>\n </div>\n <div v-else class=\"automation-logs\">\n <p v-if=\"routineFilter\" class=\"log-scope\">当前任务:{{ routines.find(r => r.id === routineFilter)?.name ?? '自动化任务' }} <button @click=\"routineFilter = ''\">显示全部</button></p>\n <p v-if=\"!visibleRuns.length\" class=\"empty\">还没有符合条件的运行记录。</p>\n <details v-for=\"run in visibleRuns\" :key=\"run.id\" class=\"run-card\"><summary><div><strong>{{ routines.find(r => r.id === run.routineId)?.name ?? '自动化任务' }}</strong><p>{{ agent(run.agentId)?.name }} · {{ date(run.startedAt) }} · {{ run.scheduledAt === 0 ? '手动执行' : '定时执行' }}</p></div><span :class=\"{ failure: run.status === 'failed', success: run.status === 'complete' }\">{{ status[run.status] }}</span></summary><p v-if=\"run.error\" class=\"failure\">{{ run.error }}</p><p v-else>{{ run.status === 'complete' ? '结果已发送到 Bot 聊天。' : '执行进度会自动更新。' }}</p><RouterLink v-if=\"run.conversationId\" :to=\"'/conversations/' + run.conversationId\">查看聊天结果 ↗</RouterLink></details>\n </div>\n </section>\n </div>\n <WorkspaceRoutinesPanel v-if=\"editorAgent\" :key=\"editorAgent\" ref=\"editor\" :agent-id=\"editorAgent\" editor-only @changed=\"load\" @executed=\"showLogs\" />\n </main>\n</template>\n\n<style scoped>\n.automations-page{height:100dvh;display:flex;flex-direction:column;background:var(--canvas);color:var(--text-primary);min-width:0}.automations-header{display:flex;align-items:center;gap:12px;min-height:72px;box-sizing:border-box;padding:12px 24px;border-bottom:1px solid var(--line);background:var(--surface)}h1{font-size:20px;margin:0 20px 0 0;letter-spacing:-.02em}.automations-page button,.automations-page input,.automations-page select{font:inherit;font-size:13px;color:inherit;border:1px solid var(--line);border-radius:9px;background:var(--surface);padding:8px 11px;min-height:40px;box-sizing:border-box}.automations-page button{cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:7px}.automations-page button:hover{background:var(--surface-hover)}.automations-page button:disabled{opacity:.45;cursor:not-allowed}.automations-page :is(button,input,select,a,summary):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.automations-page .icon-button{padding:8px;width:40px;flex-shrink:0}.automations-page .primary{background:var(--accent);border-color:var(--accent);color:var(--text-on-solid);font-weight:600}.segmented{display:flex;gap:3px;border:1px solid var(--line);border-radius:10px;padding:3px;background:var(--surface)}.segmented button{min-height:32px;border:0;background:transparent;white-space:nowrap}.segmented button[aria-selected=true]{background:var(--surface-soft);font-weight:600}.new-automation{margin-left:auto;position:relative}.new-menu{position:absolute;right:0;top:calc(100% + 8px);z-index:10;width:250px;max-height:340px;overflow:auto;padding:8px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-float)}.new-menu p{font-size:12px;color:var(--text-muted);margin:5px 8px}.new-menu button{width:100%;justify-content:flex-start;border:0}.running-count{font-size:12px;color:var(--accent)}.automations-body{display:flex;flex:1;min-height:0}.automation-sidebar{width:224px;flex-shrink:0;box-sizing:border-box;padding:24px 16px;border-right:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;gap:12px;overflow:auto}.date-filter{display:grid;gap:8px;font-size:12px;color:var(--text-secondary);padding-bottom:20px;border-bottom:1px solid var(--line)}.automation-sidebar h2{display:flex;justify-content:space-between;font-size:13px;margin:8px 2px 0}.automation-sidebar h2 span{color:var(--text-muted);font-weight:400}.automation-sidebar input{width:100%;min-width:0}.automation-sidebar nav{display:grid;gap:4px}.automation-sidebar nav button{width:100%;justify-content:flex-start;border:0;text-align:left;min-width:0}.automation-sidebar nav button[aria-current]{background:var(--surface-soft)}.automation-sidebar nav strong{font-size:13px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.automation-sidebar nav span{margin-left:auto;font-size:12px;color:var(--text-muted)}.automation-sidebar>p{font-size:12px;color:var(--text-secondary);line-height:1.7}.automation-content{flex:1;min-width:0;overflow:auto;padding:20px 24px}.automation-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px}.date-actions{display:flex;gap:3px}.date-actions button{border:0;background:transparent}.next-icon{transform:rotate(180deg)}.range-label{font-size:13px;font-weight:550}.task-search{margin-left:auto;width:170px;min-width:100px}.mobile-bot-filter{display:none}.calendar-note{font-size:12px;color:var(--text-muted);margin:0 0 14px}.schedule-week{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));min-height:450px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--surface)}.schedule-day{min-width:0;border-right:1px solid var(--line);padding:10px 7px}.schedule-day:last-child{border-right:0}.schedule-day>header{display:grid;justify-items:center;gap:6px;padding:8px 0 16px}.schedule-day>header span{font-size:12px;color:var(--text-muted)}.schedule-day h2{font-size:22px;margin:0;font-weight:500}.schedule-day.today{background:color-mix(in srgb,var(--accent) 4%,var(--surface))}.schedule-day.today h2{color:var(--accent);font-weight:650}.automations-page .schedule-event{display:grid;justify-content:stretch;gap:7px;width:100%;text-align:left;align-items:start;margin-bottom:8px;padding:10px 9px;background:color-mix(in srgb,var(--accent) 7%,var(--surface));border-color:color-mix(in srgb,var(--accent) 25%,var(--line));overflow-wrap:anywhere}.schedule-event time{font-size:11px;color:var(--accent)}.schedule-event strong{font-size:12px;line-height:1.5}.schedule-event span{font-size:11px;color:var(--text-secondary)}.no-events{font-size:11px;color:var(--text-muted);text-align:center;padding:24px 0}.automation-list,.automation-logs{display:grid;gap:12px}.automation-card{display:flex;align-items:center;gap:14px;padding:18px;border:1px solid var(--line);border-radius:14px;background:var(--surface);min-width:0}.automations-page .routine-description{display:block;flex:1;min-width:0;padding:0;text-align:left;background:transparent;border:0}.routine-description h2{margin:0 0 7px;font-size:15px;font-weight:600}.routine-description p{margin:0 0 6px;font-size:12px;color:var(--text-secondary);line-height:1.6}.routine-description small{font-size:12px;color:var(--text-muted)}.status-pill{font-size:11px;color:var(--text-muted);white-space:nowrap;padding:5px 8px;border-radius:99px;background:var(--surface-soft)}.status-pill.enabled{color:var(--accent)}.automations-page .quiet{border:0;background:transparent;white-space:nowrap}.run-card{padding:18px;border:1px solid var(--line);border-radius:12px;background:var(--surface);font-size:13px;line-height:1.7}.run-card summary{display:flex;justify-content:space-between;gap:16px;cursor:pointer;list-style:none;min-height:44px}.run-card summary::-webkit-details-marker{display:none}.run-card p{font-size:12px;color:var(--text-secondary);margin:5px 0}.run-card a{color:var(--accent)}.run-card summary>span{white-space:nowrap}.failure,.page-error{color:var(--danger)!important}.success{color:var(--accent)}.page-error{padding:12px;border-radius:9px;background:var(--surface);font-size:13px}.empty,.loading{padding:50px 20px;text-align:center;color:var(--text-secondary);font-size:13px;line-height:1.8}.log-scope{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary)}@media(max-width:1000px){.automations-header{padding:12px 16px;flex-wrap:wrap;gap:8px}h1{margin-right:8px}.automation-sidebar{width:190px}.automation-content{padding:18px 16px}.range-label{order:3;width:100%}.schedule-week{grid-template-columns:repeat(7,minmax(0,1fr))}.schedule-day{padding:8px 4px}}@media(max-width:760px){.automation-sidebar{display:none}.mobile-bot-filter{display:block;max-width:160px}.automations-page button{min-height:44px}.automations-header{padding:10px 12px}.automations-header .segmented{order:3}.running-count{display:none}.automations-body{display:block;overflow:hidden}.automation-content{height:100%;box-sizing:border-box;padding:16px 12px}.schedule-week{grid-template-columns:1fr;min-height:0;border:0;border-radius:0;background:transparent;gap:10px}.schedule-day{display:grid;grid-template-columns:56px minmax(0,1fr);align-items:start;padding:12px;border:1px solid var(--line)!important;border-radius:12px;background:var(--surface)}.schedule-day>header{grid-row:1 / span 50;padding:2px 8px 0 0}.schedule-event{grid-column:2}.no-events{text-align:left;padding:10px;margin:0}.task-search{flex:1;width:130px}.range-label{font-size:12px}.automation-card{flex-wrap:wrap;padding:14px;gap:10px}.automation-card>.routine-description{flex-basis:calc(100% - 48px)}.automation-card>.status-pill{margin-left:42px}.automation-card>.quiet{margin-left:auto}.automation-toolbar{gap:8px}}\n</style>\n"],"mappings":"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"}
|
package/dist/assets/{BotControlSettingsPanel-CtXD24FZ.js → BotControlSettingsPanel-DJ71O3Kh.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{A as e,F as t,G as n,H as r,L as i,M as a,Ot as o,_ as s,a as c,b as l,d as u,et as d,f,m as p,p as m,t as h,u as g,v as _}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{i as v}from"./WorkspaceKnowledgePanel-D34YxglF.js";import{D as y,nt as b}from"./index-DjhQ-RMG.js";import{S as x,g as S,h as C,m as w}from"./ConversationsView-DsuaLKva.js";var T=[`aria-label`],E=[`disabled`],D={"aria-label":`Bot 配置页面`},O=[`aria-pressed`,`disabled`,`onClick`],k={key:0,role:`alert`},A={key:3,class:`bot-records`,"aria-label":`运行记录`},j=[`disabled`],M={key:0,role:`status`},N={key:1},P={key:0},F=h(l({__name:`ManagedBotProfilePanel`,props:{agent:{},agents:{},permissionsEnforced:{type:Boolean}},emits:[`close`,`changed`,`navigate`,`dirty-change`,`busy-change`],setup(n,{expose:s,emit:l}){let h=n,_=l,b=d(h.agent),x=d([]),w=d(!1),F=d(!1),I=d(!1),L=d(!1),R=d(``),z=d(`profile`),B=d(),V=d(!1),H=d(),U=g(()=>({...b.value,canManageTeam:b.value.canManageTeam??!0,canCollaborate:b.value.canCollaborate??!0,memoryEnabled:b.value.memoryEnabled??!0})),W=g(()=>x.value.find(e=>e.kind===`direct`&&e.memberIds[0]===b.value.id)?.id),G=g(()=>[...B.value?.activities??[],...B.value?.reviews??[]].sort((e,t)=>(t.at??0)-(e.at??0))),K=e=>/[\u3400-\u9fff]/.test(e)?e:{completed:`已完成`,stopped:`已停止`,stopping:`正在停止`,approved:`已允许`,denied:`已拒绝`,expired:`已过期`,uncertain:`需要核对`,sending:`投递中`,sent:`已投递`}[e]??v(e),q=!0;r(L,e=>_(`dirty-change`,e)),r(()=>F.value||I.value,e=>_(`busy-change`,e));function J(){return!F.value&&!I.value&&(!L.value||window.confirm(`放弃此 Bot 未保存的配置?`))}function ee(e){e===z.value||!J()||(L.value=!1,z.value=e,R.value=``,e===`records`&&Y())}async function Y(){V.value=!0,R.value=``;try{let e=await y(`/api/app/agents/${encodeURIComponent(b.value.id)}/home`);q&&(B.value=e)}catch(e){q&&(R.value=e instanceof Error?e.message:`读取运行记录失败`)}finally{q&&(V.value=!1)}}async function X(e){if(F.value)return;F.value=!0,R.value=``;let t={name:e.name,avatar:e.avatar,instructions:e.instructions,description:e.description?.trim()??``,job:e.job?.trim()||null,antiJobs:e.antiJobs?.length?e.antiJobs:null,voice:e.voice||null,voiceCustom:e.voice===`custom`&&e.voiceCustom?.trim()||null,actBias:e.actBias||null,memoryEnabled:e.memoryEnabled,canCollaborate:e.canCollaborate,canManageTeam:e.canManageTeam,approvalPolicy:e.approvalPolicy??`ask`,expectedRevision:e.expectedRevision??b.value.revision,...e.modelSettings?{modelSettings:e.modelSettings}:{}};try{let e=await y(`/api/app/agents/${encodeURIComponent(b.value.id)}`,{method:`PATCH`,body:JSON.parse(JSON.stringify(t))});if(!q)return;if(e.confirmationRequired){if(!e.confirmationTarget)throw Error(`模型确认信息不完整,请重新读取。`);if(!window.confirm(e.confirmationMessage||`确认使用此模型?`))return;e=await y(`/api/app/agents/${encodeURIComponent(b.value.id)}`,{method:`PATCH`,body:JSON.parse(JSON.stringify({...t,confirmedModel:e.confirmationTarget}))})}if(!q)return;if(!e.agent)throw Error(`保存尚未确认,请重新读取后核对。`);b.value=e.agent,H.value?.markSaved?.(e.agent),L.value=!1,_(`changed`)}catch(e){q&&(R.value=e instanceof Error?e.message:`保存失败`)}finally{q&&(F.value=!1)}}return a(async()=>{try{let[e,t]=await Promise.all([y(`/api/app/conversations`),y(`/api/app/capabilities`)]);q&&(x.value=e.conversations,w.value=t.features.includes(`bot-file-memory-v1`))}catch(e){q&&(R.value=e instanceof Error?e.message:`加载 Bot 配置失败`)}}),e(()=>{q=!1}),s({beforeClose:J}),(e,r)=>(t(),p(`section`,{class:`managed-bot`,"aria-label":`${b.value.name} 的设置`},[u(`header`,null,[u(`button`,{disabled:F.value||I.value,onClick:r[0]||=e=>J()&&_(`close`)},`返回我的 Bot`,8,E),u(`strong`,null,o(b.value.name),1),r[9]||=u(`small`,null,`只修改此 Bot`,-1)]),u(`nav`,D,[(t(),p(c,null,i([[`profile`,`资料与权限`],[`skills`,`技能`],[`execution`,`执行设置`],[`records`,`运行记录`]],e=>u(`button`,{key:e[0],"aria-pressed":z.value===e[0],disabled:F.value||I.value,onClick:t=>ee(e[0])},o(e[1]),9,O)),64))]),R.value&&z.value!==`profile`?(t(),p(`p`,k,o(R.value),1)):m(``,!0),z.value===`profile`?(t(),f(S,{key:1,ref_key:`profile`,ref:H,embedded:``,"permission-control":``,"is-admin":``,agent:b.value,draft:U.value,agents:n.agents,conversations:x.value,"conversation-id":W.value,"knowledge-enabled":w.value,busy:F.value,error:R.value,onSave:X,onClose:r[1]||=e=>_(`close`),onChanged:r[2]||=e=>_(`changed`),onDirtyChange:r[3]||=e=>L.value=e,onBusyChange:r[4]||=e=>I.value=e,onManageModels:r[5]||=e=>_(`navigate`,`system-models`),onManagePermissions:r[6]||=e=>_(`navigate`,`workspace-permissions`)},null,8,[`agent`,`draft`,`agents`,`conversations`,`conversation-id`,`knowledge-enabled`,`busy`,`error`])):z.value===`skills`||z.value===`execution`?(t(),f(C,{key:z.value,section:z.value,"target-bot-id":b.value.id,"permission-control":n.permissionsEnforced,onDirtyChange:r[7]||=e=>L.value=e,onBusyChange:r[8]||=e=>I.value=e},null,8,[`section`,`target-bot-id`,`permission-control`])):(t(),p(`section`,A,[u(`button`,{disabled:V.value,onClick:Y},`刷新运行记录`,8,j),V.value?(t(),p(`p`,M,`正在读取…`)):G.value.length?m(``,!0):(t(),p(`p`,N,`暂无运行记录。`)),(t(!0),p(c,null,i(G.value,e=>(t(),p(`details`,{key:e.id},[u(`summary`,null,o(e.title)+` · `+o(K(e.status)),1),e.at?(t(),p(`small`,P,o(new Date(e.at).toLocaleString(`zh-CN`)),1)):m(``,!0),u(`p`,null,o(e.content||e.summary||`没有附加内容。`),1)]))),128))]))],8,T))}}),[[`__scopeId`,`data-v-e6af65fd`]]),I={class:`control-settings`},L={key:0,role:`alert`,class:`error`},R={class:`card`},z=[`value`],B=[`disabled`],V={class:`card`},H=[`onClick`],U={class:`card`},W={key:0},G={key:0},K={class:`actions`},q=[`disabled`,`onClick`],J=[`disabled`,`onClick`],ee=[`disabled`,`onClick`],Y={class:`card`},X=h(l({__name:`BotControlSettingsPanel`,props:{page:{},targetBotId:{}},emits:[`changed`,`navigate`,`dirty-change`,`busy-change`],setup(l,{emit:h}){let v=l,S=h,C=d(),T=d([]),E=d(``),D=d(!1),O=d(v.targetBotId??``),k=d(``),A=d(``),j=g(()=>T.value.find(e=>e.id===O.value)),M=g(()=>C.value?.requests.filter(e=>e.status===`pending`)??[]),N=!0,P=0,X;async function Z(){let e=++P;try{let[t,n]=await Promise.all([y(`/api/app/permissions/control`),y(`/api/app/agents`)]);N&&e===P&&(C.value=t,A.value=t.mainBotId??``,T.value=n.agents,E.value=``)}catch(t){N&&e===P&&(E.value=t instanceof Error?t.message:`读取失败`)}}let Q=e=>T.value.find(t=>t.id===e)?.name??e??`待确定`;function te(e){if(e.capability!==`tasks.delegate`)return Q(e.agentId);let t=e.resources.filter(e=>e.startsWith(`peer:`)).map(e=>e.slice(5)).filter(Boolean);return t.length?t.map(Q).join(`、`):`待确定`}async function $(e,t){if(!D.value){D.value=!0;try{await y(`/api/app/approvals/${e.id}/respond`,{method:`POST`,body:{decision:t,expectedRevision:e.revision}}),await Z(),S(`changed`)}catch(e){E.value=e instanceof Error?e.message:`处理失败`}finally{D.value=!1}}}return r(()=>v.targetBotId,e=>{e&&(O.value=e)}),a(()=>{Z(),X=setInterval(()=>{D.value||Z()},5e3)}),e(()=>{N=!1,P++,clearInterval(X)}),(e,r)=>(t(),p(`section`,I,[E.value?(t(),p(`p`,L,[s(o(E.value),1),u(`button`,{type:`button`,onClick:Z},`重新加载`)])):m(``,!0),k.value?(t(),f(w,{key:1,"target-bot-id":k.value,onClose:r[0]||=e=>k.value=``,onChanged:r[1]||=e=>{Z(),S(`changed`)}},null,8,[`target-bot-id`])):m(``,!0),l.page===`permissions`?(t(),f(x,{key:2,onChanged:r[2]||=e=>S(`changed`),onDirtyChange:r[3]||=e=>S(`dirty-change`,e),onBusyChange:r[4]||=e=>S(`busy-change`,e)})):l.page===`bots`?(t(),p(c,{key:3},[j.value?(t(),p(c,{key:0},[_(F,{agent:j.value,agents:T.value,"permissions-enforced":!0,onClose:r[5]||=e=>O.value=``,onChanged:r[6]||=e=>{Z(),S(`changed`)},onNavigate:r[7]||=e=>S(`navigate`,e),onDirtyChange:r[8]||=e=>S(`dirty-change`,e),onBusyChange:r[9]||=e=>S(`busy-change`,e)},null,8,[`agent`,`agents`]),_(x,{kind:`agents`,"target-id":j.value.id,onChanged:r[10]||=e=>S(`changed`),onDirtyChange:r[11]||=e=>S(`dirty-change`,e),onBusyChange:r[12]||=e=>S(`busy-change`,e)},null,8,[`target-id`])],64)):(t(),p(c,{key:1},[u(`section`,R,[r[17]||=u(`h3`,null,`主 Bot`,-1),r[18]||=u(`p`,null,`默认对话与工作安排的入口。切换身份不会改变任何 Bot 的权限。`,-1),u(`label`,null,[r[16]||=s(`选择主 Bot`,-1),n(u(`select`,{"onUpdate:modelValue":r[13]||=e=>A.value=e},[r[15]||=u(`option`,{value:``,disabled:``},`请选择`,-1),(t(!0),p(c,null,i(T.value.filter(e=>!e.archived&&!e.temporaryGoalId&&!e.remoteAgentId&&e.nodeId===`local`),e=>(t(),p(`option`,{key:e.id,value:e.id},o(e.name),9,z))),128))],512),[[b,A.value]])]),u(`button`,{type:`button`,disabled:!A.value||A.value===C.value?.mainBotId,onClick:r[14]||=e=>k.value=A.value},`确认切换`,8,B)]),u(`section`,V,[r[19]||=u(`h3`,null,`我的 Bot`,-1),r[20]||=u(`p`,null,`默认使用服务器授权方式,也可为每个 Bot 独立选择授权方式和额外限制。`,-1),(t(!0),p(c,null,i(T.value.filter(e=>!e.archived&&!e.temporaryGoalId),e=>(t(),p(`article`,{key:e.id},[u(`strong`,null,o(e.name)+o(e.id===C.value?.mainBotId?` · 主 Bot`:``),1),u(`button`,{type:`button`,onClick:t=>O.value=e.id},`配置 Bot 与权限`,8,H)]))),128))])],64))],64)):l.page===`requests`?(t(),p(c,{key:4},[u(`section`,U,[u(`h3`,null,`待确认操作 · `+o(M.value.length),1),M.value.length?m(``,!0):(t(),p(`p`,W,`暂无需要确认的操作。`)),(t(!0),p(c,null,i(M.value,e=>(t(),p(`article`,{key:e.id,class:`request`},[u(`strong`,null,o(T.value.find(t=>t.id===e.agentId)?.name??`Bot`),1),u(`small`,null,`发起者:`+o(Q(e.initiatorId??e.agentId)),1),u(`small`,null,`实际执行者:`+o(te(e)),1),u(`p`,null,o(e.message??e.reason),1),u(`small`,null,o(e.toolId)+` · `+o(e.resources.join(`、`)),1),e.originConversationId===e.displayConversationId?m(``,!0):(t(),p(`small`,G,`来自群任务,在执行 Bot 单聊中也可以处理。`)),u(`div`,K,[u(`button`,{type:`button`,disabled:D.value,onClick:t=>$(e,`deny`)},`拒绝`,8,q),u(`button`,{type:`button`,disabled:D.value,onClick:t=>$(e,`once`)},`允许一次`,8,J),e.manualOnly?m(``,!0):(t(),p(`button`,{key:0,type:`button`,disabled:D.value,onClick:t=>$(e,`always`)},`始终允许此类操作`,8,ee))])]))),128))]),u(`section`,Y,[r[21]||=u(`h3`,null,`操作确认记录`,-1),(t(!0),p(c,null,i(C.value?.requests.filter(e=>e.status!==`pending`)??[],e=>(t(),p(`article`,{key:e.id,class:`request`},[u(`strong`,null,o({approved:`已允许`,denied:`已拒绝`,expired:`已失效`,pending:`待确认`}[e.status]),1),u(`small`,null,`发起者:`+o(Q(e.initiatorId??e.agentId)),1),u(`small`,null,`实际执行者:`+o(te(e)),1),u(`p`,null,o(e.reason),1),u(`small`,null,o(e.toolId)+` · `+o(e.resources.join(`、`)),1)]))),128))])],64)):m(``,!0)]))}}),[[`__scopeId`,`data-v-35ace50f`]]);export{X as default};
|
|
2
|
-
//# sourceMappingURL=BotControlSettingsPanel-
|
|
1
|
+
import{A as e,F as t,G as n,H as r,L as i,M as a,Ot as o,_ as s,a as c,b as l,d as u,et as d,f,m as p,p as m,t as h,u as g,v as _}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{a as v}from"./WorkspaceKnowledgePanel-E549Ct1E.js";import{at as y,j as b}from"./index-P_kZCZ2-.js";import{S as x,g as S,h as C,m as w}from"./ConversationsView-kztie5lF.js";var T=[`aria-label`],E=[`disabled`],D={"aria-label":`Bot 配置页面`},O=[`aria-pressed`,`disabled`,`onClick`],k={key:0,role:`alert`},A={key:3,class:`bot-records`,"aria-label":`运行记录`},j=[`disabled`],M={key:0,role:`status`},N={key:1},P={key:0},F=h(l({__name:`ManagedBotProfilePanel`,props:{agent:{},agents:{},permissionsEnforced:{type:Boolean}},emits:[`close`,`changed`,`navigate`,`dirty-change`,`busy-change`],setup(n,{expose:s,emit:l}){let h=n,_=l,y=d(h.agent),x=d([]),w=d(!1),F=d(!1),I=d(!1),L=d(!1),R=d(``),z=d(`profile`),B=d(),V=d(!1),H=d(),U=g(()=>({...y.value,canManageTeam:y.value.canManageTeam??!0,canCollaborate:y.value.canCollaborate??!0,memoryEnabled:y.value.memoryEnabled??!0})),W=g(()=>x.value.find(e=>e.kind===`direct`&&e.memberIds[0]===y.value.id)?.id),G=g(()=>[...B.value?.activities??[],...B.value?.reviews??[]].sort((e,t)=>(t.at??0)-(e.at??0))),K=e=>/[\u3400-\u9fff]/.test(e)?e:{completed:`已完成`,stopped:`已停止`,stopping:`正在停止`,approved:`已允许`,denied:`已拒绝`,expired:`已过期`,uncertain:`需要核对`,sending:`投递中`,sent:`已投递`}[e]??v(e),q=!0;r(L,e=>_(`dirty-change`,e)),r(()=>F.value||I.value,e=>_(`busy-change`,e));function J(){return!F.value&&!I.value&&(!L.value||window.confirm(`放弃此 Bot 未保存的配置?`))}function ee(e){e===z.value||!J()||(L.value=!1,z.value=e,R.value=``,e===`records`&&Y())}async function Y(){V.value=!0,R.value=``;try{let e=await b(`/api/app/agents/${encodeURIComponent(y.value.id)}/home`);q&&(B.value=e)}catch(e){q&&(R.value=e instanceof Error?e.message:`读取运行记录失败`)}finally{q&&(V.value=!1)}}async function X(e){if(F.value)return;F.value=!0,R.value=``;let t={name:e.name,avatar:e.avatar,instructions:e.instructions,description:e.description?.trim()??``,job:e.job?.trim()||null,antiJobs:e.antiJobs?.length?e.antiJobs:null,voice:e.voice||null,voiceCustom:e.voice===`custom`&&e.voiceCustom?.trim()||null,actBias:e.actBias||null,memoryEnabled:e.memoryEnabled,canCollaborate:e.canCollaborate,canManageTeam:e.canManageTeam,approvalPolicy:e.approvalPolicy??`ask`,expectedRevision:e.expectedRevision??y.value.revision,...e.modelSettings?{modelSettings:e.modelSettings}:{}};try{let e=await b(`/api/app/agents/${encodeURIComponent(y.value.id)}`,{method:`PATCH`,body:JSON.parse(JSON.stringify(t))});if(!q)return;if(e.confirmationRequired){if(!e.confirmationTarget)throw Error(`模型确认信息不完整,请重新读取。`);if(!window.confirm(e.confirmationMessage||`确认使用此模型?`))return;e=await b(`/api/app/agents/${encodeURIComponent(y.value.id)}`,{method:`PATCH`,body:JSON.parse(JSON.stringify({...t,confirmedModel:e.confirmationTarget}))})}if(!q)return;if(!e.agent)throw Error(`保存尚未确认,请重新读取后核对。`);y.value=e.agent,H.value?.markSaved?.(e.agent),L.value=!1,_(`changed`)}catch(e){q&&(R.value=e instanceof Error?e.message:`保存失败`)}finally{q&&(F.value=!1)}}return a(async()=>{try{let[e,t]=await Promise.all([b(`/api/app/conversations`),b(`/api/app/capabilities`)]);q&&(x.value=e.conversations,w.value=t.features.includes(`bot-file-memory-v1`))}catch(e){q&&(R.value=e instanceof Error?e.message:`加载 Bot 配置失败`)}}),e(()=>{q=!1}),s({beforeClose:J}),(e,r)=>(t(),p(`section`,{class:`managed-bot`,"aria-label":`${y.value.name} 的设置`},[u(`header`,null,[u(`button`,{disabled:F.value||I.value,onClick:r[0]||=e=>J()&&_(`close`)},`返回我的 Bot`,8,E),u(`strong`,null,o(y.value.name),1),r[9]||=u(`small`,null,`只修改此 Bot`,-1)]),u(`nav`,D,[(t(),p(c,null,i([[`profile`,`资料与权限`],[`skills`,`技能`],[`execution`,`执行设置`],[`records`,`运行记录`]],e=>u(`button`,{key:e[0],"aria-pressed":z.value===e[0],disabled:F.value||I.value,onClick:t=>ee(e[0])},o(e[1]),9,O)),64))]),R.value&&z.value!==`profile`?(t(),p(`p`,k,o(R.value),1)):m(``,!0),z.value===`profile`?(t(),f(S,{key:1,ref_key:`profile`,ref:H,embedded:``,"permission-control":``,"is-admin":``,agent:y.value,draft:U.value,agents:n.agents,conversations:x.value,"conversation-id":W.value,"knowledge-enabled":w.value,busy:F.value,error:R.value,onSave:X,onClose:r[1]||=e=>_(`close`),onChanged:r[2]||=e=>_(`changed`),onDirtyChange:r[3]||=e=>L.value=e,onBusyChange:r[4]||=e=>I.value=e,onManageModels:r[5]||=e=>_(`navigate`,`system-models`),onManagePermissions:r[6]||=e=>_(`navigate`,`workspace-permissions`)},null,8,[`agent`,`draft`,`agents`,`conversations`,`conversation-id`,`knowledge-enabled`,`busy`,`error`])):z.value===`skills`||z.value===`execution`?(t(),f(C,{key:z.value,section:z.value,"target-bot-id":y.value.id,"permission-control":n.permissionsEnforced,onDirtyChange:r[7]||=e=>L.value=e,onBusyChange:r[8]||=e=>I.value=e},null,8,[`section`,`target-bot-id`,`permission-control`])):(t(),p(`section`,A,[u(`button`,{disabled:V.value,onClick:Y},`刷新运行记录`,8,j),V.value?(t(),p(`p`,M,`正在读取…`)):G.value.length?m(``,!0):(t(),p(`p`,N,`暂无运行记录。`)),(t(!0),p(c,null,i(G.value,e=>(t(),p(`details`,{key:e.id},[u(`summary`,null,o(e.title)+` · `+o(K(e.status)),1),e.at?(t(),p(`small`,P,o(new Date(e.at).toLocaleString(`zh-CN`)),1)):m(``,!0),u(`p`,null,o(e.content||e.summary||`没有附加内容。`),1)]))),128))]))],8,T))}}),[[`__scopeId`,`data-v-e6af65fd`]]),I={class:`control-settings`},L={key:0,role:`alert`,class:`error`},R={class:`card`},z=[`value`],B=[`disabled`],V={class:`card`},H=[`onClick`],U={class:`card`},W={key:0},G={key:0},K={class:`actions`},q=[`disabled`,`onClick`],J=[`disabled`,`onClick`],ee=[`disabled`,`onClick`],Y={class:`card`},X=h(l({__name:`BotControlSettingsPanel`,props:{page:{},targetBotId:{}},emits:[`changed`,`navigate`,`dirty-change`,`busy-change`],setup(l,{emit:h}){let v=l,S=h,C=d(),T=d([]),E=d(``),D=d(!1),O=d(v.targetBotId??``),k=d(``),A=d(``),j=g(()=>T.value.find(e=>e.id===O.value)),M=g(()=>C.value?.requests.filter(e=>e.status===`pending`)??[]),N=!0,P=0,X;async function Z(){let e=++P;try{let[t,n]=await Promise.all([b(`/api/app/permissions/control`),b(`/api/app/agents`)]);N&&e===P&&(C.value=t,A.value=t.mainBotId??``,T.value=n.agents,E.value=``)}catch(t){N&&e===P&&(E.value=t instanceof Error?t.message:`读取失败`)}}let Q=e=>T.value.find(t=>t.id===e)?.name??e??`待确定`;function te(e){if(e.capability!==`tasks.delegate`)return Q(e.agentId);let t=e.resources.filter(e=>e.startsWith(`peer:`)).map(e=>e.slice(5)).filter(Boolean);return t.length?t.map(Q).join(`、`):`待确定`}async function $(e,t){if(!D.value){D.value=!0;try{await b(`/api/app/approvals/${e.id}/respond`,{method:`POST`,body:{decision:t,expectedRevision:e.revision}}),await Z(),S(`changed`)}catch(e){E.value=e instanceof Error?e.message:`处理失败`}finally{D.value=!1}}}return r(()=>v.targetBotId,e=>{e&&(O.value=e)}),a(()=>{Z(),X=setInterval(()=>{D.value||Z()},5e3)}),e(()=>{N=!1,P++,clearInterval(X)}),(e,r)=>(t(),p(`section`,I,[E.value?(t(),p(`p`,L,[s(o(E.value),1),u(`button`,{type:`button`,onClick:Z},`重新加载`)])):m(``,!0),k.value?(t(),f(w,{key:1,"target-bot-id":k.value,onClose:r[0]||=e=>k.value=``,onChanged:r[1]||=e=>{Z(),S(`changed`)}},null,8,[`target-bot-id`])):m(``,!0),l.page===`permissions`?(t(),f(x,{key:2,onChanged:r[2]||=e=>S(`changed`),onDirtyChange:r[3]||=e=>S(`dirty-change`,e),onBusyChange:r[4]||=e=>S(`busy-change`,e)})):l.page===`bots`?(t(),p(c,{key:3},[j.value?(t(),p(c,{key:0},[_(F,{agent:j.value,agents:T.value,"permissions-enforced":!0,onClose:r[5]||=e=>O.value=``,onChanged:r[6]||=e=>{Z(),S(`changed`)},onNavigate:r[7]||=e=>S(`navigate`,e),onDirtyChange:r[8]||=e=>S(`dirty-change`,e),onBusyChange:r[9]||=e=>S(`busy-change`,e)},null,8,[`agent`,`agents`]),_(x,{kind:`agents`,"target-id":j.value.id,onChanged:r[10]||=e=>S(`changed`),onDirtyChange:r[11]||=e=>S(`dirty-change`,e),onBusyChange:r[12]||=e=>S(`busy-change`,e)},null,8,[`target-id`])],64)):(t(),p(c,{key:1},[u(`section`,R,[r[17]||=u(`h3`,null,`主 Bot`,-1),r[18]||=u(`p`,null,`默认对话与工作安排的入口。切换身份不会改变任何 Bot 的权限。`,-1),u(`label`,null,[r[16]||=s(`选择主 Bot`,-1),n(u(`select`,{"onUpdate:modelValue":r[13]||=e=>A.value=e},[r[15]||=u(`option`,{value:``,disabled:``},`请选择`,-1),(t(!0),p(c,null,i(T.value.filter(e=>!e.archived&&!e.temporaryGoalId&&!e.remoteAgentId&&e.nodeId===`local`),e=>(t(),p(`option`,{key:e.id,value:e.id},o(e.name),9,z))),128))],512),[[y,A.value]])]),u(`button`,{type:`button`,disabled:!A.value||A.value===C.value?.mainBotId,onClick:r[14]||=e=>k.value=A.value},`确认切换`,8,B)]),u(`section`,V,[r[19]||=u(`h3`,null,`我的 Bot`,-1),r[20]||=u(`p`,null,`默认使用服务器授权方式,也可为每个 Bot 独立选择授权方式和额外限制。`,-1),(t(!0),p(c,null,i(T.value.filter(e=>!e.archived&&!e.temporaryGoalId),e=>(t(),p(`article`,{key:e.id},[u(`strong`,null,o(e.name)+o(e.id===C.value?.mainBotId?` · 主 Bot`:``),1),u(`button`,{type:`button`,onClick:t=>O.value=e.id},`配置 Bot 与权限`,8,H)]))),128))])],64))],64)):l.page===`requests`?(t(),p(c,{key:4},[u(`section`,U,[u(`h3`,null,`待确认操作 · `+o(M.value.length),1),M.value.length?m(``,!0):(t(),p(`p`,W,`暂无需要确认的操作。`)),(t(!0),p(c,null,i(M.value,e=>(t(),p(`article`,{key:e.id,class:`request`},[u(`strong`,null,o(T.value.find(t=>t.id===e.agentId)?.name??`Bot`),1),u(`small`,null,`发起者:`+o(Q(e.initiatorId??e.agentId)),1),u(`small`,null,`实际执行者:`+o(te(e)),1),u(`p`,null,o(e.message??e.reason),1),u(`small`,null,o(e.toolId)+` · `+o(e.resources.join(`、`)),1),e.originConversationId===e.displayConversationId?m(``,!0):(t(),p(`small`,G,`来自群任务,在执行 Bot 单聊中也可以处理。`)),u(`div`,K,[u(`button`,{type:`button`,disabled:D.value,onClick:t=>$(e,`deny`)},`拒绝`,8,q),u(`button`,{type:`button`,disabled:D.value,onClick:t=>$(e,`once`)},`允许一次`,8,J),e.manualOnly?m(``,!0):(t(),p(`button`,{key:0,type:`button`,disabled:D.value,onClick:t=>$(e,`always`)},`始终允许此类操作`,8,ee))])]))),128))]),u(`section`,Y,[r[21]||=u(`h3`,null,`操作确认记录`,-1),(t(!0),p(c,null,i(C.value?.requests.filter(e=>e.status!==`pending`)??[],e=>(t(),p(`article`,{key:e.id,class:`request`},[u(`strong`,null,o({approved:`已允许`,denied:`已拒绝`,expired:`已失效`,pending:`待确认`}[e.status]),1),u(`small`,null,`发起者:`+o(Q(e.initiatorId??e.agentId)),1),u(`small`,null,`实际执行者:`+o(te(e)),1),u(`p`,null,o(e.reason),1),u(`small`,null,o(e.toolId)+` · `+o(e.resources.join(`、`)),1)]))),128))])],64)):m(``,!0)]))}}),[[`__scopeId`,`data-v-35ace50f`]]);export{X as default};
|
|
2
|
+
//# sourceMappingURL=BotControlSettingsPanel-DJ71O3Kh.js.map
|