@lsamien/yaovi 0.1.3 → 0.1.4
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 +15 -4
- package/desktop/main.mjs +1 -1
- package/dist/assets/{AboutDialog-CnNkIRo8.js → AboutDialog-CDpS-zAu.js} +2 -2
- package/dist/assets/{AboutDialog-CnNkIRo8.js.map → AboutDialog-CDpS-zAu.js.map} +1 -1
- package/dist/assets/{BotAutomationsView-J9Y7Unoq.js → BotAutomationsView-RXBQzdfc.js} +2 -2
- package/dist/assets/{BotAutomationsView-J9Y7Unoq.js.map → BotAutomationsView-RXBQzdfc.js.map} +1 -1
- package/dist/assets/{BotControlSettingsPanel-CtXD24FZ.js → BotControlSettingsPanel-GQEVHXbw.js} +2 -2
- package/dist/assets/{BotControlSettingsPanel-CtXD24FZ.js.map → BotControlSettingsPanel-GQEVHXbw.js.map} +1 -1
- package/dist/assets/BotPluginsDialog-HIhXqyGn.js +2 -0
- package/dist/assets/{BotPluginsDialog-qRw8dCbX.js.map → BotPluginsDialog-HIhXqyGn.js.map} +1 -1
- package/dist/assets/{BotSettingsPanel-DbCMOfAW.js → BotSettingsPanel-Bkqal3lR.js} +3 -3
- package/dist/assets/{BotSettingsPanel-DbCMOfAW.js.map → BotSettingsPanel-Bkqal3lR.js.map} +1 -1
- package/dist/assets/{ComputerPanel-CI-jDmC3.js → ComputerPanel-Dt73pgTG.js} +2 -2
- package/dist/assets/{ComputerPanel-CI-jDmC3.js.map → ComputerPanel-Dt73pgTG.js.map} +1 -1
- package/dist/assets/{ComputerViewerView-B76D6Fln.js → ComputerViewerView-ChYgaS9q.js} +2 -2
- package/dist/assets/{ComputerViewerView-B76D6Fln.js.map → ComputerViewerView-ChYgaS9q.js.map} +1 -1
- package/dist/assets/{ConversationsView-DsuaLKva.js → ConversationsView-DzcDJZh3.js} +88 -88
- package/dist/assets/ConversationsView-DzcDJZh3.js.map +1 -0
- package/dist/assets/ConversationsView-EdF5AM1T.css +1 -0
- package/dist/assets/{LocalVmSettingsPanel-BfXFdMYF.js → LocalVmSettingsPanel-DLbDb5Tq.js} +4 -4
- package/dist/assets/{LocalVmSettingsPanel-BfXFdMYF.js.map → LocalVmSettingsPanel-DLbDb5Tq.js.map} +1 -1
- package/dist/assets/{ModelNetworkChoice-DB6cLOBw.js → ModelNetworkChoice-Cfyt4Unl.js} +2 -2
- package/dist/assets/{ModelNetworkChoice-DB6cLOBw.js.map → ModelNetworkChoice-Cfyt4Unl.js.map} +1 -1
- package/dist/assets/{StandaloneDialog-BWUp2Wxo.js → StandaloneDialog-Cte829Ai.js} +2 -2
- package/dist/assets/{StandaloneDialog-BWUp2Wxo.js.map → StandaloneDialog-Cte829Ai.js.map} +1 -1
- package/dist/assets/{UpdateCheckDialog-CpZSPlUI.js → UpdateCheckDialog-BaMo_M4n.js} +2 -2
- package/dist/assets/{UpdateCheckDialog-CpZSPlUI.js.map → UpdateCheckDialog-BaMo_M4n.js.map} +1 -1
- package/dist/assets/{UsageView-BhiRCw7p.js → UsageView-CklMPG4n.js} +3 -3
- package/dist/assets/{UsageView-BhiRCw7p.js.map → UsageView-CklMPG4n.js.map} +1 -1
- package/dist/assets/WorkspaceKnowledgePanel-BdbhD3rO.js +3 -0
- package/dist/assets/{WorkspaceKnowledgePanel-D34YxglF.js.map → WorkspaceKnowledgePanel-BdbhD3rO.js.map} +1 -1
- package/dist/assets/WorkspaceRoutinesPanel-VpRoMe1x.js +2 -0
- package/dist/assets/{WorkspaceRoutinesPanel-Bn-W52Im.js.map → WorkspaceRoutinesPanel-VpRoMe1x.js.map} +1 -1
- package/dist/assets/{WorkstreamsView-CH6qDPvj.js → WorkstreamsView-BwZpuuhs.js} +2 -2
- package/dist/assets/{WorkstreamsView-CH6qDPvj.js.map → WorkstreamsView-BwZpuuhs.js.map} +1 -1
- package/dist/assets/index-C-5Gq82f.css +1 -0
- package/dist/assets/{index-DjhQ-RMG.js → index-Cx1SdzRY.js} +18 -18
- package/dist/assets/index-Cx1SdzRY.js.map +1 -0
- package/dist/assets/{pdf-wqiF06Qz.js → pdf-CoNh_Rmj.js} +2 -2
- package/dist/assets/{pdf-wqiF06Qz.js.map → pdf-CoNh_Rmj.js.map} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/server/remoteAccess/dispatcher.js +5 -1
- 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/dist/index.html
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" />
|
|
10
10
|
<link rel="manifest" href="/manifest.webmanifest" />
|
|
11
11
|
<title>Yaovi</title>
|
|
12
|
-
<script type="module" crossorigin src="/assets/index-
|
|
12
|
+
<script type="module" crossorigin src="/assets/index-Cx1SdzRY.js"></script>
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-Dd_uD5pT.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-CD0r-vVb.js">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C-5Gq82f.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
|
@@ -99,6 +99,10 @@ export function remoteDispatcher(app, principal, workspace, uploads) {
|
|
|
99
99
|
const callback = app.callback();
|
|
100
100
|
const dispatch = async (request) => {
|
|
101
101
|
principal.assert();
|
|
102
|
+
// A cancelled file permission probe must not allocate an abandoned response
|
|
103
|
+
// promise: rejecting it and throwing separately crashes Node's Host process.
|
|
104
|
+
if (request.signal.aborted)
|
|
105
|
+
throw new Error("REQUEST_ABORTED");
|
|
102
106
|
const url = new URL(request.url);
|
|
103
107
|
if (!remoteRouteAllowed(request.method, url.pathname))
|
|
104
108
|
return Response.json({
|
|
@@ -222,7 +226,7 @@ export function remoteDispatcher(app, principal, workspace, uploads) {
|
|
|
222
226
|
});
|
|
223
227
|
if (request.signal.aborted) {
|
|
224
228
|
stop();
|
|
225
|
-
|
|
229
|
+
return response;
|
|
226
230
|
}
|
|
227
231
|
callback(req, res);
|
|
228
232
|
return response;
|
|
@@ -26010,7 +26010,9 @@ var RemoteHost = class {
|
|
|
26010
26010
|
timers = [];
|
|
26011
26011
|
stop;
|
|
26012
26012
|
stopped = false;
|
|
26013
|
+
/** Extra heartbeat fields, e.g. devices revoked on the Host itself. */
|
|
26013
26014
|
heartbeatPayload;
|
|
26015
|
+
/** Receives each heartbeat reply, including the cloud's current trusted devices. */
|
|
26014
26016
|
onHeartbeat;
|
|
26015
26017
|
async start() {
|
|
26016
26018
|
await this.control.connect();
|
|
@@ -26018,13 +26020,13 @@ var RemoteHost = class {
|
|
|
26018
26020
|
if (f.type === "connect.request") void this.incoming(f.payload).catch(() => {
|
|
26019
26021
|
});
|
|
26020
26022
|
});
|
|
26021
|
-
const heartbeat =
|
|
26022
|
-
|
|
26023
|
-
|
|
26024
|
-
|
|
26025
|
-
});
|
|
26023
|
+
const heartbeat = () => this.api.signed(`/api/v1/hosts/${this.hostId}/heartbeat`, this.hostId, {
|
|
26024
|
+
capabilities: ["wss", "rtc", "rpc", "events", "files"],
|
|
26025
|
+
...this.heartbeatPayload?.()
|
|
26026
|
+
}).then((result) => {
|
|
26026
26027
|
this.onHeartbeat?.(result);
|
|
26027
|
-
|
|
26028
|
+
return result;
|
|
26029
|
+
});
|
|
26028
26030
|
await heartbeat();
|
|
26029
26031
|
let checking = false;
|
|
26030
26032
|
this.timers.push(
|
|
@@ -26192,7 +26194,8 @@ function framed(socket) {
|
|
|
26192
26194
|
try {
|
|
26193
26195
|
frame = JSON.parse(String(event.data));
|
|
26194
26196
|
if (frame.t === "d") {
|
|
26195
|
-
if (typeof frame.d !== "string" || frame.d.length > 12e4)
|
|
26197
|
+
if (typeof frame.d !== "string" || frame.d.length > 12e4)
|
|
26198
|
+
throw new Error("FRAME_INVALID");
|
|
26196
26199
|
queue.push(unb64(frame.d));
|
|
26197
26200
|
} else for (const fn of [...waiters]) fn(frame);
|
|
26198
26201
|
} catch {
|
|
@@ -26561,12 +26564,12 @@ var StreamMux = class {
|
|
|
26561
26564
|
throw new Error("STREAM_INVALID");
|
|
26562
26565
|
this.lastIncoming = h.streamId;
|
|
26563
26566
|
const v = rpcOpen.parse(h);
|
|
26564
|
-
|
|
26565
|
-
|
|
26567
|
+
const remaining = v.deadline - Date.now();
|
|
26568
|
+
if (remaining <= 0) throw new Error("DEADLINE_INVALID");
|
|
26566
26569
|
s = this.state(h.streamId, true);
|
|
26567
26570
|
const current = s;
|
|
26568
26571
|
current.eventRequest = v.method === "GET" && new URL(v.path, "https://remote.invalid").pathname === "/api/app/events/stream";
|
|
26569
|
-
this.deadline(current,
|
|
26572
|
+
this.deadline(current, Math.min(remaining, 3e5));
|
|
26570
26573
|
const body = ["GET", "HEAD"].includes(v.method) ? null : this.body(current);
|
|
26571
26574
|
const request = this.platform.request("https://remote.invalid" + v.path, {
|
|
26572
26575
|
method: v.method,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yaovi/remote-core",
|
|
3
|
-
"version": "0.2.0-remote.
|
|
3
|
+
"version": "0.2.0-remote.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
|
-
"yaoviSourceRevision": "
|
|
6
|
+
"yaoviSourceRevision": "872d3bdfcec5f4878e06685ccb7f4725776db274",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
9
|
"types": "./types/remote-core/src/index.d.ts",
|
|
@@ -33,6 +33,6 @@ export declare class ConnectionRecovery<T> {
|
|
|
33
33
|
retryNow(): Promise<T>;
|
|
34
34
|
/** Coalesce replacement requests while a new link is already opening. */
|
|
35
35
|
reconnect(): Promise<T>;
|
|
36
|
-
verify(probe: (value: T, signal: AbortSignal) => Promise<
|
|
36
|
+
verify(probe: (value: T, signal: AbortSignal) => Promise<unknown>, timeoutMs?: number): Promise<T | undefined>;
|
|
37
37
|
close(): void;
|
|
38
38
|
}
|
|
@@ -37,7 +37,9 @@ export declare class RemoteHost {
|
|
|
37
37
|
private timers;
|
|
38
38
|
private stop?;
|
|
39
39
|
private stopped;
|
|
40
|
+
/** Extra heartbeat fields, e.g. devices revoked on the Host itself. */
|
|
40
41
|
heartbeatPayload?: () => Record<string, unknown>;
|
|
42
|
+
/** Receives each heartbeat reply, including the cloud's current trusted devices. */
|
|
41
43
|
onHeartbeat?: (result: any) => void;
|
|
42
44
|
constructor(api: ControlClient, control: ControlSocket, hostId: string, allowed: (issued: any) => Promise<boolean>, onConnection: (connection: RemoteConnection) => void, factory?: RtcFactory | undefined);
|
|
43
45
|
start(): Promise<void>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type DeviceKeys } from '../crypto/proof.ts';
|
|
2
2
|
import type { SocketLike } from '../control/socket.ts';
|
|
3
3
|
import { LeaseDeadline, type RemoteConnection } from '../control/remote.ts';
|
|
4
|
+
/** Direct LAN entry for devices the Host already trusts; works without the cloud. */
|
|
5
|
+
export declare const LAN_PATH = "/yaovi-lan/v1";
|
|
6
|
+
export declare const LAN_DEFAULT_PORT = 8981;
|
|
4
7
|
export type LanEndpoint = {
|
|
5
8
|
address: string;
|
|
6
9
|
port: number;
|
|
@@ -15,20 +18,23 @@ export type LanTrust = {
|
|
|
15
18
|
clientKey: string;
|
|
16
19
|
clientProofKey: string;
|
|
17
20
|
};
|
|
18
|
-
|
|
19
|
-
export declare const LAN_DEFAULT_PORT = 8981;
|
|
21
|
+
/** Discovery tag: the Host id is not broadcast, only a short digest of it. */
|
|
20
22
|
export declare function lanHostTag(hostId: string): Promise<string>;
|
|
23
|
+
/** Only literal private IPv4 addresses are acceptable LAN targets. */
|
|
21
24
|
export declare function lanUrl(endpoint: LanEndpoint): string;
|
|
25
|
+
/** Unbounded by design: LAN entry stays usable offline until the Host revokes the device. */
|
|
22
26
|
export declare class LocalLease extends LeaseDeadline {
|
|
23
27
|
update(): void;
|
|
24
28
|
assert(): void;
|
|
25
29
|
}
|
|
30
|
+
/** Client side: pins the Host key, proves both device keys, needs no cloud access. */
|
|
26
31
|
export declare function connectLan(socket: SocketLike, pin: LanPin, keys: DeviceKeys, signal?: AbortSignal): Promise<RemoteConnection>;
|
|
32
|
+
/** Host side: only a device in the Host's own trust list completes the handshake. */
|
|
27
33
|
export declare function acceptLan(socket: SocketLike, host: {
|
|
28
34
|
hostId: string;
|
|
29
35
|
bindingEpoch: number;
|
|
30
36
|
keys: DeviceKeys;
|
|
31
|
-
}, find: (
|
|
37
|
+
}, find: (clientDeviceId: string) => LanTrust | undefined): Promise<{
|
|
32
38
|
connection: RemoteConnection;
|
|
33
|
-
clientDeviceId:
|
|
39
|
+
clientDeviceId: string;
|
|
34
40
|
}>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type PathDiagnostics = {
|
|
2
|
-
selected: '
|
|
2
|
+
selected: 'p2p' | 'turn' | 'wss' | 'lan' | 'unverified';
|
|
3
3
|
bytesSent?: number;
|
|
4
4
|
bytesReceived?: number;
|
|
5
5
|
fallbacks?: {
|
|
@@ -8,7 +8,7 @@ export type PathDiagnostics = {
|
|
|
8
8
|
}[];
|
|
9
9
|
};
|
|
10
10
|
export interface PacketTransport {
|
|
11
|
-
readonly path: '
|
|
11
|
+
readonly path: 'p2p' | 'turn' | 'wss' | 'lan';
|
|
12
12
|
readonly bufferedAmount: number;
|
|
13
13
|
diagnostics?(): Promise<PathDiagnostics>;
|
|
14
14
|
send(data: Uint8Array): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lsamien/yaovi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Yaovi:单用户、多 Bot、多设备服务器",
|
|
6
6
|
"type": "module",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@vicons/tabler": "^0.13.0",
|
|
67
67
|
"@vitejs/plugin-vue": "^6.0.5",
|
|
68
68
|
"@vue/tsconfig": "^0.9.1",
|
|
69
|
-
"@yaovi/remote-core": "file:vendor/yaovi-remote-core-0.2.0-remote.
|
|
69
|
+
"@yaovi/remote-core": "file:vendor/yaovi-remote-core-0.2.0-remote.18.tgz",
|
|
70
70
|
"bonjour-service": "1.4.4",
|
|
71
71
|
"busboy": "^1.6.0",
|
|
72
72
|
"cookie": "^1.0.2",
|
package/release.json
CHANGED
|
Binary file
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{A as e,Et as t,F as n,G as r,H as i,L as a,M as o,Ot as s,W as c,_ as l,a as u,b as d,d as f,et as p,f as m,m as h,p as g,st as _,t as v,u as y,v as b}from"./_plugin-vue_export-helper-CD0r-vVb.js";import{$ as x,D as S,I as C,nt as w,ot as T,rt as E}from"./index-DjhQ-RMG.js";import{t as D}from"./StandaloneDialog-BWUp2Wxo.js";import{_ as O,b as k,s as A,v as j,x as M,y as N}from"./ConversationsView-DsuaLKva.js";var P={class:`integration-panel plugins`,"aria-label":`本地原生插件`},F={class:`integration-header`},I={class:`catalog-intro`},L=[`disabled`],R={class:`plugin-trust`},z={key:0,class:`integration-alert`,role:`alert`},B={key:1,class:`integration-alert`,role:`status`},V={class:`integration-toolbar`},H={class:`integration-search`},U={class:`integration-check`},W={key:2,class:`integration-card update-review`},G={class:`capability-compare`},K={class:`integration-actions`},q=[`disabled`],ee={class:`catalog-results`},J={class:`integration-count`},Y={class:`plugins-grid`},X={class:`plugin-heading`},Z={class:`integration-mark`},te={class:`plugin-version`},ne={class:`plugin-description`},re={class:`compatibility`},Q={class:`plugin-details`},$=[`href`],ie={class:`source-sha`},ae={key:0},oe={key:0,class:`plugin-failure`},se={class:`integration-actions plugin-footer`},ce=[`disabled`,`onClick`],le=[`disabled`,`onClick`],ue=[`disabled`,`onClick`],de={key:3,class:`integration-empty`},fe=v(d({__name:`NativePluginsPanel`,setup(e){let i=p([]),c=p(``),d=p(!1),m=p(!1),_=p(``),v=p(``),w=p(),T=p(),D=y(()=>i.value.filter(e=>(!d.value||e.installed)&&`${e.name} ${e.title} ${e.description}`.toLowerCase().includes(c.value.toLowerCase())));async function O(){i.value=(await S(`/api/app/admin/hermes/local/plugins/catalog`)).plugins}async function k(e){if(!m.value){m.value=!0,_.value=``;try{await e()}catch(e){_.value=e instanceof Error?e.message:`插件操作失败`}finally{m.value=!1}}}async function A(e,t=!1){await k(async()=>{let n=await S(`/api/app/admin/hermes/local/plugins/install`,{method:`POST`,timeoutMs:61e4,body:{name:e.name,sha:e.sha,acceptChanges:t}});if(n.consent_required){w.value=e,T.value=n,v.value=`更新版本可能改变能力和依赖,请审阅后确认。`;return}if(!n.ok)throw Error(n.error??`插件未安装`);w.value=void 0,v.value=`安装完成。插件保持停用,启用时检查宿主兼容性。`,await O()})}async function j(e){await k(async()=>{let t=await S(`/api/app/admin/hermes/local/plugins/enabled`,{method:`POST`,body:{name:e.name,enabled:!e.installed?.enabled}});if(!t.ok)throw Error(t.error??`插件状态未改变`);await O()})}async function M(e){window.confirm(`移除 `+e.name+`?原包会保留在主机备份目录。`)&&await k(async()=>{await S(`/api/app/admin/hermes/local/plugins/remove`,{method:`POST`,body:{name:e.name}}),await O()})}return o(()=>k(O)),(e,o)=>(n(),h(`section`,P,[f(`header`,F,[f(`div`,null,[o[5]||=f(`h3`,null,`发现更多能力`,-1),f(`p`,I,s(i.value.length)+` 项本地插件,按固定版本安装。`,1)]),f(`button`,{class:`quiet`,disabled:m.value,"aria-label":`刷新本地目录`,onClick:o[0]||=e=>k(O)},[b(C,{name:`refresh`,size:17})],8,L)]),f(`details`,R,[f(`summary`,null,[b(C,{name:`shield`,size:17}),o[6]||=l(`仅安装你信任的插件`,-1)]),o[7]||=f(`p`,null,`插件运行在主机上,可访问文件和网络。Bot 权限控制工具入口,不能隔离插件的初始化或内部行为。桌面、Hook、供应商等能力需要各自宿主适配,安装成功不代表已可用。`,-1)]),_.value?(n(),h(`p`,z,[b(C,{name:`alert`,size:17}),l(s(_.value),1)])):g(``,!0),v.value?(n(),h(`p`,B,[b(C,{name:`check`,size:17}),l(s(v.value),1)])):g(``,!0),f(`div`,V,[f(`label`,H,[o[8]||=f(`span`,{class:`sr-only`},`搜索插件`,-1),b(C,{name:`search`,size:17}),r(f(`input`,{"onUpdate:modelValue":o[1]||=e=>c.value=e,type:`search`,placeholder:`搜索插件名称或用途`},null,512),[[E,c.value]])]),f(`label`,U,[r(f(`input`,{"onUpdate:modelValue":o[2]||=e=>d.value=e,type:`checkbox`},null,512),[[x,d.value]]),o[9]||=l(`仅显示已安装`,-1)])]),w.value?(n(),h(`article`,W,[o[12]||=f(`span`,{class:`integration-tag warning`},`需要审阅`,-1),f(`h4`,null,`审阅 `+s(w.value.name)+` 更新`,1),f(`p`,null,s(w.value.description),1),f(`p`,null,`版本 `+s(w.value.version)+` · `+s(w.value.sha),1),f(`div`,G,[f(`div`,null,[o[10]||=f(`h4`,null,`旧能力`,-1),f(`pre`,null,s(JSON.stringify(T.value?.oldCapabilities,null,2)),1)]),f(`div`,null,[o[11]||=f(`h4`,null,`新能力`,-1),f(`pre`,null,s(JSON.stringify(T.value?.newCapabilities,null,2)),1)])]),o[13]||=f(`h4`,null,`当前依赖`,-1),f(`pre`,null,s(T.value?.oldDependencies),1),o[14]||=f(`p`,null,`新版本按固定 SHA 扫描并校验实际能力;依赖安装受 Host 版本约束,安装后保持停用。`,-1),f(`div`,K,[f(`button`,{class:`primary`,disabled:m.value,onClick:o[3]||=e=>A(w.value,!0)},`确认更新到此版本`,8,q),f(`button`,{onClick:o[4]||=e=>w.value=void 0},`取消更新`)])])):g(``,!0),f(`div`,ee,[f(`span`,J,s(c.value||d.value?`匹配 `+D.value.length+` 项`:`全部 `+i.value.length+` 项`),1),o[15]||=f(`span`,{class:`integration-count`},`安装后默认停用`,-1)]),f(`ul`,Y,[(n(!0),h(u,null,a(D.value,e=>(n(),h(`li`,{key:e.name,class:`integration-card plugin-card`},[f(`div`,X,[f(`span`,Z,[b(C,{name:e.compatibility===`tools`?`tools`:e.category===`desktop`?`monitor`:`artifacts`,size:20},null,8,[`name`])]),f(`div`,null,[f(`h4`,null,s(e.title||e.name),1),f(`span`,te,`v`+s(e.version),1)]),e.installed?(n(),h(`span`,{key:0,class:t([`integration-tag`,{success:e.installed.enabled}])},s(e.installed.enabled?`已启用`:`已安装`),3)):g(``,!0)]),f(`p`,ne,s(e.description),1),f(`p`,re,[f(`span`,{class:t([`integration-tag`,{success:e.compatibility===`tools`,warning:e.compatibility!==`tools`}])},s(e.compatibility===`tools`?`工具可接入`:`需适配`),3),l(s(e.compatibilityNote),1)]),f(`details`,Q,[o[16]||=f(`summary`,null,`来源、能力与依赖`,-1),f(`p`,null,s(e.description),1),f(`a`,{href:e.repo,target:`_blank`,rel:`noopener noreferrer`},`查看源码 ↗`,8,$),f(`p`,ie,`固定版本:`+s(e.sha),1),f(`pre`,null,s(JSON.stringify(e.capabilities,null,2)),1),e.installed?.dependencies?.length?(n(),h(`p`,ae,`已安装依赖:`+s(e.installed.dependencies.join(`、`)),1)):g(``,!0)]),e.installed?.lastError?(n(),h(`p`,oe,s(e.installed.lastError),1)):g(``,!0),f(`div`,se,[!e.installed||e.installed.sha!==e.sha?(n(),h(`button`,{key:0,disabled:m.value,onClick:t=>A(e)},[b(C,{name:e.installed?`refresh`:`plus`,size:15},null,8,[`name`]),l(s(e.installed?`检查并更新`:`安装固定版本`),1)],8,ce)):g(``,!0),e.installed?(n(),h(`button`,{key:1,class:t({primary:!e.installed.enabled}),disabled:m.value||!e.installed.enabled&&e.compatibility!==`tools`,onClick:t=>j(e)},s(e.installed.enabled?`停用`:`检查并启用工具`),11,le)):g(``,!0),e.installed?(n(),h(`button`,{key:2,class:`quiet danger`,disabled:m.value,onClick:t=>M(e)},`移除`,8,ue)):g(``,!0)])]))),128))]),!m.value&&!D.value.length?(n(),h(`div`,de,[b(C,{name:`search`,size:28}),o[17]||=f(`strong`,null,`没有匹配的插件`,-1),o[18]||=f(`p`,null,`试试其他关键词,或取消已安装筛选。`,-1)])):g(``,!0)]))}}),[[`__scopeId`,`data-v-2e231ffc`]]),pe=[`aria-label`],me={class:`integration-header`},he={class:`integration-heading`},ge=[`disabled`],_e={class:`mail-account`},ve=[`disabled`],ye=[`value`],be={class:`integration-search`},xe=[`disabled`],Se={key:0,class:`mail-loading`,role:`status`},Ce={key:1,class:`integration-alert`,role:`alert`},we={key:2,class:`integration-alert`,role:`status`},Te={key:3,class:`mail-unknown`},Ee={class:`integration-heading`},De={class:`integration-actions`},Oe=[`disabled`],ke=[`disabled`],Ae={class:`mail-layout`},je={class:`mail-list`},Me={class:`mail-list-heading`},Ne={class:`messages`},Pe=[`aria-pressed`,`disabled`,`onClick`],Fe={class:`message-from`},Ie={key:0,class:`integration-empty`},Le={class:`mail-reading`},Re={class:`compose-heading`},ze={class:`integration-tag`},Be=[`disabled`],Ve=[`disabled`],He={class:`integration-actions`},Ue=[`disabled`],We=[`disabled`],Ge={key:1,class:`mail-detail`},Ke={class:`mail-detail-heading`},qe={class:`message-meta`},Je=[`innerHTML`],Ye={key:0,class:`mail-attachments`},Xe=[`disabled`,`onClick`],Ze={class:`integration-actions mail-actions`},Qe=[`disabled`],$e=[`disabled`],et=[`disabled`],tt={class:`mail-labels`},nt=[`value`],rt={class:`integration-actions`},it=[`disabled`],at=[`disabled`],ot={key:2,class:`integration-empty reading-empty`},st={class:`reading-illustration`},ct=v(d({__name:`GmailPanel`,props:{accounts:{},source:{default:`local`}},setup(e){let c=e,d=y(()=>c.source===`composio`?`Composio 托管`:`本地连接`),m=(e=c.source)=>e===`composio`?`/api/app/admin/composio`:`/api/app/admin/hermes/local/google`,_=p(c.accounts[0]?.id??``),v=p(`in:inbox`),x=p([]),D=p(),O=p(!1),k=p(``),j=p(``),M=p(!1),N=p(!1),P=p(``),F=p(``),I=p(``),L=p(``),R=p([]),z=p(!1),B=0,V=!1,H,U=p(),W=(e,t)=>e?.payload?.headers?.find(e=>e.name.toLowerCase()===t.toLowerCase())?.value??``;async function G(e,t,n=!1,r=_.value,i,a=c.source){let o=n?i??crypto.randomUUID():void 0;try{let i=await S(m(a)+`/call`,{method:`POST`,timeoutMs:95e3,body:{accountId:r,operation:e,arguments:t,...n?{operationId:o}:{}}});if(i?.isError){n&&i.outcomeUnknown&&(z.value=!0,U.value={accountId:r,operationId:o,source:a});let e=Error(i.error?.message??`Google 请求失败`);throw Object.assign(e,{known:!i.outcomeUnknown}),e}return i}catch(e){throw a===`composio`&&[400,401,403,404,409,413,422].includes(e?.status??0)&&Object.assign(e,{known:!0}),n&&!e?.known&&(z.value=!0,U.value={accountId:r,operationId:o,source:a}),e}}async function K(e){if(O.value){e===q&&(V=!0);return}O.value=!0,k.value=``,j.value=``;try{await e()}catch(e){k.value=e instanceof Error?e.message:`邮箱操作失败`}finally{O.value=!1,V&&(V=!1,K(q))}}async function q(){if(!_.value)return;let e=++B,t=_.value,n=c.source;D.value=void 0;let r=await G(`gmail.search`,{query:v.value,max:15},!1,t,void 0,n),i=[];if(e!==B||t!==_.value||n!==c.source)return;for(let a of r.messages??[]){let r=await G(`gmail.get`,{id:a.id},!1,t,void 0,n);if(e!==B||t!==_.value)return;i.push(r)}let a=await G(`gmail.labels`,{},!1,t,void 0,n);e===B&&t===_.value&&(x.value=i,R.value=a.labels??[])}async function ee(e){await K(async()=>{let t=_.value,n=B,r=c.source,i=await G(`gmail.get`,{id:e.id},!1,t,void 0,r);t===_.value&&n===B&&(D.value=i)})}async function J(){await K(async()=>{if(!U.value)return;let e=await S(m(U.value.source)+`/receipts/`+U.value.accountId+`/`+encodeURIComponent(U.value.operationId));j.value=e.status===`complete`?`邮箱操作已完成,已读取保存的结果。`:e.status===`rejected`?`邮箱服务已拒绝此操作。`:`仍无确认结果,请在 Gmail 核对。`,[`complete`,`rejected`].includes(e.status)&&(z.value=!1,M.value=!1,H=void 0,U.value=void 0,await q())})}function Y(e){let t=Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0));return new TextDecoder().decode(t)}function X(e){if(!e)return``;if(e.mimeType===`text/plain`&&e.body?.data)return`<pre>`+Y(e.body.data).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/\n/g,`<br>`)+`</pre>`;let t=e.parts??[],n=t.find(e=>e.mimeType===`text/plain`);return n?X(n):e.mimeType===`text/html`&&e.body?.data?A.sanitize(Y(e.body.data),{FORBID_TAGS:[`img`,`style`,`script`,`iframe`,`form`,`svg`,`math`,`video`,`audio`,`link`],FORBID_ATTR:[`style`,`src`,`srcset`,`background`]}):t.map(X).join(``)}function Z(e){return[...e?.filename&&(e?.body?.attachmentId||e?.body?.data)?[e]:[],...(e?.parts??[]).flatMap(Z)]}async function te(e){await K(async()=>{let t=e.body.data?e.body:await G(`gmail.attachment`,{id:D.value.id,attachmentId:e.body.attachmentId});if(t.size>26214400||String(t.data??``).length>104857600/3+4)throw Error(`附件超过25MB限制`);let n=Uint8Array.from(atob(t.data.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0)),r=URL.createObjectURL(new Blob([n],{type:`application/octet-stream`})),i=document.createElement(`a`);i.href=r,i.download=String(e.filename).replace(/[\\/\x00-\x1f]/g,`_`).slice(0,180)||`attachment`,document.body.append(i),i.click(),i.remove(),setTimeout(()=>URL.revokeObjectURL(r),3e4)})}function ne(e=!1){z.value||(H={accountId:_.value,...e?{messageId:D.value.id}:{},operationId:crypto.randomUUID(),source:c.source},N.value=e,M.value=!0,P.value=e?W(D.value,`Reply-To`)||W(D.value,`From`):``,F.value=e?`Re: `+W(D.value,`Subject`):``,I.value=``)}async function re(){await K(async()=>{let e=H;if(!e||e.accountId!==_.value||e.source!==c.source||z.value)throw Error(`草稿账号已改变,请重新编辑。`);try{let t=await G(e.messageId?`gmail.reply`:`gmail.send`,e.messageId?{id:e.messageId,body:I.value}:{to:P.value,subject:F.value,body:I.value},!0,e.accountId,e.operationId,e.source);if(e.accountId!==_.value||e.source!==c.source)return;M.value=!1,H=void 0,j.value=`邮件已发送,消息编号:`+(t.id??`已确认`),t.id&&(D.value=await G(`gmail.get`,{id:t.id},!1,e.accountId,void 0,e.source))}catch(e){throw!z.value&&H&&(H.operationId=crypto.randomUUID()),e}})}async function Q(e,t){z.value||await K(async()=>{let n=_.value;await G(e,t,!0,n),await q(),j.value=`邮箱操作已完成。`})}return i(()=>c.accounts.map(e=>e.id).join(`,`),()=>{c.accounts.some(e=>e.id===_.value)||(_.value=c.accounts[0]?.id??``,B++,x.value=[],D.value=void 0,M.value=!1,H=void 0)}),i(()=>c.source,()=>{B++,x.value=[],D.value=void 0,M.value=!1,H=void 0,k.value=``,j.value=``,K(q)}),i(_,()=>{B++,x.value=[],D.value=void 0,M.value=!1,H=void 0,K(q)}),o(()=>K(q)),(i,o)=>(n(),h(`section`,{class:`integration-panel mailbox`,"aria-label":e.source===`composio`?`Composio Gmail 邮箱`:`本地 Gmail 邮箱`},[f(`header`,me,[f(`div`,he,[o[16]||=f(`span`,{class:`integration-mark gmail-mark`},[f(`img`,{src:`/provider-logos/gmail.svg`,alt:``,width:`25`,height:`25`})],-1),f(`div`,null,[o[15]||=f(`h3`,null,`Gmail`,-1),f(`p`,null,s(d.value)+` · `+s(x.value.length)+` 封邮件`,1)])]),f(`button`,{class:`primary`,type:`button`,disabled:O.value||z.value||!_.value,onClick:o[0]||=e=>ne()},[b(C,{name:`edit`,size:16}),o[17]||=l(`写邮件`,-1)],8,ge)]),f(`label`,_e,[o[18]||=l(`账号`,-1),r(f(`select`,{"onUpdate:modelValue":o[1]||=e=>_.value=e,disabled:O.value},[(n(!0),h(u,null,a(e.accounts,e=>(n(),h(`option`,{value:e.id,key:e.id},s(e.label),9,ye))),128))],8,ve),[[w,_.value]])]),f(`form`,{class:`mail-search`,onSubmit:o[3]||=T(e=>K(q),[`prevent`])},[f(`label`,be,[o[19]||=f(`span`,{class:`sr-only`},`搜索邮件`,-1),b(C,{name:`search`,size:17}),r(f(`input`,{"onUpdate:modelValue":o[2]||=e=>v.value=e,placeholder:`in:inbox 或 Gmail 搜索语法`},null,512),[[E,v.value]])]),f(`button`,{disabled:O.value},[b(C,{name:`refresh`,size:16}),o[20]||=l(`搜索 / 刷新`,-1)],8,xe)],32),O.value?(n(),h(`p`,Se,[b(C,{name:`clock`,size:15}),o[21]||=l(`正在处理邮箱…`,-1)])):g(``,!0),k.value?(n(),h(`p`,Ce,s(k.value),1)):g(``,!0),j.value?(n(),h(`p`,we,s(j.value),1)):g(``,!0),z.value?(n(),h(`div`,Te,[f(`div`,Ee,[b(C,{name:`alert`,size:19}),o[22]||=f(`strong`,null,`写入结果尚未确认`,-1)]),o[23]||=f(`p`,null,`请先在 Gmail 核对,再继续操作。`,-1),f(`div`,De,[f(`button`,{disabled:O.value,onClick:J},`查询操作收据`,8,Oe),f(`button`,{class:`quiet`,disabled:O.value,onClick:o[4]||=e=>{z.value=!1,M.value=!1,j.value=`已按你的确认允许新的操作;原操作不会自动重发。`}},`我已在 Gmail 核对,允许新操作`,8,ke)])])):g(``,!0),f(`div`,Ae,[f(`aside`,je,[f(`div`,Me,[o[24]||=f(`span`,null,`邮件列表`,-1),f(`span`,null,s(x.value.length),1)]),f(`ul`,Ne,[(n(!0),h(u,null,a(x.value,e=>(n(),h(`li`,{key:e.id},[f(`button`,{class:t({active:D.value?.id===e.id}),"aria-pressed":D.value?.id===e.id,disabled:O.value,onClick:t=>ee(e)},[f(`span`,Fe,s(W(e,`From`)),1),f(`strong`,null,s(W(e,`Subject`)||`(无主题)`),1),f(`small`,null,s(e.snippet),1)],10,Pe)]))),128))]),!O.value&&!x.value.length?(n(),h(`div`,Ie,[b(C,{name:`archive`,size:26}),o[25]||=f(`p`,null,`没有匹配的邮件。`,-1)])):g(``,!0)]),f(`div`,Le,[M.value?(n(),h(`form`,{key:0,class:`mail-compose`,onSubmit:T(re,[`prevent`])},[f(`div`,Re,[f(`h4`,null,s(N.value?`回复邮件`:`新邮件`),1),f(`span`,ze,s(e.accounts.find(e=>e.id===_.value)?.label),1)]),f(`label`,null,[o[26]||=l(`收件人`,-1),r(f(`input`,{"onUpdate:modelValue":o[5]||=e=>P.value=e,disabled:N.value,required:``},null,8,Be),[[E,P.value]])]),f(`label`,null,[o[27]||=l(`主题`,-1),r(f(`input`,{"onUpdate:modelValue":o[6]||=e=>F.value=e,disabled:N.value,required:``},null,8,Ve),[[E,F.value]])]),f(`label`,null,[o[28]||=l(`正文`,-1),r(f(`textarea`,{"onUpdate:modelValue":o[7]||=e=>I.value=e,rows:`7`,placeholder:`写下你的邮件…`,required:``},null,512),[[E,I.value]])]),f(`div`,He,[f(`button`,{class:`primary`,disabled:O.value||z.value},[b(C,{name:`arrow-up`,size:16}),o[29]||=l(`发送邮件`,-1)],8,Ue),f(`button`,{class:`quiet`,type:`button`,disabled:O.value,onClick:o[8]||=e=>M.value=!1},`取消编辑`,8,We)])],32)):g(``,!0),D.value?(n(),h(`article`,Ge,[f(`header`,Ke,[f(`h4`,null,s(W(D.value,`Subject`)||`(无主题)`),1),f(`p`,null,s(W(D.value,`From`)),1),f(`p`,qe,[l(`发送至 `+s(W(D.value,`To`)),1),o[30]||=f(`br`,null,null,-1),l(s(W(D.value,`Date`)),1)])]),f(`div`,{class:`email-body`,innerHTML:X(D.value.payload)},null,8,Je),Z(D.value.payload).length?(n(),h(`div`,Ye,[(n(!0),h(u,null,a(Z(D.value.payload),e=>(n(),h(`button`,{key:e.partId??e.body.attachmentId??e.filename,disabled:O.value,onClick:t=>te(e)},[b(C,{name:`download`,size:16}),l(`下载 `+s(e.filename)+`(`+s(e.body.size)+` 字节)`,1)],8,Xe))),128))])):g(``,!0),f(`div`,Ze,[f(`button`,{disabled:O.value||z.value,onClick:o[9]||=e=>ne(!0)},[b(C,{name:`edit`,size:15}),o[31]||=l(`回复`,-1)],8,Qe),f(`button`,{class:`quiet`,disabled:O.value||z.value,onClick:o[10]||=e=>Q(`gmail.modify`,{id:D.value.id,removeLabels:[`INBOX`]})},[b(C,{name:`archive`,size:15}),o[32]||=l(`归档`,-1)],8,$e),f(`button`,{class:`quiet danger`,disabled:O.value||z.value,onClick:o[11]||=e=>Q(`gmail.trash`,{id:D.value.id})},[b(C,{name:`trash`,size:15}),o[33]||=l(`移入垃圾箱`,-1)],8,et)]),f(`div`,tt,[f(`label`,null,[o[35]||=l(`标签`,-1),r(f(`select`,{"onUpdate:modelValue":o[12]||=e=>L.value=e},[o[34]||=f(`option`,{value:``},`选择标签`,-1),(n(!0),h(u,null,a(R.value,e=>(n(),h(`option`,{key:e.id,value:e.id},s(e.name),9,nt))),128))],512),[[w,L.value]])]),f(`div`,rt,[f(`button`,{disabled:O.value||z.value||!L.value.trim(),onClick:o[13]||=e=>Q(`gmail.modify`,{id:D.value.id,addLabels:[L.value]})},`添加标签`,8,it),f(`button`,{class:`quiet`,disabled:O.value||z.value||!L.value,onClick:o[14]||=e=>Q(`gmail.modify`,{id:D.value.id,removeLabels:[L.value]})},`移除标签`,8,at)])])])):M.value?g(``,!0):(n(),h(`div`,ot,[f(`span`,st,[b(C,{name:`file`,size:32})]),o[36]||=f(`strong`,null,`选择一封邮件开始阅读`,-1),o[37]||=f(`p`,null,`也可以写封新邮件,继续你的对话。`,-1)]))])])],8,pe))}}),[[`__scopeId`,`data-v-c7018d71`]]),lt={class:`integration-panel local-apps`,"aria-label":`本地应用`},ut={class:`integration-header`},dt=[`disabled`],ft={key:0,class:`integration-alert`,role:`alert`},pt={key:1,class:`integration-alert`,role:`status`},mt={class:`integration-card google-card`},ht={class:`integration-header`},gt={class:`google-setup`},_t={class:`setup-content`},vt=[`disabled`],yt={class:`google-services`},bt={class:`service-grid`},xt=[`value`],St=[`src`],Ct={class:`connect-row`},wt={class:`integration-actions`},Tt=[`disabled`],Et=[`disabled`],Dt={key:0,class:`auth-progress`,role:`status`},Ot={key:0},kt={class:`integration-actions`},At=[`href`],jt=[`disabled`],Mt={class:`google-accounts`},Nt={class:`accounts-heading`},Pt={class:`integration-count`},Ft={key:0},It={class:`account-row`},Lt={class:`account-avatar`},Rt={class:`account-copy`},zt={class:`account-manage`},Bt={class:`integration-actions`},Vt=[`disabled`,`onClick`],Ht=[`disabled`,`onClick`],Ut=[`disabled`,`onClick`],Wt={key:1,class:`accounts-empty`},Gt=v(d({__name:`LocalAppsPanel`,setup(i){let c=p(),d=p(``),_=p([`gmail`]),v=p(),y=p(!1),w=p(``),D=p(``),O=p(!1),k=p(),A={gmail:`gmail`,calendar:`googlecalendar`,drive:`googledrive`},j={gmail:`Gmail`,calendar:`日历`,drive:`云盘`,contacts:`联系人`,sheets:`表格`,docs:`文档`},M,N=!1;async function P(){c.value=await S(`/api/app/admin/hermes/local/google/status`)}async function F(e){if(!y.value){y.value=!0,w.value=``;try{await e()}catch(e){w.value=e instanceof Error?e.message:`操作失败`}finally{y.value=!1}}}async function I(){await F(async()=>{await S(`/api/app/admin/hermes/local/google/client`,{method:`POST`,body:{client:JSON.parse(d.value)}}),d.value=``,D.value=`客户端已保存在主机。请选择服务并连接账号。`,await P()})}async function L(e){if(y.value)return;let t=window.open(`about:blank`,`_blank`);t&&(t.opener=null),await F(async()=>{try{v.value=await S(`/api/app/admin/hermes/local/google/auth`,{method:`POST`,body:{services:_.value,...e?{accountId:e}:{}}}),t&&v.value.authUrl?t.location.href=v.value.authUrl:t?.close(),z()}catch(e){throw t?.close(),e}})}function R(e){let t=c.value?.accounts.find(t=>t.id===e);t&&(_.value=[...t.services],k.value=e,D.value=`已选择 `+t.label+`。请在上方勾选本次服务,再点击重新授权。`)}function z(){clearTimeout(M),!(N||!v.value||![`pending`,`received`,`exchanging`].includes(v.value.status))&&(M=setTimeout(async()=>{try{let e=await S(`/api/app/admin/hermes/local/google/auth/`+v.value.id);if(N)return;v.value={...v.value,...e},e.status===`approved`&&(D.value=`Google 已连接。`,await P())}catch(e){N||(w.value=e instanceof Error?e.message:`授权状态读取失败`)}z()},2e3))}async function B(){await F(async()=>{v.value&&=await S(`/api/app/admin/hermes/local/google/auth/`+v.value.id,{method:`DELETE`}),clearTimeout(M)})}async function V(e,t,n=!1){window.confirm(n?`撤销Google授权并断开?同一Google账号和客户端的其他本地连接也可能需要重新授权。`:`断开这个本地 Google 账号?使用此连接的 Bot 将无法继续访问。`)&&await F(async()=>{let r=await S(`/api/app/admin/hermes/local/google/accounts/`+e,{method:`DELETE`,body:{revision:t,revoke:n}});D.value=r.note,await P()})}let H=e=>({pending:`等待授权`,received:`授权已收到`,exchanging:`确认授权中`,approved:`已连接`,failed:`授权未完成`,expired:`授权已过期`,cancelled:`已取消`,connected:`已连接`,partial:`部分服务未获授权`,reauth_required:`需要重新授权`})[e]??e;return o(()=>F(P)),e(()=>{N=!0,clearTimeout(M),v.value&&[`pending`,`received`,`exchanging`].includes(v.value.status)&&S(`/api/app/admin/hermes/local/google/auth/`+v.value.id,{method:`DELETE`}).catch(()=>{})}),(e,i)=>(n(),h(`section`,lt,[f(`header`,ut,[i[6]||=f(`div`,null,[f(`h3`,null,`连接你的日常工具`),f(`p`,{class:`local-intro`},`由当前主机直接连接,账号与 Nous 应用独立管理。`)],-1),f(`button`,{class:`quiet refresh-local`,type:`button`,disabled:y.value,"aria-label":`刷新本地连接`,onClick:i[0]||=e=>F(P)},[b(C,{name:`refresh`,size:17})],8,dt)]),w.value?(n(),h(`p`,ft,[b(C,{name:`alert`,size:17}),l(s(w.value),1)])):g(``,!0),D.value?(n(),h(`p`,pt,[b(C,{name:`check`,size:17}),l(s(D.value),1)])):g(``,!0),f(`article`,mt,[f(`header`,ht,[i[7]||=f(`div`,{class:`integration-heading`},[f(`span`,{class:`google-mark`},[f(`span`,null,`G`)]),f(`div`,null,[f(`h3`,null,`Google Workspace`),f(`p`,null,`邮件、日程和文件,一处连接。`)])],-1),f(`span`,{class:t([`integration-tag`,{success:c.value?.configured}])},s(c.value?.configured?`客户端已配置`:`待配置`),3)]),f(`details`,gt,[f(`summary`,null,[b(C,{name:`settings`,size:16}),l(s(c.value?.configured?`更新 Google 客户端`:`配置 Google 客户端`),1)]),f(`div`,_t,[i[9]||=f(`p`,null,`在 Google Cloud 创建“桌面应用”客户端,启用所需 API,然后粘贴下载的 JSON。`,-1),i[10]||=f(`a`,{href:`https://console.cloud.google.com/auth/clients`,target:`_blank`,rel:`noopener noreferrer`},`打开 Google Cloud ↗`,-1),f(`form`,{onSubmit:T(I,[`prevent`])},[f(`label`,null,[i[8]||=l(`桌面客户端 JSON`,-1),r(f(`textarea`,{"onUpdate:modelValue":i[1]||=e=>d.value=e,rows:`5`,autocomplete:`off`,spellcheck:`false`,placeholder:`{ "installed": { … } }`,required:``},null,512),[[E,d.value]])]),f(`button`,{class:`primary`,disabled:y.value||!d.value.trim()},`保存到主机`,8,vt)],32)])]),f(`fieldset`,yt,[i[11]||=f(`legend`,null,`选择本次授权的服务`,-1),f(`div`,bt,[(n(),h(u,null,a(j,(e,a)=>f(`label`,{key:a,class:t([`service-option`,{selected:_.value.includes(a)}])},[r(f(`input`,{"onUpdate:modelValue":i[2]||=e=>_.value=e,type:`checkbox`,value:a},null,8,xt),[[x,_.value]]),[`gmail`,`calendar`,`drive`].includes(a)?(n(),h(`img`,{key:0,src:`/provider-logos/`+A[a]+`.svg`,alt:``,width:`19`,height:`19`},null,8,St)):(n(),m(C,{key:1,name:a===`contacts`?`users`:a===`sheets`?`board`:`file`,size:19},null,8,[`name`])),f(`span`,null,s(e),1)],2)),64))])]),f(`div`,Ct,[f(`p`,null,[b(C,{name:`monitor`,size:15}),i[12]||=l(`首次授权需在主机电脑的浏览器完成。`,-1)]),f(`div`,wt,[f(`button`,{class:`primary`,type:`button`,disabled:y.value||!c.value?.configured||!_.value.length||!!v.value&&[`pending`,`received`,`exchanging`].includes(v.value.status),onClick:i[3]||=e=>L(k.value)},[b(C,{name:`plus`,size:16}),l(s(k.value?`重新授权选中的账号`:`连接 Google 账号`),1)],8,Tt),k.value?(n(),h(`button`,{key:0,class:`quiet`,disabled:y.value,onClick:i[4]||=e=>{k.value=void 0,_.value=[`gmail`]}},`改为添加账号`,8,Et)):g(``,!0)])]),v.value?(n(),h(`div`,Dt,[f(`span`,{class:t([`integration-tag`,{success:v.value.status===`approved`}])},s(H(v.value.status)),3),v.value.error?(n(),h(`p`,Ot,s(v.value.error),1)):g(``,!0),f(`div`,kt,[v.value.authUrl&&v.value.status===`pending`?(n(),h(`a`,{key:0,href:v.value.authUrl,target:`_blank`,rel:`noopener noreferrer`},`在 Host 电脑浏览器继续授权 ↗`,8,At)):g(``,!0),[`pending`,`received`,`exchanging`].includes(v.value.status)?(n(),h(`button`,{key:1,class:`quiet`,disabled:y.value,onClick:B},`取消授权`,8,jt)):g(``,!0)])])):g(``,!0),f(`div`,Mt,[f(`div`,Nt,[i[13]||=f(`h4`,null,`已连接账号`,-1),f(`span`,Pt,s(c.value?.accounts.length??0)+` 个账号`,1)]),c.value?.accounts.length?(n(),h(`ul`,Ft,[(n(!0),h(u,null,a(c.value.accounts,e=>(n(),h(`li`,{key:e.id},[f(`div`,It,[f(`span`,Lt,[b(C,{name:`users`,size:18})]),f(`div`,Rt,[f(`strong`,null,s(e.label),1),f(`p`,null,s(e.services.map(e=>j[e]??e).join(` · `)),1)]),f(`span`,{class:t([`integration-tag`,{success:e.status===`connected`,warning:e.status!==`connected`}])},s(H(e.status)),3)]),f(`details`,zt,[i[14]||=f(`summary`,null,`管理账号`,-1),f(`div`,Bt,[f(`button`,{disabled:y.value,onClick:t=>R(e.id)},`重新授权`,8,Vt),f(`button`,{class:`quiet`,disabled:y.value,onClick:t=>V(e.id,e.revision)},`断开`,8,Ht),f(`button`,{class:`quiet danger`,disabled:y.value,onClick:t=>V(e.id,e.revision,!0)},`撤销 Google 授权`,8,Ut)])])]))),128))])):(n(),h(`p`,Wt,`连接账号后,所有设备都可以使用已授权的服务。`))]),c.value?.accounts?.some(e=>e.services.includes(`gmail`))?(n(),h(`button`,{key:1,class:`mail-entry`,onClick:i[5]||=e=>O.value=!O.value},[i[15]||=f(`img`,{src:`/provider-logos/gmail.svg`,alt:``,width:`20`,height:`20`},null,-1),l(s(O.value?`收起邮箱`:`打开本地 Gmail 邮箱`),1),b(C,{name:O.value?`chevron-down`:`chevron-right`,size:17},null,8,[`name`])])):g(``,!0)]),O.value&&c.value?(n(),m(ct,{key:2,accounts:c.value.accounts.filter(e=>e.services.includes(`gmail`))},null,8,[`accounts`])):g(``,!0)]))}}),[[`__scopeId`,`data-v-dfc4941d`]]),Kt={class:`integration-panel composio-apps`,"aria-label":`Composio 应用`},qt={class:`integration-header`},Jt=[`disabled`],Yt={key:0,class:`integration-alert`,role:`alert`},Xt={key:1,class:`integration-alert`,role:`status`},Zt={key:2,class:`integration-card import-card`},Qt={class:`integration-heading`},$t={class:`integration-mark`},en={key:0},tn=[`value`],nn={key:1,class:`hint`},rn=[`disabled`],an={class:`integration-card gmail-connection`},on={class:`integration-header`},sn={class:`composio-setup`},cn=[`disabled`],ln={class:`accounts-heading`},un={class:`integration-count`},dn={key:0,class:`composio-accounts`},fn={class:`account-copy`},pn=[`disabled`,`aria-label`,`onClick`],mn={key:1,class:`hint`},hn=[`required`,`disabled`],gn=[`disabled`],_n={key:2,class:`authorization-link`},vn=[`href`],yn=v(d({__name:`ComposioAppsPanel`,setup(i){let c=p(),d=p([]),_=p(!1),v=p(``),y=p(``),x=p(``),D=p(``),O=p(``),k=p(``),A=p(``),j=p(!1),M=0,N=new Set,P=!1,F,I=e=>({ACTIVE:`已连接`,INITIATED:`等待授权`,PENDING:`等待授权`,INITIALIZING:`连接中`,EXPIRED:`已过期`,FAILED:`连接失败`,INACTIVE:`未启用`,REVOKED:`已撤销`})[e.toUpperCase()]??e;async function L(){let e=await S(`/api/app/admin/composio/status`);if(P)return;if(c.value=e,e.legacy.some(e=>e.id===k.value)||(k.value=e.legacy[0]?.id??``),!e.configured){d.value=[];return}let t=await S(`/api/app/admin/composio/accounts`);P||(d.value=t.accounts)}async function R(e){if(!_.value){_.value=!0,v.value=``;try{await e()}catch(e){P||(v.value=e instanceof Error?e.message:`Composio 操作失败`)}finally{_.value=!1}}}async function z(){await R(async()=>{await S(`/api/app/admin/composio/import`,{method:`POST`,body:{candidateId:k.value,revision:c.value?.revision??0}}),y.value=`已导入旧连接。原 Gmail 授权和 yaoyao 数据均已保留。`,A.value=``,await L()})}async function B(){await R(async()=>{await S(`/api/app/admin/composio/settings`,{method:`PUT`,body:{apiKey:x.value.trim(),...D.value.trim()?{userId:D.value.trim()}:{},revision:c.value?.revision??0}}),x.value=``,D.value=``,y.value=`Composio 连接配置已保存到主机。`,await L()})}function V(){A.value=``,clearTimeout(F)}function H(){if(clearTimeout(F),!(P||!A.value)){if(Date.now()>M){y.value=`授权检查已结束,完成授权后可以手动刷新连接。`;return}F=setTimeout(async()=>{try{await L(),d.value.some(e=>e.status===`ACTIVE`&&!N.has(e.id))&&(A.value=``,y.value=`Gmail 已连接。`)}catch(e){P||(v.value=e instanceof Error?e.message:`授权状态读取失败`)}H()},5e3)}}function U(e){try{let t=new URL(e);return t.protocol===`https:`&&!t.username&&!t.password&&(t.hostname===`composio.dev`||t.hostname.endsWith(`.composio.dev`))?t.href:``}catch{return``}}async function W(){if(_.value)return;let e=window.open(`about:blank`,`_blank`);e&&(e.opener=null),await R(async()=>{try{let t=await S(`/api/app/admin/composio/authorize`,{method:`POST`,body:O.value.trim()?{alias:O.value.trim()}:{}});N=new Set(d.value.filter(e=>e.status===`ACTIVE`).map(e=>e.id)),M=Date.now()+12e4,A.value=U(t.url),e&&A.value?e.location.href=A.value:e?.close(),O.value=``,y.value=`请在浏览器完成 Gmail 授权,然后刷新连接。`,H()}catch(t){throw e?.close(),t}})}async function G(e){window.confirm(`断开此 Composio Gmail 账号并撤销其授权?原 yaoyao 中使用此连接的功能也会受到影响。`)&&await R(async()=>{await S(`/api/app/admin/composio/accounts/`+encodeURIComponent(e.id),{method:`DELETE`,body:{revision:c.value?.revision??0}}),y.value=`已断开指定 Gmail 账号。`,await L()})}return o(()=>R(L)),e(()=>{P=!0,clearTimeout(F)}),(e,i)=>(n(),h(`section`,Kt,[f(`header`,qt,[i[6]||=f(`div`,null,[f(`h3`,null,`继续使用你的 Gmail`),f(`p`,null,`通过 Composio 托管连接,与本地 Google 和 Nous 独立管理。`)],-1),f(`button`,{class:`quiet`,disabled:_.value,"aria-label":`刷新 Composio 连接`,onClick:i[0]||=e=>R(L)},[b(C,{name:`refresh`,size:17})],8,Jt)]),v.value?(n(),h(`p`,Yt,s(v.value),1)):g(``,!0),y.value?(n(),h(`p`,Xt,s(y.value),1)):g(``,!0),c.value?.legacy.length?(n(),h(`article`,Zt,[f(`div`,Qt,[f(`span`,$t,[b(C,{name:`archive`,size:22})]),i[7]||=f(`div`,null,[f(`h4`,null,`找到了 yaoyao 的旧连接`),f(`p`,null,`导入项目配置,继续使用已有 Gmail 授权。`)],-1)]),c.value.legacy.length>1?(n(),h(`label`,en,[i[8]||=l(`选择旧配置`,-1),r(f(`select`,{"onUpdate:modelValue":i[1]||=e=>k.value=e},[(n(!0),h(u,null,a(c.value.legacy,e=>(n(),h(`option`,{key:e.id,value:e.id},s(e.label),9,tn))),128))],512),[[w,k.value]])])):g(``,!0),c.value.configured?(n(),h(`p`,nn,`导入将替换当前 Composio 项目配置。`)):g(``,!0),f(`button`,{class:`primary`,disabled:_.value||!k.value,onClick:z},[b(C,{name:`download`,size:15}),i[9]||=l(`导入 yaoyao 旧连接`,-1)],8,rn)])):g(``,!0),f(`article`,an,[f(`header`,on,[i[10]||=f(`div`,{class:`integration-heading`},[f(`span`,{class:`integration-mark`},[f(`img`,{src:`/provider-logos/gmail.svg`,alt:``,width:`25`,height:`25`})]),f(`div`,null,[f(`h3`,null,`Gmail`),f(`p`,null,`邮件与草稿 · Composio`)])],-1),f(`span`,{class:t([`integration-tag`,{success:c.value?.configured}])},s(c.value?.configured?`项目已配置`:`待配置`),3)]),f(`details`,sn,[f(`summary`,null,[b(C,{name:`settings`,size:16}),l(s(c.value?.configured?`更新项目配置`:`手动配置 Composio`),1)]),f(`form`,{onSubmit:T(B,[`prevent`])},[i[13]||=f(`p`,null,`也可以使用自己的 Composio 项目 API Key。凭据加密保存在这台主机,不会回显。`,-1),i[14]||=f(`a`,{href:`https://platform.composio.dev`,target:`_blank`,rel:`noopener noreferrer`},`打开 Composio ↗`,-1),f(`label`,null,[i[11]||=l(`项目 API Key`,-1),r(f(`input`,{"onUpdate:modelValue":i[2]||=e=>x.value=e,type:`password`,autocomplete:`new-password`,placeholder:`输入 Composio API Key`,required:``},null,512),[[E,x.value]])]),f(`label`,null,[i[12]||=l(`已有用户标识(可选)`,-1),r(f(`input`,{"onUpdate:modelValue":i[3]||=e=>D.value=e,placeholder:`留空自动创建或保留现有标识`,maxlength:`256`},null,512),[[E,D.value]])]),f(`button`,{class:`primary`,disabled:_.value||!x.value.trim()},`保存项目配置`,8,cn)],32)]),f(`div`,ln,[i[15]||=f(`h4`,null,`已连接账号`,-1),f(`span`,un,s(d.value.length)+` 个账号`,1)]),d.value.length?(n(),h(`ul`,dn,[(n(!0),h(u,null,a(d.value,e=>(n(),h(`li`,{key:e.id},[f(`div`,fn,[f(`strong`,null,s(e.label),1),i[16]||=f(`p`,null,`Composio 托管授权`,-1)]),f(`span`,{class:t([`integration-tag`,{success:e.status===`ACTIVE`}])},s(I(e.status)),3),f(`button`,{class:`quiet danger`,disabled:_.value,"aria-label":`断开 `+e.label,onClick:t=>G(e)},`断开`,8,pn)]))),128))])):(n(),h(`p`,mn,s(c.value?.configured?`还没有 Gmail 连接,可以添加账号。`:`导入旧连接或配置项目后,即可连接 Gmail。`),1)),f(`form`,{class:`add-account`,onSubmit:T(W,[`prevent`])},[f(`label`,null,[l(s(d.value.length?`新账号别名`:`账号别名(可选)`),1),r(f(`input`,{"onUpdate:modelValue":i[4]||=e=>O.value=e,placeholder:`例如:工作邮箱`,maxlength:`64`,required:!!d.value.length,disabled:_.value||!c.value?.configured},null,8,hn),[[E,O.value]])]),f(`button`,{disabled:_.value||!c.value?.configured},[b(C,{name:`plus`,size:16}),i[17]||=l(`连接 Gmail 账号`,-1)],8,gn)],32),A.value?(n(),h(`div`,_n,[f(`a`,{href:A.value,target:`_blank`,rel:`noopener noreferrer`},`继续 Gmail 授权 ↗`,8,vn),f(`button`,{class:`quiet`,onClick:V},`停止检查授权状态`)])):g(``,!0),d.value.some(e=>e.status===`ACTIVE`)?(n(),h(`button`,{key:3,class:`mail-entry`,onClick:i[5]||=e=>j.value=!j.value},[i[18]||=f(`img`,{src:`/provider-logos/gmail.svg`,alt:``,width:`20`,height:`20`},null,-1),l(s(j.value?`收起邮箱`:`打开 Composio Gmail 邮箱`),1),b(C,{name:j.value?`chevron-down`:`chevron-right`,size:17},null,8,[`name`])])):g(``,!0)]),j.value?(n(),m(ct,{key:3,source:`composio`,accounts:d.value.filter(e=>e.status===`ACTIVE`)},null,8,[`accounts`])):g(``,!0)]))}}),[[`__scopeId`,`data-v-a0eb0c09`]]),bn={class:`bot-plugins`,"aria-label":`Bot 插件管理`},xn={class:`intro`},Sn={class:`plugin-tabs`,role:`tablist`,"aria-label":`插件类型`},Cn=[`aria-selected`],wn=[`aria-selected`],Tn=[`aria-selected`],En=[`aria-selected`],Dn=[`aria-selected`],On={key:1},kn={key:3},An={key:5},jn={key:0,class:`plugin-notice`},Mn={key:0,class:`plugin-error`,role:`alert`},Nn=[`disabled`],Pn={key:1,class:`plugin-notice`,role:`status`},Fn={key:2,role:`status`},In={key:3,class:`connection-settings`},Ln={class:`hint`},Rn={key:0,class:`hint`},zn=[`disabled`],Bn=[`disabled`],Vn={key:2,class:`hint`},Hn={key:4,class:`connection-settings`,"aria-label":`应用授权进度`},Un={role:`status`},Wn={key:0,class:`plugin-error`},Gn={key:0,class:`hint`},Kn=[`href`],qn=[`disabled`],Jn={class:`plugin-toolbar`},Yn={class:`view-tabs`,role:`tablist`,"aria-label":`应用列表`},Xn=[`aria-selected`],Zn=[`aria-selected`],Qn=[`disabled`],$n={class:`plugin-search`},er={class:`app-grid`},tr={class:`card-heading`},nr={class:`hint`},rr={class:`app-account`},ir=[`disabled`,`aria-label`,`onClick`],ar={key:0,class:`hint`},or=[`onSubmit`],sr={class:`card-actions`},cr=[`disabled`],lr={key:2,class:`card-actions`},ur=[`disabled`,`onClick`],dr=[`disabled`,`onClick`],fr=[`onSubmit`],pr={class:`card-actions`},mr=[`disabled`,`onClick`],hr={key:6,class:`plugin-empty`},gr=`/api/app/admin/hermes/connectors`,_r=v(d({__name:`BotPluginsPanel`,emits:[`dirty-change`],setup(t,{emit:c}){let d=c,v=p(`local`),x=p(`marketplace`),w=p(!1),D=p(),A=p([]),P=p([]),F=p(!0),I=p(!1),L=p(``),R=p(``),z=p(``),B=p(``),V=p(``),H=p(),U=p(),W=p(40),G=p(``),K=p(``);i([z,x],()=>{W.value=40}),i([V,G],e=>d(`dirty-change`,e.some(Boolean)));let q=!1,ee=0,J,Y=(e,t,n)=>S(gr+e,{method:t,...n===void 0?{}:{body:n}}),X=e=>P.value.filter(t=>t.connector===e),Z=y(()=>{let e=new Map(A.value.map(e=>[e.slug,e]));for(let t of P.value)e.has(t.connector)||e.set(t.connector,{slug:t.connector,name:t.connector,description:``,category:``});let t=z.value.trim().toLowerCase();return[...e.values()].filter(e=>(x.value!==`connected`||X(e.slug).length)&&`${e.name} ${e.slug} ${e.description}`.toLowerCase().includes(t))}),te=e=>({active:`已连接`,pending:`待授权`,failed:`连接失败`,expired:`已过期`,revoked:`已撤销`,inactive:`未启用`})[e]??e,ne=y(()=>({pending:`等待完成授权`,complete:`连接已完成`,failed:`连接失败`,cancelled:`已取消授权`,expired:`授权已过期`})[U.value?.status??`pending`]);function re(e){try{let t=new URL(e??``);return t.protocol===`https:`&&!t.username&&!t.password?t.href:``}catch{return``}}async function Q(){let e=++ee,t=await Promise.allSettled([S(`/api/app/admin/hermes/connectors/status`),S(`/api/app/admin/hermes/connectors/catalog`),S(`/api/app/admin/hermes/connectors/accounts`)]);if(q||e!==ee)return;let[n,r,i]=t;n.status===`fulfilled`&&(D.value=n.value),r.status===`fulfilled`&&(A.value=r.value.connectors),i.status===`fulfilled`&&(P.value=i.value.accounts),L.value=t.filter(e=>e.status===`rejected`).map(e=>e.reason instanceof Error?e.reason.message:`读取失败,请重试`).join(`;`),F.value=!1}async function $(e){if(!I.value){I.value=!0,L.value=``,R.value=``;try{await e(),q||await Q()}catch(e){q||(L.value=e instanceof Error?e.message:`操作失败,请重试`)}finally{I.value=!1}}}function ie(){if(clearTimeout(J),!(q||U.value?.status!==`pending`)){if(Date.now()>U.value.deadlineAt){U.value={...U.value,status:`expired`};return}J=setTimeout(async()=>{let e=U.value?.id;if(!(!e||q)){try{let t=await S(`${gr}/operations/${encodeURIComponent(e)}`);if(q||U.value?.id!==e)return;U.value=t,t.status===`complete`&&(R.value=`应用已连接,所有 Bot 均可使用。`,await Q())}catch(e){q||(L.value=e instanceof Error?e.message:`暂时无法刷新授权状态`)}ie()}},2500)}}async function ae(e,t){if(I.value||U.value?.status===`pending`)return;if(!t&&X(e.slug).length&&G.value!==e.slug){G.value=e.slug,K.value=``;return}let n=!t&&G.value===e.slug?K.value.trim():void 0;if(n!==void 0&&!/^[a-z0-9][a-z0-9-]{0,31}$/.test(n)){L.value=`新账号别名需为 1–32 位小写字母、数字或连字符,以字母或数字开头。`;return}if(n&&X(e.slug).some(e=>e.alias===n)){L.value=`该应用已有同名账号,请换一个别名。`;return}let r=window.open(`about:blank`,`_blank`);r&&(r.opener=null),await $(async()=>{try{let i={connector:e.slug,...n?{alias:n}:{},...t?{reconnect:!0,connectionId:t.id}:{}},a=await Y(`/operations`,`POST`,i);if(q){r?.close();return}U.value=a,G.value=``,K.value=``;let o=re(a.targets.find(e=>e.connectUrl)?.connectUrl);r&&o?r.location.href=o:r?.close(),R.value=`请在浏览器完成授权。授权状态会自动刷新。`,ie()}catch(e){throw r?.close(),e}})}async function oe(){await $(async()=>{U.value&&=await Y(`/operations/${encodeURIComponent(U.value.id)}`,`DELETE`),clearTimeout(J)})}async function se(e){window.confirm(`断开这个应用账号?所有 Bot 将失去此账号的访问权限。`)&&await $(async()=>{await Y(`/accounts/${encodeURIComponent(e.id)}`,`DELETE`)})}async function ce(e){await $(async()=>{if(!/^[a-z0-9][a-z0-9-]{0,31}$/.test(B.value.trim()))throw Error(`别名需为 1–32 位小写字母、数字或连字符,以字母或数字开头。`);await Y(`/accounts/${encodeURIComponent(e.id)}`,`PATCH`,{alias:B.value.trim()}),V.value=``,B.value=``})}async function le(){await $(async()=>{let e=(await M.oauth()).providers.find(e=>e.id===`nous`);if(!e)throw Error(`Nous 登录暂不可用,请检查主机版本。`);H.value=e})}return o(async()=>{try{let e=await S(`/api/app/bootstrap`);w.value=e.user?.role===`admin`}catch(e){L.value=e instanceof Error?e.message:`无法读取管理权限`}q||(w.value?await Q():F.value=!1)}),e(()=>{q=!0,ee++,clearTimeout(J)}),(e,t)=>(n(),h(`section`,bn,[f(`p`,xn,[b(C,{name:`link`,size:14}),t[16]||=l(`连接的应用由这台服务器的所有 Bot 共用。`,-1)]),f(`div`,Sn,[f(`button`,{type:`button`,role:`tab`,"aria-selected":v.value===`local`,onClick:t[0]||=e=>v.value=`local`},[b(C,{name:`monitor`,size:16}),t[17]||=l(`本地应用`,-1)],8,Cn),f(`button`,{type:`button`,role:`tab`,"aria-selected":v.value===`native`,onClick:t[1]||=e=>v.value=`native`},[b(C,{name:`artifacts`,size:16}),t[18]||=l(`本地插件`,-1)],8,wn),f(`button`,{type:`button`,role:`tab`,"aria-selected":v.value===`composio`,onClick:t[2]||=e=>v.value=`composio`},[b(C,{name:`link`,size:16}),t[19]||=l(`Composio`,-1)],8,Tn),f(`button`,{type:`button`,role:`tab`,"aria-selected":v.value===`apps`,onClick:t[3]||=e=>v.value=`apps`},[b(C,{name:`link`,size:17}),t[20]||=l(`Nous 应用`,-1)],8,En),f(`button`,{type:`button`,role:`tab`,"aria-selected":v.value===`mcp`,onClick:t[4]||=e=>v.value=`mcp`},[b(C,{name:`tools`,size:17}),t[21]||=l(`MCP 服务`,-1)],8,Dn)]),v.value===`native`&&w.value?(n(),m(fe,{key:0})):v.value===`native`?(n(),h(`p`,On,`本地插件由管理员管理。`)):v.value===`composio`&&w.value?(n(),m(yn,{key:2})):v.value===`composio`?(n(),h(`p`,kn,`Composio 连接由管理员管理。`)):v.value===`local`&&w.value?(n(),m(Gt,{key:4})):v.value===`local`?(n(),h(`p`,An,`本地连接由管理员管理。`)):v.value===`mcp`?(n(),m(O,{key:6,"can-manage":w.value,onDirtyChange:t[5]||=e=>d(`dirty-change`,e)},null,8,[`can-manage`])):(n(),h(u,{key:7},[!F.value&&!w.value?(n(),h(`p`,jn,`应用连接由管理员管理。`)):(n(),h(u,{key:1},[L.value?(n(),h(`p`,Mn,[l(s(L.value)+` `,1),f(`button`,{type:`button`,disabled:I.value,onClick:Q},`重试`,8,Nn)])):g(``,!0),R.value?(n(),h(`p`,Pn,s(R.value),1)):g(``,!0),F.value?(n(),h(`p`,Fn,`正在读取应用…`)):(n(),h(`div`,In,[D.value?.authenticated?(n(),h(u,{key:0},[f(`p`,Ln,s(D.value.accountLabel||`Nous 账号已登录`),1),D.value.available?g(``,!0):(n(),h(`p`,Rn,s(D.value.reason===`disabled`||D.value.reason===`not_enabled`?`应用连接服务尚未启用,请检查主机设置后刷新。`:`应用连接服务暂不可用,请刷新或检查主机设置。`),1)),f(`button`,{disabled:I.value,onClick:le},`重新登录 Nous`,8,zn)],64)):D.value?.reason===`needs_auth`||D.value?.available&&!D.value.authenticated?(n(),h(u,{key:1},[t[22]||=f(`p`,null,`登录 Nous 后即可连接应用。登录只用于应用授权,当前主模型保持不变。`,-1),f(`button`,{disabled:I.value,onClick:le},`登录 Nous`,8,Bn)],64)):D.value?.available?g(``,!0):(n(),h(`p`,Vn,s(D.value?.reason===`disabled`||D.value?.reason===`not_enabled`?`应用连接服务尚未启用,请检查主机设置后刷新。`:`应用连接服务暂不可用,请刷新或检查主机设置。`),1))])),U.value?(n(),h(`section`,Hn,[f(`p`,Un,s(ne.value),1),U.value.error?(n(),h(`p`,Wn,s(U.value.error),1)):g(``,!0),(n(!0),h(u,null,a(U.value.targets,e=>(n(),h(`div`,{key:e.connector},[e.detail?(n(),h(`p`,Gn,s(e.detail),1)):g(``,!0),U.value.status===`pending`&&re(e.connectUrl)?(n(),h(`a`,{key:1,href:re(e.connectUrl),target:`_blank`,rel:`noopener noreferrer`},[t[23]||=l(`继续授权 `,-1),b(C,{name:`external`,size:13})],8,Kn)):g(``,!0)]))),128)),U.value.status===`pending`?(n(),h(`button`,{key:1,disabled:I.value,onClick:oe},`取消授权`,8,qn)):g(``,!0)])):g(``,!0),f(`div`,Jn,[f(`div`,Yn,[f(`button`,{role:`tab`,"aria-selected":x.value===`marketplace`,onClick:t[6]||=e=>x.value=`marketplace`},`应用目录`,8,Xn),f(`button`,{role:`tab`,"aria-selected":x.value===`connected`,onClick:t[7]||=e=>x.value=`connected`},`已连接 `+s(P.value.length||``),9,Zn)]),f(`button`,{disabled:I.value||F.value,"aria-label":`刷新应用连接`,onClick:Q},[b(C,{name:`refresh`,size:17})],8,Qn)]),f(`label`,$n,[b(C,{name:`search`,size:17}),r(f(`input`,{"onUpdate:modelValue":t[8]||=e=>z.value=e,type:`search`,"aria-label":`搜索应用`,placeholder:`搜索应用`},null,512),[[E,z.value]])]),f(`div`,er,[(n(!0),h(u,null,a(Z.value.slice(0,W.value),e=>(n(),h(`article`,{key:e.slug,class:`app-card`},[f(`div`,tr,[b(j,{name:e.name,logo:e.logoUrl,"bundled-logo":_(N)(e.slug)},null,8,[`name`,`logo`,`bundled-logo`]),f(`h4`,null,s(e.name),1)]),f(`p`,nr,s(e.description),1),(n(!0),h(u,null,a(X(e.slug),i=>(n(),h(`div`,{key:i.id,class:`account-block`},[f(`div`,rr,[f(`span`,null,[l(s(i.alias||i.label),1),f(`small`,null,s(te(i.status)),1)]),f(`button`,{class:`danger`,disabled:I.value,"aria-label":`断开 ${e.name} ${i.alias||i.label}`,onClick:e=>se(i)},`断开`,8,ir)]),i.statusReason?(n(),h(`p`,ar,s(i.statusReason),1)):g(``,!0),V.value===i.id?(n(),h(`form`,{key:1,onSubmit:T(e=>ce(i),[`prevent`])},[f(`label`,null,[t[24]||=l(`账号别名`,-1),r(f(`input`,{"onUpdate:modelValue":t[9]||=e=>B.value=e,maxlength:`32`,pattern:`[a-z0-9][a-z0-9-]{0,31}`,required:``,placeholder:`work-mail`},null,512),[[E,B.value]]),t[25]||=f(`small`,{class:`hint`},`1–32 位小写字母、数字或连字符,以字母或数字开头。`,-1)]),f(`div`,sr,[f(`button`,{type:`button`,onClick:t[10]||=e=>V.value=``},`取消`),f(`button`,{disabled:I.value,type:`submit`},`保存别名`,8,cr)])],40,or)):(n(),h(`div`,lr,[f(`button`,{disabled:I.value,onClick:e=>{V.value=i.id,B.value=i.alias||``}},`修改别名`,8,ur),i.active?g(``,!0):(n(),h(`button`,{key:0,disabled:I.value||U.value?.status===`pending`||!D.value?.authenticated,onClick:t=>ae(e,i)},`重新连接`,8,dr))]))]))),128)),G.value===e.slug?(n(),h(`form`,{key:0,onSubmit:T(t=>ae(e),[`prevent`])},[f(`label`,null,[t[26]||=l(`新账号别名`,-1),r(f(`input`,{"onUpdate:modelValue":t[11]||=e=>K.value=e,maxlength:`32`,pattern:`[a-z0-9][a-z0-9-]{0,31}`,required:``,placeholder:`personal-mail`},null,512),[[E,K.value]]),t[27]||=f(`small`,{class:`hint`},`使用不同的别名添加第二个账号:1–32 位小写字母、数字或连字符。`,-1)]),f(`button`,{type:`button`,onClick:t[12]||=e=>{G.value=``,K.value=``}},`取消添加`)],40,fr)):g(``,!0),f(`div`,pr,[f(`button`,{disabled:I.value||!D.value?.authenticated||!D.value?.available||U.value?.status===`pending`,onClick:t=>ae(e)},s(G.value===e.slug?`继续连接`:X(e.slug).length?`添加账号`:`连接`),9,mr)])]))),128))]),Z.value.length>W.value?(n(),h(`button`,{key:5,type:`button`,onClick:t[13]||=e=>W.value+=40},`显示更多应用(`+s(Z.value.length-W.value)+`)`,1)):g(``,!0),!F.value&&!Z.value.length?(n(),h(`p`,hr,s(z.value?`没有匹配的应用。`:x.value===`connected`?`还没有已连接的应用,可前往应用目录添加。`:`应用目录暂为空。`),1)):g(``,!0)],64))],64)),H.value?(n(),m(k,{key:8,provider:H.value,onClose:t[14]||=e=>H.value=void 0,onSuccess:t[15]||=e=>{H.value=void 0,Q()}},null,8,[`provider`])):g(``,!0)]))}}),[[`__scopeId`,`data-v-ed72ee2f`]]),vr=d({__name:`BotPluginsDialog`,emits:[`close`],setup(e,{emit:t}){let r=t,i=p(!1),a=()=>!i.value||window.confirm(`放弃尚未保存的插件更改?`);return(e,t)=>(n(),m(D,{title:`已连接应用`,"before-close":a,onClose:t[1]||=e=>r(`close`)},{default:c(()=>[b(_r,{onDirtyChange:t[0]||=e=>i.value=e})]),_:1}))}});export{vr as default};
|
|
2
|
-
//# sourceMappingURL=BotPluginsDialog-qRw8dCbX.js.map
|