@xopcai/xopc 0.0.19 → 0.0.21
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/dist/extensions/feishu/src/adapters/cli-login.d.ts +8 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js +225 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -0
- package/dist/extensions/feishu/src/adapters/onboard-cli.js +1 -105
- package/dist/extensions/feishu/src/adapters/onboard-cli.js.map +1 -1
- package/dist/extensions/feishu/src/auth/app-registration.d.ts +47 -0
- package/dist/extensions/feishu/src/auth/app-registration.js +122 -0
- package/dist/extensions/feishu/src/auth/app-registration.js.map +1 -0
- package/dist/extensions/feishu/src/plugin.d.ts +2 -0
- package/dist/extensions/feishu/src/plugin.js +2 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.d.ts +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agents-ByiiWRbv.js → agents-MbH57-L9.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-ByiiWRbv.js.map → agents-MbH57-L9.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BpR0gguZ.js → apps-page-3i3DvI7i.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-BpR0gguZ.js.map → apps-page-3i3DvI7i.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js.map +1 -0
- package/dist/gateway/static/root/assets/{cron-page-D6wtd-hq.js → cron-page-Be1h9Yub.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-D6wtd-hq.js.map → cron-page-Be1h9Yub.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-o-QI_XCC.js → cron-utils-CR97EvZS.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-o-QI_XCC.js.map → cron-utils-CR97EvZS.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-D2Td6E_v.js → dist-r_Gy-XJv.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-D2Td6E_v.js.map → dist-r_Gy-XJv.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BIni4Qq4.js → extension-debug-page-QfYEYruq.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-BIni4Qq4.js.map → extension-debug-page-QfYEYruq.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BRLScNkx.js → extension-page-4FW-BmKG.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-BRLScNkx.js.map → extension-page-4FW-BmKG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DjiK9Igx.js → extension-settings-page-E_Wq9LL8.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-DjiK9Igx.js.map → extension-settings-page-E_Wq9LL8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-KGmhufWu.js → index-CcQtNJKo.js} +60 -54
- package/dist/gateway/static/root/assets/{index-KGmhufWu.js.map → index-CcQtNJKo.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-D9Wmfh2f.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-C76F4Y0H.js → logs-page-DFhTU-kG.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-C76F4Y0H.js.map → logs-page-DFhTU-kG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-9jwUqGtS.js → sessions-page-wmnnIj6Z.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-9jwUqGtS.js.map → sessions-page-wmnnIj6Z.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js.map +1 -0
- package/dist/gateway/static/root/assets/{skills-page-BY1cLNEz.js → skills-page-D-fRbJG0.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-BY1cLNEz.js.map → skills-page-D-fRbJG0.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.d.ts +2 -1
- package/dist/src/agent/memory/builtin-memory-store.js +7 -6
- package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
- package/dist/src/agent/prompt/memory/index.d.ts +4 -2
- package/dist/src/agent/prompt/memory/index.js +22 -10
- package/dist/src/agent/prompt/memory/index.js.map +1 -1
- package/dist/src/agent/service.js +1 -1
- package/dist/src/agent/tools/factory.js +9 -2
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +7 -2
- package/dist/src/agent/tools/memory-tool.js +11 -5
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/channels/registry.d.ts +1 -1
- package/dist/src/channels/registry.js +25 -1
- package/dist/src/channels/registry.js.map +1 -1
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/chat-commands/builtins/session.js +1 -1
- package/dist/src/chat-commands/index.js +1 -1
- package/dist/src/chat-commands/processor.js +1 -1
- package/dist/src/cli/commands/channels.js +20 -2
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/gateway/call.d.ts +2 -0
- package/dist/src/cli/commands/gateway/call.js +90 -0
- package/dist/src/cli/commands/gateway/call.js.map +1 -0
- package/dist/src/cli/commands/gateway/health.d.ts +2 -0
- package/dist/src/cli/commands/gateway/health.js +77 -0
- package/dist/src/cli/commands/gateway/health.js.map +1 -0
- package/dist/src/cli/commands/gateway/index.d.ts +3 -0
- package/dist/src/cli/commands/gateway/index.js +4 -1
- package/dist/src/cli/commands/gateway/probe.d.ts +2 -0
- package/dist/src/cli/commands/gateway/probe.js +102 -0
- package/dist/src/cli/commands/gateway/probe.js.map +1 -0
- package/dist/src/cli/commands/gateway/status.d.ts +0 -3
- package/dist/src/cli/commands/gateway/status.js +107 -24
- package/dist/src/cli/commands/gateway/status.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +7 -1
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/update.js +19 -1
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/utils/gateway-client.d.ts +28 -0
- package/dist/src/cli/utils/gateway-client.js +115 -0
- package/dist/src/cli/utils/gateway-client.js.map +1 -0
- package/dist/src/config/paths-state.d.ts +4 -0
- package/dist/src/config/paths-state.js +9 -1
- package/dist/src/config/paths-state.js.map +1 -1
- package/dist/src/config/reload.d.ts +2 -0
- package/dist/src/config/reload.js +9 -1
- package/dist/src/config/reload.js.map +1 -1
- package/dist/src/config/rules.js +12 -2
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/extensions/api.d.ts +6 -1
- package/dist/src/extensions/api.js +52 -1
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +6 -1
- package/dist/src/extensions/loader.js +20 -1
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/normalize-manifest.js +33 -0
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +35 -1
- package/dist/src/extensions/types/manifest.d.ts +14 -0
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -0
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/routes/channels.js +111 -0
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +13 -2
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +81 -0
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +17 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +16 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/status.js +31 -7
- package/dist/src/gateway/hono/routes/status.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.js +118 -15
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/index.js +1 -1
- package/dist/src/gateway/server.js +3 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +23 -0
- package/dist/src/gateway/service.js +107 -0
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/infra/update-check.js +54 -21
- package/dist/src/infra/update-check.js.map +1 -1
- package/dist/src/infra/update-lock.d.ts +13 -0
- package/dist/src/infra/update-lock.js +67 -0
- package/dist/src/infra/update-lock.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +6 -5
- package/dist/src/infra/update-runner.js +93 -13
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.js +37 -11
- package/dist/src/infra/update-startup.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/channels-settings-h3eQwIPi.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-h3eQwIPi.js.map +0 -1
- package/dist/gateway/static/root/assets/index-BQNdJlkw.css +0 -1
- package/dist/gateway/static/root/assets/settings-page-DNG3Zijx.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-DNG3Zijx.js.map +0 -1
|
@@ -1,14 +1,37 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../utils/logger.js";
|
|
1
3
|
import { join } from "node:path";
|
|
2
|
-
import { access } from "node:fs/promises";
|
|
4
|
+
import { access, readdir, unlink } from "node:fs/promises";
|
|
3
5
|
import { spawn } from "node:child_process";
|
|
4
6
|
//#region src/infra/update-runner.ts
|
|
7
|
+
init_logger();
|
|
8
|
+
const log = createLogger("UpdateRunner");
|
|
5
9
|
const AUTO_UPDATE_TIMEOUT_MS = 2700 * 1e3;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
function createLineEmitter(onProgress) {
|
|
11
|
+
let bufOut = "";
|
|
12
|
+
let bufErr = "";
|
|
13
|
+
const flush = (buf, source) => {
|
|
14
|
+
const parts = buf.split("\n");
|
|
15
|
+
const rest = parts.pop() ?? "";
|
|
16
|
+
for (const line of parts) if (line.length) onProgress?.(line, source);
|
|
17
|
+
return rest;
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
pushStdout(chunk) {
|
|
21
|
+
bufOut += chunk;
|
|
22
|
+
bufOut = flush(bufOut, "stdout");
|
|
23
|
+
},
|
|
24
|
+
pushStderr(chunk) {
|
|
25
|
+
bufErr += chunk;
|
|
26
|
+
bufErr = flush(bufErr, "stderr");
|
|
27
|
+
},
|
|
28
|
+
flushEnd() {
|
|
29
|
+
if (bufOut.length) onProgress?.(bufOut, "stdout");
|
|
30
|
+
if (bufErr.length) onProgress?.(bufErr, "stderr");
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function spawnUpdateCommand(params) {
|
|
12
35
|
const timeoutMs = params.timeoutMs ?? AUTO_UPDATE_TIMEOUT_MS;
|
|
13
36
|
const argv = await resolveUpdateCommandArgv([
|
|
14
37
|
"update",
|
|
@@ -32,32 +55,60 @@ async function runAutoUpdateCommand(params) {
|
|
|
32
55
|
});
|
|
33
56
|
let stdout = "";
|
|
34
57
|
let stderr = "";
|
|
58
|
+
let stdoutTruncated = false;
|
|
59
|
+
let stderrTruncated = false;
|
|
60
|
+
const lineEmitter = createLineEmitter(params.onProgress);
|
|
35
61
|
const timeoutId = setTimeout(() => {
|
|
36
62
|
child.kill("SIGTERM");
|
|
37
63
|
}, timeoutMs);
|
|
38
64
|
const finish = (result) => {
|
|
39
65
|
clearTimeout(timeoutId);
|
|
66
|
+
lineEmitter.flushEnd();
|
|
40
67
|
resolve(result);
|
|
41
68
|
};
|
|
42
69
|
child.stdout?.on("data", (chunk) => {
|
|
43
|
-
|
|
44
|
-
|
|
70
|
+
const text = chunk.toString();
|
|
71
|
+
stdout += text;
|
|
72
|
+
lineEmitter.pushStdout(text);
|
|
73
|
+
if (stdout.length > 64e3) {
|
|
74
|
+
if (!stdoutTruncated) {
|
|
75
|
+
log.warn("Update command stdout exceeded 64KB; truncating");
|
|
76
|
+
stdoutTruncated = true;
|
|
77
|
+
}
|
|
78
|
+
stdout = stdout.slice(-32e3);
|
|
79
|
+
}
|
|
45
80
|
});
|
|
46
81
|
child.stderr?.on("data", (chunk) => {
|
|
47
|
-
|
|
48
|
-
|
|
82
|
+
const text = chunk.toString();
|
|
83
|
+
stderr += text;
|
|
84
|
+
lineEmitter.pushStderr(text);
|
|
85
|
+
if (stderr.length > 64e3) {
|
|
86
|
+
if (!stderrTruncated) {
|
|
87
|
+
log.warn("Update command stderr exceeded 64KB; truncating");
|
|
88
|
+
stderrTruncated = true;
|
|
89
|
+
}
|
|
90
|
+
stderr = stderr.slice(-32e3);
|
|
91
|
+
}
|
|
49
92
|
});
|
|
50
93
|
child.on("error", (err) => {
|
|
94
|
+
log.error({ err }, `Update subprocess spawn error: ${err.message}`);
|
|
51
95
|
finish({
|
|
52
96
|
ok: false,
|
|
53
97
|
exitCode: null,
|
|
54
|
-
reason:
|
|
98
|
+
reason: err.message,
|
|
55
99
|
stdout,
|
|
56
100
|
stderr
|
|
57
101
|
});
|
|
58
102
|
});
|
|
59
103
|
child.on("exit", (code, signal) => {
|
|
60
104
|
if (signal === "SIGTERM" || code === 143) {
|
|
105
|
+
log.warn({
|
|
106
|
+
code,
|
|
107
|
+
signal
|
|
108
|
+
}, "Update subprocess timed out; attempting lock file cleanup");
|
|
109
|
+
cleanupNpmLockFiles(params.root).catch((cleanupErr) => {
|
|
110
|
+
log.warn({ err: cleanupErr }, "Failed to clean npm lock files after timeout");
|
|
111
|
+
});
|
|
61
112
|
finish({
|
|
62
113
|
ok: false,
|
|
63
114
|
exitCode: code,
|
|
@@ -77,6 +128,24 @@ async function runAutoUpdateCommand(params) {
|
|
|
77
128
|
});
|
|
78
129
|
});
|
|
79
130
|
}
|
|
131
|
+
async function runAutoUpdateCommand(params) {
|
|
132
|
+
return spawnUpdateCommand(params);
|
|
133
|
+
}
|
|
134
|
+
async function runAutoUpdateCommandWithProgress(params) {
|
|
135
|
+
return spawnUpdateCommand(params);
|
|
136
|
+
}
|
|
137
|
+
async function cleanupNpmLockFiles(root) {
|
|
138
|
+
if (!root) return;
|
|
139
|
+
let entries;
|
|
140
|
+
try {
|
|
141
|
+
entries = await readdir(root);
|
|
142
|
+
} catch {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
for (const entry of entries) if (entry.startsWith(".package-lock")) try {
|
|
146
|
+
await unlink(join(root, entry));
|
|
147
|
+
} catch {}
|
|
148
|
+
}
|
|
80
149
|
/**
|
|
81
150
|
* Resolve the argv array for spawning the update command.
|
|
82
151
|
*
|
|
@@ -104,9 +173,20 @@ async function resolveUpdateCommandArgv(baseArgs, root) {
|
|
|
104
173
|
];
|
|
105
174
|
} catch {}
|
|
106
175
|
}
|
|
176
|
+
log.warn("Falling back to bare `xopc` command — version mismatch possible");
|
|
177
|
+
try {
|
|
178
|
+
const { execSync } = await import("node:child_process");
|
|
179
|
+
const whichResult = execSync(process.platform === "win32" ? "where xopc" : "which xopc", {
|
|
180
|
+
encoding: "utf-8",
|
|
181
|
+
timeout: 3e3
|
|
182
|
+
}).trim();
|
|
183
|
+
if (whichResult) log.info({ resolvedPath: whichResult.split(/\r?\n/)[0]?.trim() }, "Resolved xopc via PATH");
|
|
184
|
+
} catch {
|
|
185
|
+
log.warn("Could not resolve `xopc` in PATH; update command may fail");
|
|
186
|
+
}
|
|
107
187
|
return ["xopc", ...baseArgs];
|
|
108
188
|
}
|
|
109
189
|
//#endregion
|
|
110
|
-
export { runAutoUpdateCommand };
|
|
190
|
+
export { runAutoUpdateCommand, runAutoUpdateCommandWithProgress };
|
|
111
191
|
|
|
112
192
|
//# sourceMappingURL=update-runner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-runner.js","names":[],"sources":["../../../src/infra/update-runner.ts"],"sourcesContent":["// src/infra/update-runner.ts\n\nimport { spawn } from 'node:child_process';\nimport { access } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport type { UpdateChannel } from './update-channels.js';\n\nconst AUTO_UPDATE_TIMEOUT_MS = 45 * 60 * 1000; // 45 minutes\n\nexport type AutoUpdateResult = {\n ok: boolean;\n exitCode: number | null;\n reason?: string;\n stdout?: string;\n stderr?: string;\n};\n\n
|
|
1
|
+
{"version":3,"file":"update-runner.js","names":[],"sources":["../../../src/infra/update-runner.ts"],"sourcesContent":["// src/infra/update-runner.ts\n\nimport { spawn } from 'node:child_process';\nimport { access, readdir, unlink } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { createLogger } from '../utils/logger.js';\n\nimport type { UpdateChannel } from './update-channels.js';\n\nconst log = createLogger('UpdateRunner');\n\nconst AUTO_UPDATE_TIMEOUT_MS = 45 * 60 * 1000; // 45 minutes\n\nexport type AutoUpdateResult = {\n ok: boolean;\n exitCode: number | null;\n reason?: string;\n stdout?: string;\n stderr?: string;\n};\n\ntype SpawnUpdateParams = {\n channel: UpdateChannel;\n root?: string | null;\n timeoutMs?: number;\n onProgress?: (line: string, source: 'stdout' | 'stderr') => void | Promise<void>;\n};\n\nfunction createLineEmitter(\n onProgress?: (line: string, source: 'stdout' | 'stderr') => void | Promise<void>,\n) {\n let bufOut = '';\n let bufErr = '';\n const flush = (buf: string, source: 'stdout' | 'stderr'): string => {\n const parts = buf.split('\\n');\n const rest = parts.pop() ?? '';\n for (const line of parts) {\n if (line.length) void onProgress?.(line, source);\n }\n return rest;\n };\n return {\n pushStdout(chunk: string) {\n bufOut += chunk;\n bufOut = flush(bufOut, 'stdout');\n },\n pushStderr(chunk: string) {\n bufErr += chunk;\n bufErr = flush(bufErr, 'stderr');\n },\n flushEnd() {\n if (bufOut.length) void onProgress?.(bufOut, 'stdout');\n if (bufErr.length) void onProgress?.(bufErr, 'stderr');\n },\n };\n}\n\nasync function spawnUpdateCommand(params: SpawnUpdateParams): Promise<AutoUpdateResult> {\n const timeoutMs = params.timeoutMs ?? AUTO_UPDATE_TIMEOUT_MS;\n const baseArgs = ['update', '--yes', '--channel', params.channel, '--json'];\n const argv = await resolveUpdateCommandArgv(baseArgs, params.root ?? null);\n\n return new Promise<AutoUpdateResult>((resolve) => {\n const child = spawn(argv[0], argv.slice(1), {\n env: {\n ...process.env,\n XOPC_AUTO_UPDATE: '1',\n },\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n let stdout = '';\n let stderr = '';\n let stdoutTruncated = false;\n let stderrTruncated = false;\n\n const lineEmitter = createLineEmitter(params.onProgress);\n\n const timeoutId = setTimeout(() => {\n child.kill('SIGTERM');\n }, timeoutMs);\n\n const finish = (result: AutoUpdateResult) => {\n clearTimeout(timeoutId);\n lineEmitter.flushEnd();\n resolve(result);\n };\n\n child.stdout?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n stdout += text;\n lineEmitter.pushStdout(text);\n if (stdout.length > 64_000) {\n if (!stdoutTruncated) {\n log.warn('Update command stdout exceeded 64KB; truncating');\n stdoutTruncated = true;\n }\n stdout = stdout.slice(-32_000);\n }\n });\n child.stderr?.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n stderr += text;\n lineEmitter.pushStderr(text);\n if (stderr.length > 64_000) {\n if (!stderrTruncated) {\n log.warn('Update command stderr exceeded 64KB; truncating');\n stderrTruncated = true;\n }\n stderr = stderr.slice(-32_000);\n }\n });\n\n child.on('error', (err) => {\n log.error({ err }, `Update subprocess spawn error: ${err.message}`);\n finish({ ok: false, exitCode: null, reason: err.message, stdout, stderr });\n });\n\n child.on('exit', (code, signal) => {\n if (signal === 'SIGTERM' || code === 143) {\n log.warn({ code, signal }, 'Update subprocess timed out; attempting lock file cleanup');\n void cleanupNpmLockFiles(params.root).catch((cleanupErr) => {\n log.warn({ err: cleanupErr }, 'Failed to clean npm lock files after timeout');\n });\n finish({ ok: false, exitCode: code, reason: 'timeout', stdout, stderr });\n return;\n }\n finish({\n ok: code === 0,\n exitCode: code,\n reason: code === 0 ? undefined : 'non-zero-exit',\n stdout,\n stderr,\n });\n });\n });\n}\n\nexport async function runAutoUpdateCommand(params: {\n channel: UpdateChannel;\n root?: string | null;\n timeoutMs?: number;\n}): Promise<AutoUpdateResult> {\n return spawnUpdateCommand(params);\n}\n\nexport async function runAutoUpdateCommandWithProgress(params: {\n channel: UpdateChannel;\n root?: string | null;\n timeoutMs?: number;\n onProgress?: (line: string, source: 'stdout' | 'stderr') => void | Promise<void>;\n}): Promise<AutoUpdateResult> {\n return spawnUpdateCommand(params);\n}\n\nasync function cleanupNpmLockFiles(root: string | null | undefined): Promise<void> {\n if (!root) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.startsWith('.package-lock')) {\n try {\n await unlink(join(root, entry));\n } catch {\n // best-effort\n }\n }\n }\n}\n\n/**\n * Resolve the argv array for spawning the update command.\n *\n * Priority:\n * 1. process.execPath + process.argv[1] (current runtime + entry point)\n * 2. process.execPath + known dist entry points in root\n * 3. Fallback to bare `xopc` (assumes global install)\n */\nasync function resolveUpdateCommandArgv(\n baseArgs: string[],\n root: string | null,\n): Promise<string[]> {\n const execPath = process.execPath?.trim();\n const argv1 = process.argv[1]?.trim();\n\n if (execPath && argv1) {\n return [execPath, argv1, ...baseArgs];\n }\n\n if (execPath && root) {\n const candidates = [join(root, 'dist/src/cli/index.js'), join(root, 'dist/index.js')];\n for (const candidate of candidates) {\n try {\n await access(candidate);\n return [execPath, candidate, ...baseArgs];\n } catch {\n // try next\n }\n }\n }\n\n log.warn('Falling back to bare `xopc` command — version mismatch possible');\n try {\n const { execSync } = await import('node:child_process');\n const cmd = process.platform === 'win32' ? 'where xopc' : 'which xopc';\n const whichResult = execSync(cmd, { encoding: 'utf-8', timeout: 3000 }).trim();\n if (whichResult) {\n log.info({ resolvedPath: whichResult.split(/\\r?\\n/)[0]?.trim() }, 'Resolved xopc via PATH');\n }\n } catch {\n log.warn('Could not resolve `xopc` in PATH; update command may fail');\n }\n\n return ['xopc', ...baseArgs];\n}\n"],"mappings":"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"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
|
|
2
|
-
import {
|
|
2
|
+
import { init_paths_state, resolveUpdateCheckStatePath } from "../config/paths-state.js";
|
|
3
3
|
import { createLogger } from "../utils/logger/index.js";
|
|
4
4
|
import { init_logger } from "../utils/logger.js";
|
|
5
|
-
import {
|
|
5
|
+
import { acquireUpdateLock } from "./update-lock.js";
|
|
6
6
|
import { normalizeUpdateChannel } from "./update-channels.js";
|
|
7
7
|
import { compareSemver, detectInstallKind, resolveNpmChannelTag, resolvePackageRoot } from "./update-check.js";
|
|
8
|
-
import { dirname
|
|
9
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
10
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
10
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
11
11
|
//#region src/infra/update-startup.ts
|
|
12
|
-
|
|
12
|
+
init_paths_state();
|
|
13
13
|
init_package_version();
|
|
14
14
|
init_logger();
|
|
15
15
|
const log = createLogger("UpdateCheck");
|
|
16
|
-
const UPDATE_CHECK_FILENAME = "update-check.json";
|
|
17
16
|
const CHECK_INTERVAL_MS = 1440 * 60 * 1e3;
|
|
18
17
|
const ONE_HOUR_MS = 3600 * 1e3;
|
|
19
18
|
let updateAvailableCache = null;
|
|
@@ -25,14 +24,31 @@ async function readState(statePath) {
|
|
|
25
24
|
try {
|
|
26
25
|
const raw = await readFile(statePath, "utf-8");
|
|
27
26
|
const parsed = JSON.parse(raw);
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
if (!parsed || typeof parsed !== "object") {
|
|
28
|
+
log.warn({ statePath }, "Update check state file contains non-object; resetting");
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
return parsed;
|
|
32
|
+
} catch (err) {
|
|
33
|
+
if (err.code !== "ENOENT") log.warn({
|
|
34
|
+
err,
|
|
35
|
+
statePath
|
|
36
|
+
}, "Failed to read update check state; resetting");
|
|
30
37
|
return {};
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
async function writeState(statePath, state) {
|
|
34
41
|
await mkdir(dirname(statePath), { recursive: true });
|
|
35
|
-
|
|
42
|
+
const tmpPath = `${statePath}.${randomBytes(4).toString("hex")}.tmp`;
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8");
|
|
45
|
+
await rename(tmpPath, statePath);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
try {
|
|
48
|
+
await unlink(tmpPath);
|
|
49
|
+
} catch {}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
36
52
|
}
|
|
37
53
|
function resolveCheckIntervalMs(config) {
|
|
38
54
|
const auto = config.update?.auto;
|
|
@@ -59,7 +75,7 @@ async function runGatewayUpdateCheck(params) {
|
|
|
59
75
|
const autoEnabled = config.update?.auto?.enabled ?? false;
|
|
60
76
|
const shouldCheckHints = config.update?.checkOnStart !== false;
|
|
61
77
|
if (!force && !shouldCheckHints && !autoEnabled) return;
|
|
62
|
-
const statePath =
|
|
78
|
+
const statePath = resolveUpdateCheckStatePath();
|
|
63
79
|
const state = await readState(statePath);
|
|
64
80
|
const now = Date.now();
|
|
65
81
|
const lastCheckedAt = state.lastCheckedAt ? Date.parse(state.lastCheckedAt) : null;
|
|
@@ -184,6 +200,14 @@ async function handleAutoUpdate(params) {
|
|
|
184
200
|
version,
|
|
185
201
|
tag
|
|
186
202
|
}, "Starting auto-update");
|
|
203
|
+
const lock = await acquireUpdateLock("auto");
|
|
204
|
+
if (!lock) {
|
|
205
|
+
log.info({
|
|
206
|
+
version,
|
|
207
|
+
tag
|
|
208
|
+
}, "Auto-update skipped: another update is in progress");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
187
211
|
try {
|
|
188
212
|
const { runAutoUpdateCommand } = await import("./update-runner.js");
|
|
189
213
|
const result = await runAutoUpdateCommand({
|
|
@@ -211,6 +235,8 @@ async function handleAutoUpdate(params) {
|
|
|
211
235
|
channel,
|
|
212
236
|
version
|
|
213
237
|
}, "Auto-update command threw");
|
|
238
|
+
} finally {
|
|
239
|
+
await lock.release();
|
|
214
240
|
}
|
|
215
241
|
}
|
|
216
242
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-startup.js","names":[],"sources":["../../../src/infra/update-startup.ts"],"sourcesContent":["// src/infra/update-startup.ts\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\n\nimport type { Config } from '../config/schema.js';\nimport { resolveStateDir } from '../config/paths.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { createLogger } from '../utils/logger.js';\n\nimport { normalizeUpdateChannel, DEFAULT_PACKAGE_CHANNEL } from './update-channels.js';\nimport {\n compareSemver,\n resolveNpmChannelTag,\n detectInstallKind,\n resolvePackageRoot,\n type InstallKind,\n type UpdateAvailable,\n} from './update-check.js';\n\nconst log = createLogger('UpdateCheck');\n\n// --- State persistence ---\n\nconst UPDATE_CHECK_FILENAME = 'update-check.json';\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours\nconst ONE_HOUR_MS = 60 * 60 * 1000;\n\ntype UpdateCheckState = {\n /** `package.json` version at the last successful registry check (used to bypass 24h throttle when you bump the local version). */\n lastCheckPackageVersion?: string;\n lastCheckedAt?: string;\n lastAvailableVersion?: string;\n lastAvailableTag?: string;\n lastNotifiedVersion?: string;\n lastNotifiedTag?: string;\n autoInstallId?: string;\n autoFirstSeenVersion?: string;\n autoFirstSeenTag?: string;\n autoFirstSeenAt?: string;\n autoLastAttemptVersion?: string;\n autoLastAttemptAt?: string;\n autoLastSuccessVersion?: string;\n autoLastSuccessAt?: string;\n};\n\n// --- In-memory cache ---\n\nlet updateAvailableCache: UpdateAvailable | null = null;\n\n/** Get the cached update-available state (populated after startup check). */\nexport function getUpdateAvailable(): UpdateAvailable | null {\n return updateAvailableCache;\n}\n\n// --- Core logic ---\n\nasync function readState(statePath: string): Promise<UpdateCheckState> {\n try {\n const raw = await readFile(statePath, 'utf-8');\n const parsed = JSON.parse(raw) as UpdateCheckState;\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nasync function writeState(statePath: string, state: UpdateCheckState): Promise<void> {\n await mkdir(dirname(statePath), { recursive: true });\n await writeFile(statePath, JSON.stringify(state, null, 2), 'utf-8');\n}\n\nfunction resolveCheckIntervalMs(config: Config): number {\n const auto = config.update?.auto;\n if (!auto?.enabled) return CHECK_INTERVAL_MS;\n\n const channel = normalizeUpdateChannel(config.update?.channel) ?? DEFAULT_PACKAGE_CHANNEL;\n if (channel === 'beta') {\n const hours = auto.betaCheckIntervalHours ?? 1;\n return Math.max(ONE_HOUR_MS / 4, Math.floor(hours * ONE_HOUR_MS));\n }\n return ONE_HOUR_MS;\n}\n\n/**\n * Compute a deterministic delay for stable auto-update rollout,\n * based on a per-installation hash to spread updates over time.\n */\nfunction resolveStableJitterMs(\n installId: string,\n version: string,\n tag: string,\n jitterWindowMs: number,\n): number {\n if (jitterWindowMs <= 0) return 0;\n const hash = createHash('sha256').update(`${installId}:${version}:${tag}`).digest();\n const bucket = hash.readUInt32BE(0);\n return bucket % (Math.floor(jitterWindowMs) + 1);\n}\n\n/**\n * Main startup update check. Called once when the gateway starts (or on demand).\n */\nexport async function runGatewayUpdateCheck(params: {\n config: Config;\n onUpdateAvailableChange?: (update: UpdateAvailable | null) => void;\n /** When true, bypass checkOnStart/auto-disabled early exit and throttle (for POST /api/update/check). */\n force?: boolean;\n}): Promise<void> {\n const { config, force } = params;\n\n const autoEnabled = config.update?.auto?.enabled ?? false;\n const shouldCheckHints = config.update?.checkOnStart !== false;\n if (!force && !shouldCheckHints && !autoEnabled) return;\n\n const stateDir = resolveStateDir();\n const statePath = join(stateDir, UPDATE_CHECK_FILENAME);\n const state = await readState(statePath);\n const now = Date.now();\n\n // Hydrate from persisted state if within throttle window\n const lastCheckedAt = state.lastCheckedAt ? Date.parse(state.lastCheckedAt) : null;\n if (state.lastAvailableVersion && (shouldCheckHints || force)) {\n const comparison = compareSemver(PACKAGE_VERSION, state.lastAvailableVersion);\n if (comparison !== null && comparison < 0) {\n const cached: UpdateAvailable = {\n currentVersion: PACKAGE_VERSION,\n latestVersion: state.lastAvailableVersion,\n channel: state.lastAvailableTag ?? 'latest',\n };\n updateAvailableCache = cached;\n params.onUpdateAvailableChange?.(cached);\n }\n }\n\n const checkIntervalMs = resolveCheckIntervalMs(config);\n // Re-check npm when the local package version changed (e.g. after editing package.json) even within 24h.\n const shouldBypassThrottleForVersion =\n state.lastCheckPackageVersion === undefined || state.lastCheckPackageVersion !== PACKAGE_VERSION;\n if (\n !force &&\n !shouldBypassThrottleForVersion &&\n lastCheckedAt &&\n Number.isFinite(lastCheckedAt) &&\n now - lastCheckedAt < checkIntervalMs\n ) {\n return; // Within throttle window\n }\n\n // Install kind: auto-install only for npm global installs, but we still query npm in git\n // so the Web UI / CLI can show \"newer on registry\" and the top reminder bar.\n const root = await resolvePackageRoot();\n let installKind: InstallKind = 'unknown';\n if (root) {\n installKind = await detectInstallKind(root);\n if (installKind === 'git') {\n log.info('Update check: git checkout (hint-only; use git pull to update, no auto npm install)');\n }\n }\n\n // Query npm registry\n const channel = normalizeUpdateChannel(config.update?.channel) ?? DEFAULT_PACKAGE_CHANNEL;\n const resolved = await resolveNpmChannelTag({ channel, timeoutMs: 2500 });\n\n const nextState: UpdateCheckState = {\n ...state,\n lastCheckedAt: new Date(now).toISOString(),\n };\n\n if (!resolved.version) {\n nextState.lastCheckPackageVersion = PACKAGE_VERSION;\n await writeState(statePath, nextState);\n return;\n }\n\n const comparison = compareSemver(PACKAGE_VERSION, resolved.version);\n if (comparison !== null && comparison < 0) {\n // Update available\n const updateInfo: UpdateAvailable = {\n currentVersion: PACKAGE_VERSION,\n latestVersion: resolved.version,\n channel: resolved.tag,\n };\n\n if (shouldCheckHints || force) {\n updateAvailableCache = updateInfo;\n params.onUpdateAvailableChange?.(updateInfo);\n }\n\n nextState.lastAvailableVersion = resolved.version;\n nextState.lastAvailableTag = resolved.tag;\n\n // Log notification (once per version)\n const shouldNotify =\n state.lastNotifiedVersion !== resolved.version || state.lastNotifiedTag !== resolved.tag;\n if ((shouldCheckHints || force) && shouldNotify) {\n log.info(\n { currentVersion: PACKAGE_VERSION, latestVersion: resolved.version, tag: resolved.tag },\n `Update available (${resolved.tag}): v${resolved.version} (current v${PACKAGE_VERSION}). Run: xopc update`,\n );\n nextState.lastNotifiedVersion = resolved.version;\n nextState.lastNotifiedTag = resolved.tag;\n }\n\n // Auto-update logic (never from a git worktree)\n if (\n autoEnabled &&\n (channel === 'stable' || channel === 'beta') &&\n installKind !== 'git'\n ) {\n await handleAutoUpdate({\n channel,\n version: resolved.version,\n tag: resolved.tag,\n state,\n nextState,\n now,\n root,\n config,\n });\n }\n } else {\n // Current version is up to date or newer\n delete nextState.lastAvailableVersion;\n delete nextState.lastAvailableTag;\n updateAvailableCache = null;\n params.onUpdateAvailableChange?.(null);\n }\n\n nextState.lastCheckPackageVersion = PACKAGE_VERSION;\n await writeState(statePath, nextState);\n}\n\nasync function handleAutoUpdate(params: {\n channel: 'stable' | 'beta';\n version: string;\n tag: string;\n state: UpdateCheckState;\n nextState: UpdateCheckState;\n now: number;\n root: string | null;\n config: Config;\n}): Promise<void> {\n const { channel, version, tag, state, nextState, now, root, config } = params;\n const auto = config.update?.auto;\n if (!auto) return;\n\n const stableDelayHours = auto.stableDelayHours ?? 6;\n const stableJitterHours = auto.stableJitterHours ?? 12;\n const betaCheckIntervalHours = auto.betaCheckIntervalHours ?? 1;\n\n // Rate limit: don't re-attempt same version within interval\n const attemptIntervalMs =\n channel === 'beta'\n ? Math.max(ONE_HOUR_MS / 4, Math.floor(betaCheckIntervalHours * ONE_HOUR_MS))\n : ONE_HOUR_MS;\n const lastAttemptAt = state.autoLastAttemptAt ? Date.parse(state.autoLastAttemptAt) : null;\n const recentAttempt =\n state.autoLastAttemptVersion === version &&\n lastAttemptAt !== null &&\n Number.isFinite(lastAttemptAt) &&\n now - lastAttemptAt < attemptIntervalMs;\n\n if (recentAttempt) {\n log.info({ version, tag }, 'Auto-update deferred: recent attempt exists');\n return;\n }\n\n // Stable rollout delay + jitter\n if (channel === 'stable') {\n if (!nextState.autoInstallId) {\n nextState.autoInstallId = state.autoInstallId?.trim() || randomUUID();\n }\n // Track first-seen time for this version\n if (state.autoFirstSeenVersion !== version || state.autoFirstSeenTag !== tag) {\n nextState.autoFirstSeenVersion = version;\n nextState.autoFirstSeenTag = tag;\n nextState.autoFirstSeenAt = new Date(now).toISOString();\n } else {\n nextState.autoFirstSeenAt = state.autoFirstSeenAt;\n }\n\n const firstSeenMs = nextState.autoFirstSeenAt ? Date.parse(nextState.autoFirstSeenAt) : now;\n const baseDelayMs = Math.max(0, stableDelayHours) * ONE_HOUR_MS;\n const jitterWindowMs = Math.max(0, stableJitterHours) * ONE_HOUR_MS;\n const jitterMs = resolveStableJitterMs(nextState.autoInstallId, version, tag, jitterWindowMs);\n const applyAfterMs = firstSeenMs + baseDelayMs + jitterMs;\n\n if (now < applyAfterMs) {\n log.info(\n { version, tag, applyAfter: new Date(applyAfterMs).toISOString() },\n 'Auto-update deferred: stable rollout window not yet due',\n );\n return;\n }\n }\n\n // Execute auto-update\n nextState.autoLastAttemptVersion = version;\n nextState.autoLastAttemptAt = new Date(now).toISOString();\n\n log.info({ channel, version, tag }, 'Starting auto-update');\n\n try {\n const { runAutoUpdateCommand } = await import('./update-runner.js');\n const result = await runAutoUpdateCommand({ channel, root });\n if (result.ok) {\n nextState.autoLastSuccessVersion = version;\n nextState.autoLastSuccessAt = new Date(now).toISOString();\n log.info({ channel, version, tag }, 'Auto-update applied successfully');\n } else {\n log.warn(\n { channel, version, tag, exitCode: result.exitCode, reason: result.reason },\n `Auto-update attempt failed: ${result.reason ?? `exit ${result.exitCode}`}`,\n );\n }\n } catch (err) {\n log.error({ err, channel, version }, 'Auto-update command threw');\n }\n}\n\n/**\n * Schedule periodic update checks. Returns a cleanup function to stop the timer.\n */\nexport function scheduleGatewayUpdateCheck(params: {\n config: Config;\n onUpdateAvailableChange?: (update: UpdateAvailable | null) => void;\n}): () => void {\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const tick = async () => {\n if (stopped) return;\n try {\n await runGatewayUpdateCheck(params);\n } catch (err) {\n log.warn({ err }, 'Periodic update check failed');\n }\n if (!stopped) {\n const intervalMs = resolveCheckIntervalMs(params.config);\n timer = setTimeout(() => void tick(), intervalMs);\n }\n };\n\n // Initial check after a short delay (don't block startup)\n timer = setTimeout(() => void tick(), 5000);\n\n return () => {\n stopped = true;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"update-startup.js","names":[],"sources":["../../../src/infra/update-startup.ts"],"sourcesContent":["// src/infra/update-startup.ts\n\nimport { createHash, randomBytes, randomUUID } from 'node:crypto';\nimport { readFile, writeFile, mkdir, rename, unlink } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport type { Config } from '../config/schema.js';\nimport { resolveUpdateCheckStatePath } from '../config/paths-state.js';\nimport { acquireUpdateLock } from './update-lock.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { createLogger } from '../utils/logger.js';\n\nimport { normalizeUpdateChannel, DEFAULT_PACKAGE_CHANNEL } from './update-channels.js';\nimport {\n compareSemver,\n resolveNpmChannelTag,\n detectInstallKind,\n resolvePackageRoot,\n type InstallKind,\n type UpdateAvailable,\n} from './update-check.js';\n\nconst log = createLogger('UpdateCheck');\n\n// --- State persistence ---\n\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours\nconst ONE_HOUR_MS = 60 * 60 * 1000;\n\ntype UpdateCheckState = {\n /** `package.json` version at the last successful registry check (used to bypass 24h throttle when you bump the local version). */\n lastCheckPackageVersion?: string;\n lastCheckedAt?: string;\n lastAvailableVersion?: string;\n lastAvailableTag?: string;\n lastNotifiedVersion?: string;\n lastNotifiedTag?: string;\n autoInstallId?: string;\n autoFirstSeenVersion?: string;\n autoFirstSeenTag?: string;\n autoFirstSeenAt?: string;\n autoLastAttemptVersion?: string;\n autoLastAttemptAt?: string;\n autoLastSuccessVersion?: string;\n autoLastSuccessAt?: string;\n};\n\n// --- In-memory cache ---\n\nlet updateAvailableCache: UpdateAvailable | null = null;\n\n/** Get the cached update-available state (populated after startup check). */\nexport function getUpdateAvailable(): UpdateAvailable | null {\n return updateAvailableCache;\n}\n\n// --- Core logic ---\n\nasync function readState(statePath: string): Promise<UpdateCheckState> {\n try {\n const raw = await readFile(statePath, 'utf-8');\n const parsed = JSON.parse(raw) as UpdateCheckState;\n if (!parsed || typeof parsed !== 'object') {\n log.warn({ statePath }, 'Update check state file contains non-object; resetting');\n return {};\n }\n return parsed;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n log.warn({ err, statePath }, 'Failed to read update check state; resetting');\n }\n return {};\n }\n}\n\nasync function writeState(statePath: string, state: UpdateCheckState): Promise<void> {\n await mkdir(dirname(statePath), { recursive: true });\n const tmpPath = `${statePath}.${randomBytes(4).toString('hex')}.tmp`;\n try {\n await writeFile(tmpPath, JSON.stringify(state, null, 2), 'utf-8');\n await rename(tmpPath, statePath);\n } catch (err) {\n try {\n await unlink(tmpPath);\n } catch {\n // ignore\n }\n throw err;\n }\n}\n\nfunction resolveCheckIntervalMs(config: Config): number {\n const auto = config.update?.auto;\n if (!auto?.enabled) return CHECK_INTERVAL_MS;\n\n const channel = normalizeUpdateChannel(config.update?.channel) ?? DEFAULT_PACKAGE_CHANNEL;\n if (channel === 'beta') {\n const hours = auto.betaCheckIntervalHours ?? 1;\n return Math.max(ONE_HOUR_MS / 4, Math.floor(hours * ONE_HOUR_MS));\n }\n return ONE_HOUR_MS;\n}\n\n/**\n * Compute a deterministic delay for stable auto-update rollout,\n * based on a per-installation hash to spread updates over time.\n */\nfunction resolveStableJitterMs(\n installId: string,\n version: string,\n tag: string,\n jitterWindowMs: number,\n): number {\n if (jitterWindowMs <= 0) return 0;\n const hash = createHash('sha256').update(`${installId}:${version}:${tag}`).digest();\n const bucket = hash.readUInt32BE(0);\n return bucket % (Math.floor(jitterWindowMs) + 1);\n}\n\n/**\n * Main startup update check. Called once when the gateway starts (or on demand).\n */\nexport async function runGatewayUpdateCheck(params: {\n config: Config;\n onUpdateAvailableChange?: (update: UpdateAvailable | null) => void;\n /** When true, bypass checkOnStart/auto-disabled early exit and throttle (for POST /api/update/check). */\n force?: boolean;\n}): Promise<void> {\n const { config, force } = params;\n\n const autoEnabled = config.update?.auto?.enabled ?? false;\n const shouldCheckHints = config.update?.checkOnStart !== false;\n if (!force && !shouldCheckHints && !autoEnabled) return;\n\n const statePath = resolveUpdateCheckStatePath();\n const state = await readState(statePath);\n const now = Date.now();\n\n // Hydrate from persisted state if within throttle window\n const lastCheckedAt = state.lastCheckedAt ? Date.parse(state.lastCheckedAt) : null;\n if (state.lastAvailableVersion && (shouldCheckHints || force)) {\n const comparison = compareSemver(PACKAGE_VERSION, state.lastAvailableVersion);\n if (comparison !== null && comparison < 0) {\n const cached: UpdateAvailable = {\n currentVersion: PACKAGE_VERSION,\n latestVersion: state.lastAvailableVersion,\n channel: state.lastAvailableTag ?? 'latest',\n };\n updateAvailableCache = cached;\n params.onUpdateAvailableChange?.(cached);\n }\n }\n\n const checkIntervalMs = resolveCheckIntervalMs(config);\n // Re-check npm when the local package version changed (e.g. after editing package.json) even within 24h.\n const shouldBypassThrottleForVersion =\n state.lastCheckPackageVersion === undefined || state.lastCheckPackageVersion !== PACKAGE_VERSION;\n if (\n !force &&\n !shouldBypassThrottleForVersion &&\n lastCheckedAt &&\n Number.isFinite(lastCheckedAt) &&\n now - lastCheckedAt < checkIntervalMs\n ) {\n return; // Within throttle window\n }\n\n // Install kind: auto-install only for npm global installs, but we still query npm in git\n // so the Web UI / CLI can show \"newer on registry\" and the top reminder bar.\n const root = await resolvePackageRoot();\n let installKind: InstallKind = 'unknown';\n if (root) {\n installKind = await detectInstallKind(root);\n if (installKind === 'git') {\n log.info('Update check: git checkout (hint-only; use git pull to update, no auto npm install)');\n }\n }\n\n // Query npm registry\n const channel = normalizeUpdateChannel(config.update?.channel) ?? DEFAULT_PACKAGE_CHANNEL;\n const resolved = await resolveNpmChannelTag({ channel, timeoutMs: 2500 });\n\n const nextState: UpdateCheckState = {\n ...state,\n lastCheckedAt: new Date(now).toISOString(),\n };\n\n if (!resolved.version) {\n nextState.lastCheckPackageVersion = PACKAGE_VERSION;\n await writeState(statePath, nextState);\n return;\n }\n\n const comparison = compareSemver(PACKAGE_VERSION, resolved.version);\n if (comparison !== null && comparison < 0) {\n // Update available\n const updateInfo: UpdateAvailable = {\n currentVersion: PACKAGE_VERSION,\n latestVersion: resolved.version,\n channel: resolved.tag,\n };\n\n if (shouldCheckHints || force) {\n updateAvailableCache = updateInfo;\n params.onUpdateAvailableChange?.(updateInfo);\n }\n\n nextState.lastAvailableVersion = resolved.version;\n nextState.lastAvailableTag = resolved.tag;\n\n // Log notification (once per version)\n const shouldNotify =\n state.lastNotifiedVersion !== resolved.version || state.lastNotifiedTag !== resolved.tag;\n if ((shouldCheckHints || force) && shouldNotify) {\n log.info(\n { currentVersion: PACKAGE_VERSION, latestVersion: resolved.version, tag: resolved.tag },\n `Update available (${resolved.tag}): v${resolved.version} (current v${PACKAGE_VERSION}). Run: xopc update`,\n );\n nextState.lastNotifiedVersion = resolved.version;\n nextState.lastNotifiedTag = resolved.tag;\n }\n\n // Auto-update logic (never from a git worktree)\n if (\n autoEnabled &&\n (channel === 'stable' || channel === 'beta') &&\n installKind !== 'git'\n ) {\n await handleAutoUpdate({\n channel,\n version: resolved.version,\n tag: resolved.tag,\n state,\n nextState,\n now,\n root,\n config,\n });\n }\n } else {\n // Current version is up to date or newer\n delete nextState.lastAvailableVersion;\n delete nextState.lastAvailableTag;\n updateAvailableCache = null;\n params.onUpdateAvailableChange?.(null);\n }\n\n nextState.lastCheckPackageVersion = PACKAGE_VERSION;\n await writeState(statePath, nextState);\n}\n\nasync function handleAutoUpdate(params: {\n channel: 'stable' | 'beta';\n version: string;\n tag: string;\n state: UpdateCheckState;\n nextState: UpdateCheckState;\n now: number;\n root: string | null;\n config: Config;\n}): Promise<void> {\n const { channel, version, tag, state, nextState, now, root, config } = params;\n const auto = config.update?.auto;\n if (!auto) return;\n\n const stableDelayHours = auto.stableDelayHours ?? 6;\n const stableJitterHours = auto.stableJitterHours ?? 12;\n const betaCheckIntervalHours = auto.betaCheckIntervalHours ?? 1;\n\n // Rate limit: don't re-attempt same version within interval\n const attemptIntervalMs =\n channel === 'beta'\n ? Math.max(ONE_HOUR_MS / 4, Math.floor(betaCheckIntervalHours * ONE_HOUR_MS))\n : ONE_HOUR_MS;\n const lastAttemptAt = state.autoLastAttemptAt ? Date.parse(state.autoLastAttemptAt) : null;\n const recentAttempt =\n state.autoLastAttemptVersion === version &&\n lastAttemptAt !== null &&\n Number.isFinite(lastAttemptAt) &&\n now - lastAttemptAt < attemptIntervalMs;\n\n if (recentAttempt) {\n log.info({ version, tag }, 'Auto-update deferred: recent attempt exists');\n return;\n }\n\n // Stable rollout delay + jitter\n if (channel === 'stable') {\n if (!nextState.autoInstallId) {\n nextState.autoInstallId = state.autoInstallId?.trim() || randomUUID();\n }\n // Track first-seen time for this version\n if (state.autoFirstSeenVersion !== version || state.autoFirstSeenTag !== tag) {\n nextState.autoFirstSeenVersion = version;\n nextState.autoFirstSeenTag = tag;\n nextState.autoFirstSeenAt = new Date(now).toISOString();\n } else {\n nextState.autoFirstSeenAt = state.autoFirstSeenAt;\n }\n\n const firstSeenMs = nextState.autoFirstSeenAt ? Date.parse(nextState.autoFirstSeenAt) : now;\n const baseDelayMs = Math.max(0, stableDelayHours) * ONE_HOUR_MS;\n const jitterWindowMs = Math.max(0, stableJitterHours) * ONE_HOUR_MS;\n const jitterMs = resolveStableJitterMs(nextState.autoInstallId, version, tag, jitterWindowMs);\n const applyAfterMs = firstSeenMs + baseDelayMs + jitterMs;\n\n if (now < applyAfterMs) {\n log.info(\n { version, tag, applyAfter: new Date(applyAfterMs).toISOString() },\n 'Auto-update deferred: stable rollout window not yet due',\n );\n return;\n }\n }\n\n // Execute auto-update\n nextState.autoLastAttemptVersion = version;\n nextState.autoLastAttemptAt = new Date(now).toISOString();\n\n log.info({ channel, version, tag }, 'Starting auto-update');\n\n const lock = await acquireUpdateLock('auto');\n if (!lock) {\n log.info({ version, tag }, 'Auto-update skipped: another update is in progress');\n return;\n }\n try {\n const { runAutoUpdateCommand } = await import('./update-runner.js');\n const result = await runAutoUpdateCommand({ channel, root });\n if (result.ok) {\n nextState.autoLastSuccessVersion = version;\n nextState.autoLastSuccessAt = new Date(now).toISOString();\n log.info({ channel, version, tag }, 'Auto-update applied successfully');\n } else {\n log.warn(\n { channel, version, tag, exitCode: result.exitCode, reason: result.reason },\n `Auto-update attempt failed: ${result.reason ?? `exit ${result.exitCode}`}`,\n );\n }\n } catch (err) {\n log.error({ err, channel, version }, 'Auto-update command threw');\n } finally {\n await lock.release();\n }\n}\n\n/**\n * Schedule periodic update checks. Returns a cleanup function to stop the timer.\n */\nexport function scheduleGatewayUpdateCheck(params: {\n config: Config;\n onUpdateAvailableChange?: (update: UpdateAvailable | null) => void;\n}): () => void {\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const tick = async () => {\n if (stopped) return;\n try {\n await runGatewayUpdateCheck(params);\n } catch (err) {\n log.warn({ err }, 'Periodic update check failed');\n }\n if (!stopped) {\n const intervalMs = resolveCheckIntervalMs(params.config);\n timer = setTimeout(() => void tick(), intervalMs);\n }\n };\n\n // Initial check after a short delay (don't block startup)\n timer = setTimeout(() => void tick(), 5000);\n\n return () => {\n stopped = true;\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Personal AI assistant: CLI, gateway (HTTP/WebSocket + React console), Telegram and WeChat (Weixin) channels — TypeScript, 20+ LLM providers via pi-ai, extensions and skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{i as e,t}from"./rolldown-runtime-DWdDZTNf.js";import{i as n,t as r}from"./vendor-react-DbimaAId.js";import{r as i}from"./vendor-swr-Dp4nzp5h.js";import{$n as a,Bt as o,It as s,Jn as c,Kn as l,Kt as u,Mt as d,Ot as f,Qt as p,Rt as m,Sn as h,Vt as g,Wt as _,Yn as v,at as y,cn as b,ct as x,dr as S,dt as C,et as w,fr as T,ft as ee,kt as te,lt as ne,ot as re,qn as ie,rt as E,st as ae,t as oe,tt as se,ut as ce,yn as le,zt as D}from"./index-KGmhufWu.js";import{a as ue,i as O,n as de,r as fe,t as pe}from"./dist-D2Td6E_v.js";var k=e(n(),1);function A(e){return(e??``).trim().toLowerCase()}function me(e){let t=e.match;return!(!t?.channel||!t.accountId||t.peerId||t.peerKind||t.guildId||t.teamId||t.memberRoleIds&&t.memberRoleIds.length>0)}function he(e){let t=Object.keys(e.accounts??{});return t.length>0?[...t].sort():typeof e.botToken==`string`&&e.botToken.trim()?[`default`]:[]}function j(e){return Object.keys(e.accounts??{}).sort()}function ge(e){let t=Object.keys(e.accounts??{});return t.length>0?[...t].sort():typeof e.appId==`string`&&e.appId.trim()&&typeof e.appSecret==`string`&&e.appSecret.trim()?[`default`]:[]}function M(e,t,n,r,i){let a={},o={},s={};for(let n of t)a[n]=(e.find(e=>A(e.match?.channel)===`telegram`&&A(e.match?.accountId)===A(n)&&me(e))?.agentId??i).trim().toLowerCase();for(let t of n)o[t]=(e.find(e=>A(e.match?.channel)===`weixin`&&A(e.match?.accountId)===A(t)&&me(e))?.agentId??i).trim().toLowerCase();for(let t of r)s[t]=(e.find(e=>A(e.match?.channel)===`feishu`&&A(e.match?.accountId)===A(t)&&me(e))?.agentId??i).trim().toLowerCase();return{telegram:a,weixin:o,feishu:s}}function N(e,t,n,r,i,a){let o=new Set(n.map(A)),s=new Set(r.map(A)),c=new Set(i.map(A)),l=e.filter(e=>{if(e.id?.startsWith(`ui:route:account:`))return!1;if(!me(e))return!0;let t=A(e.match.channel),n=A(e.match.accountId);return!n||n===`*`?!0:!(t===`telegram`&&o.has(n)||t===`weixin`&&s.has(n)||t===`feishu`&&c.has(n))}),u=[];for(let e of n){let n=(t.telegram[e]??t.telegram[A(e)]??a).trim().toLowerCase();u.push({id:`ui:route:account:telegram:${e}`,agentId:n,priority:45,enabled:!0,match:{channel:`telegram`,accountId:e}})}for(let e of r){let n=(t.weixin[e]??t.weixin[A(e)]??a).trim().toLowerCase();u.push({id:`ui:route:account:weixin:${e}`,agentId:n,priority:45,enabled:!0,match:{channel:`weixin`,accountId:e}})}for(let e of i){let n=(t.feishu[e]??t.feishu[A(e)]??a).trim().toLowerCase();u.push({id:`ui:route:account:feishu:${e}`,agentId:n,priority:45,enabled:!0,match:{channel:`feishu`,accountId:e}})}return[...l,...u]}function _e(){return{bindingsFull:[],channelAgentRoutes:{telegram:{},weixin:{},feishu:{}},defaultAgentId:`main`,telegram:{enabled:!1,botToken:``,apiRoot:``,debug:!1,allowFrom:[],groupAllowFrom:[],dmPolicy:`pairing`,groupPolicy:`open`,replyToMode:`off`,streamMode:`partial`,historyLimit:50,textChunkLimit:4e3,proxy:``,accounts:{}},weixin:{enabled:!1,dmPolicy:`pairing`,allowFrom:[],debug:!1,streamMode:`partial`,historyLimit:50,textChunkLimit:4e3,routeTag:``,accounts:{}},feishu:{enabled:!1,defaultAccount:``,appId:``,appSecret:``,domain:`feishu`,connectionMode:`websocket`,verificationToken:``,encryptKey:``,webhookHost:`127.0.0.1`,webhookPort:3e3,webhookPath:`/feishu/events`,dmPolicy:`pairing`,groupPolicy:`allowlist`,allowFrom:[],groupAllowFrom:[],requireMention:!0,historyLimit:50,textChunkLimit:4e3,renderMode:`auto`,streaming:!1,reactionNotifications:`own`,tools:{doc:!0,wiki:!0,drive:!0,scopes:!0,bitable:!0,perm:!1},actions:{reactions:!0},accounts:{}}}}function ve(e){let t=e&&typeof e==`object`?e.channels:void 0,n=t&&typeof t==`object`?t:{},r=n.telegram,i=n.weixin,a=n.feishu,o=r?.accounts,s=o&&typeof o==`object`&&!Array.isArray(o)?o:{},c=i?.accounts,l=c&&typeof c==`object`&&!Array.isArray(c)?c:{},u=(()=>{let t=(e&&typeof e==`object`?e:{}).bindings;return Array.isArray(t)?t:[]})(),d=(()=>{let t=(e&&typeof e==`object`?e:{}).agents;return t&&typeof t==`object`?t:{}})(),f=typeof d.defaultId==`string`&&d.defaultId.trim()?d.defaultId.trim().toLowerCase():`main`,p={telegram:{enabled:!!r?.enabled,botToken:typeof r?.botToken==`string`?r.botToken:``,apiRoot:typeof r?.apiRoot==`string`?r.apiRoot:``,debug:!!r?.debug,allowFrom:Array.isArray(r?.allowFrom)?[...r.allowFrom]:[],groupAllowFrom:Array.isArray(r?.groupAllowFrom)?[...r.groupAllowFrom]:[],dmPolicy:r?.dmPolicy||`pairing`,groupPolicy:r?.groupPolicy||`open`,replyToMode:r?.replyToMode||`off`,streamMode:r?.streamMode??`partial`,historyLimit:typeof r?.historyLimit==`number`?r.historyLimit:50,textChunkLimit:typeof r?.textChunkLimit==`number`?r.textChunkLimit:4e3,proxy:typeof r?.proxy==`string`?r.proxy:``,accounts:{...s}},weixin:{enabled:!!i?.enabled,dmPolicy:i?.dmPolicy||`pairing`,allowFrom:Array.isArray(i?.allowFrom)?[...i.allowFrom]:[],debug:!!i?.debug,streamMode:i?.streamMode??`partial`,historyLimit:typeof i?.historyLimit==`number`?i.historyLimit:50,textChunkLimit:typeof i?.textChunkLimit==`number`?i.textChunkLimit:4e3,routeTag:i?.routeTag==null?``:String(i.routeTag),accounts:{...l}},feishu:{enabled:!!a?.enabled,defaultAccount:typeof a?.defaultAccount==`string`?a.defaultAccount:``,appId:typeof a?.appId==`string`?a.appId:``,appSecret:typeof a?.appSecret==`string`?a.appSecret:``,domain:typeof a?.domain==`string`&&a.domain||`feishu`,connectionMode:a?.connectionMode||`websocket`,verificationToken:typeof a?.verificationToken==`string`?a.verificationToken:``,encryptKey:typeof a?.encryptKey==`string`?a.encryptKey:``,webhookHost:typeof a?.webhookHost==`string`?a.webhookHost:`127.0.0.1`,webhookPort:typeof a?.webhookPort==`number`?a.webhookPort:3e3,webhookPath:typeof a?.webhookPath==`string`?a.webhookPath:`/feishu/events`,dmPolicy:a?.dmPolicy||`pairing`,groupPolicy:a?.groupPolicy||`allowlist`,allowFrom:Array.isArray(a?.allowFrom)?[...a.allowFrom]:[],groupAllowFrom:Array.isArray(a?.groupAllowFrom)?[...a.groupAllowFrom]:[],requireMention:a?.requireMention===void 0?!0:!!a.requireMention,historyLimit:typeof a?.historyLimit==`number`?a.historyLimit:50,textChunkLimit:typeof a?.textChunkLimit==`number`?a.textChunkLimit:4e3,renderMode:a?.renderMode||`auto`,streaming:a?.streaming===void 0?!1:!!a.streaming,reactionNotifications:a?.reactionNotifications||`own`,tools:a?.tools&&typeof a.tools==`object`&&!Array.isArray(a.tools)?{...a.tools}:void 0,actions:a?.actions&&typeof a.actions==`object`&&!Array.isArray(a.actions)?{...a.actions}:void 0,accounts:a?.accounts&&typeof a.accounts==`object`&&!Array.isArray(a.accounts)?{...a.accounts}:{}}},m=M(u,he(p.telegram),j(p.weixin),ge(p.feishu),f);return{...p,bindingsFull:u.map(e=>({...e})),channelAgentRoutes:m,defaultAgentId:f}}async function ye(e){return(await y(E(`/api/channels/weixin/login/start`),{method:`POST`,body:JSON.stringify(e??{})})).payload}async function be(e){return(await y(E(`/api/channels/weixin/login/${encodeURIComponent(e)}`))).payload.status}async function xe(e){let t=e.telegram,n=e.weixin,r=e.feishu,i=N(e.bindingsFull,e.channelAgentRoutes,he(t),j(n),ge(r),e.defaultAgentId),a=(()=>{let e=n.routeTag.trim();return e?/^\d+$/.test(e)?Number(e):e:null})(),o=(await y(E(`/api/config`),{method:`PATCH`,body:JSON.stringify({bindings:i,channels:{telegram:{enabled:t.enabled,botToken:t.botToken,apiRoot:t.apiRoot||void 0,debug:t.debug,allowFrom:t.allowFrom,groupAllowFrom:t.groupAllowFrom.length?t.groupAllowFrom:void 0,dmPolicy:t.dmPolicy,groupPolicy:t.groupPolicy,replyToMode:t.replyToMode,streamMode:t.streamMode,historyLimit:t.historyLimit,textChunkLimit:t.textChunkLimit,proxy:t.proxy||void 0,accounts:t.accounts},weixin:{enabled:n.enabled,dmPolicy:n.dmPolicy,allowFrom:n.allowFrom,debug:n.debug,streamMode:n.streamMode,historyLimit:n.historyLimit,textChunkLimit:n.textChunkLimit,routeTag:a,accounts:n.accounts},feishu:{enabled:r.enabled,defaultAccount:r.defaultAccount||void 0,appId:r.appId,appSecret:r.appSecret||void 0,domain:r.domain||void 0,connectionMode:r.connectionMode,verificationToken:r.verificationToken?.trim()?r.verificationToken:void 0,encryptKey:r.encryptKey?.trim()?r.encryptKey:void 0,webhookHost:r.webhookHost?.trim()?r.webhookHost:void 0,webhookPort:typeof r.webhookPort==`number`?r.webhookPort:void 0,webhookPath:r.webhookPath?.trim()?r.webhookPath:void 0,dmPolicy:r.dmPolicy,groupPolicy:r.groupPolicy,allowFrom:r.allowFrom,groupAllowFrom:r.groupAllowFrom.length?r.groupAllowFrom:void 0,requireMention:r.requireMention,historyLimit:r.historyLimit,textChunkLimit:r.textChunkLimit,renderMode:r.renderMode,streaming:r.streaming,reactionNotifications:r.reactionNotifications,tools:r.tools,actions:r.actions,accounts:r.accounts}}})})).payload?.config;return w(),o?ve(o):{...e,bindingsFull:i}}function Se(){return _(`w-full rounded-lg border border-edge bg-surface-panel px-3 py-2 text-sm text-fg`,`placeholder:text-fg-subtle`,D,`dark:border-edge`)}function Ce(){return _(m,s)}function we(e){return e.split(/[,\n]/).map(e=>e.trim()).filter(Boolean).map(e=>/^-?\d+$/.test(e)?Number(e):e)}function Te(e){return e.map(String).join(`, `)}function Ee(e){return!!e.botToken?.trim()||Object.keys(e.accounts??{}).length>0}function De(e){return Object.keys(e.accounts??{}).length>0||e.allowFrom.length>0}function Oe(e){return!!(e.appId?.trim()&&e.appSecret?.trim())||Object.keys(e.accounts??{}).length>0}var P=r();function F({children:e}){return(0,P.jsx)(`div`,{className:`text-sm font-medium text-fg`,children:e})}function I({children:e}){return(0,P.jsx)(`p`,{className:`text-xs leading-relaxed text-fg-subtle`,children:e})}function L({label:e,value:t,onChange:n,options:r}){return(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:e}),(0,P.jsx)(`select`,{className:Ce(),value:t,onChange:e=>n(e.target.value),children:r.map(e=>(0,P.jsx)(`option`,{value:e.value,children:e.label},e.value))})]})}function ke({accountIds:e,routes:t,defaultAgentId:n,agentItems:r,disabled:i,onChange:a,ch:o}){if(e.length===0)return null;let c=r.length>0?r:[{id:n}];return(0,P.jsxs)(`div`,{className:`space-y-3 border-t border-edge-subtle pt-4 dark:border-edge`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(F,{children:o.agentRoutingTitle}),(0,P.jsx)(I,{children:o.agentRoutingHint})]}),(0,P.jsx)(`div`,{className:`space-y-2`,children:e.map(e=>(0,P.jsxs)(`div`,{className:`grid grid-cols-1 items-start gap-2 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2.5 sm:grid-cols-2 sm:items-center dark:border-edge`,children:[(0,P.jsxs)(`div`,{className:`min-w-0`,children:[(0,P.jsx)(`p`,{className:`text-xs font-medium text-fg-muted`,children:o.agentRoutingAccountLabel}),(0,P.jsx)(`p`,{className:`mt-0.5 truncate font-mono text-sm text-fg`,title:e,children:e})]}),(0,P.jsxs)(`div`,{className:`min-w-0`,children:[(0,P.jsx)(`label`,{className:`sr-only`,htmlFor:`agent-route-${e}`,children:o.agentRoutingAgentLabel}),(0,P.jsx)(`select`,{id:`agent-route-${e}`,className:_(Se(),s),disabled:i,value:(t[e]??n).toLowerCase(),onChange:t=>a(e,t.target.value),children:c.map(e=>(0,P.jsx)(`option`,{value:e.id,children:e.name?.trim()?`${e.name} (${e.id})`:e.id},e.id))})]})]},e))})]})}function Ae({icon:e,title:t,subtitle:n,configured:r,enabled:i,onToggle:a,toggleDisabled:o,onConfigure:s,onEdit:c,onRemove:l,ch:u}){return(0,P.jsxs)(`div`,{className:`flex flex-col gap-3 rounded-2xl border border-edge bg-surface-base px-4 py-4 dark:border-edge sm:flex-row sm:items-center sm:gap-4`,children:[(0,P.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-start gap-4`,children:[(0,P.jsx)(`div`,{className:`flex size-12 shrink-0 items-center justify-center rounded-xl bg-surface-hover`,"aria-hidden":!0,children:e}),(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,P.jsx)(`h2`,{className:`text-sm font-semibold text-fg`,children:t}),r?(0,P.jsx)(`span`,{className:`inline-flex items-center rounded-full bg-success-soft px-2 py-0.5 text-xs font-medium text-success`,children:u.hubConnectedBadge}):null]}),(0,P.jsx)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:n})]})]}),r?(0,P.jsxs)(`div`,{className:`flex shrink-0 flex-wrap items-center justify-end gap-2 sm:gap-3`,children:[(0,P.jsxs)(O,{children:[(0,P.jsx)(ue,{asChild:!0,children:(0,P.jsx)(g,{type:`button`,variant:`ghost`,className:`size-9 shrink-0 p-0`,"aria-label":u.menuMoreAria,children:(0,P.jsx)(v,{className:`size-5 text-fg-muted`,strokeWidth:1.75})})}),(0,P.jsx)(fe,{children:(0,P.jsxs)(pe,{className:`z-[70] min-w-[11rem] rounded-xl border border-edge bg-surface-panel p-1 shadow-popover dark:border-edge`,sideOffset:6,align:`end`,children:[(0,P.jsx)(de,{className:`cursor-pointer rounded-lg px-3 py-2 text-sm text-fg outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover`,onSelect:()=>c(),children:(0,P.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,P.jsx)(le,{className:`size-4 shrink-0 text-fg-muted`,strokeWidth:1.75}),u.menuEditConfig]})}),(0,P.jsx)(de,{className:`cursor-pointer rounded-lg px-3 py-2 text-sm text-danger outline-none hover:bg-surface-hover data-[highlighted]:bg-surface-hover`,onSelect:()=>l(),children:(0,P.jsxs)(`span`,{className:`flex items-center gap-2`,children:[(0,P.jsx)(p,{className:`size-4 shrink-0`,strokeWidth:1.75}),u.menuRemoveConfig]})})]})})]}),(0,P.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":i,"aria-label":`${t} — ${u.enableChannelAria}`,disabled:o,className:_(`inline-flex h-6 w-10 shrink-0 items-center rounded-full border border-edge p-0.5 transition-colors`,i?`justify-end bg-accent`:`justify-start bg-surface-hover`,o&&`cursor-not-allowed opacity-50`),onClick:()=>void a(!i),children:(0,P.jsx)(`span`,{className:`size-4 rounded-full bg-surface-panel shadow-surface ring-1 ring-edge/40 dark:ring-edge/55`})})]}):(0,P.jsx)(`div`,{className:`flex shrink-0 justify-end sm:justify-end`,children:(0,P.jsx)(g,{type:`button`,variant:`primary`,className:`shrink-0`,onClick:s,children:u.hubConfigureButton})})]})}function je({tg:e,updateTelegram:t,ch:n,dmOpts:r,groupOpts:i,replyOpts:a,streamOpts:o,tgAccountsDraft:s,setTgAccountsDraft:c,tgAccountsError:l,onTgAccountsBlur:u}){let d=Se;return(0,P.jsxs)(`div`,{className:`space-y-4 border-t border-edge-subtle pt-4 dark:border-edge`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.apiRoot}),(0,P.jsx)(`input`,{className:d(),value:e.apiRoot,onChange:e=>t({apiRoot:e.target.value}),placeholder:`https://api.telegram.org`})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.proxy}),(0,P.jsx)(`input`,{className:d(),value:e.proxy,onChange:e=>t({proxy:e.target.value}),placeholder:`http://proxy.example.com:8080`})]}),(0,P.jsx)(L,{label:n.dmPolicy,value:e.dmPolicy,onChange:e=>t({dmPolicy:e}),options:r}),(0,P.jsx)(L,{label:n.groupPolicy,value:e.groupPolicy,onChange:e=>t({groupPolicy:e}),options:i}),(0,P.jsx)(L,{label:n.replyToMode,value:e.replyToMode,onChange:e=>t({replyToMode:e}),options:a}),(0,P.jsx)(L,{label:n.streamMode,value:e.streamMode,onChange:e=>t({streamMode:e}),options:o}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.allowFromGroups}),(0,P.jsx)(`textarea`,{className:_(d(),`min-h-[2.75rem] resize-y font-mono text-xs`),rows:2,placeholder:`-1001234567890`,value:Te(e.groupAllowFrom),onChange:e=>t({groupAllowFrom:we(e.target.value)})})]}),(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.historyLimit}),(0,P.jsx)(`input`,{type:`number`,min:10,max:200,className:d(),value:e.historyLimit,onChange:e=>t({historyLimit:parseInt(e.target.value,10)||50})})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.textChunkLimit}),(0,P.jsx)(`input`,{type:`number`,min:1e3,max:1e4,step:100,className:d(),value:e.textChunkLimit,onChange:e=>t({textChunkLimit:parseInt(e.target.value,10)||4e3})})]})]}),(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:e.debug,onChange:e=>t({debug:e.target.checked})}),n.telegramDebug]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.multiAccountJson}),(0,P.jsx)(`textarea`,{className:_(d(),`min-h-[140px] resize-y font-mono text-xs`),spellCheck:!1,value:s,onChange:e=>c(e.target.value),onBlur:u,placeholder:`{ "personal": { "accountId": "personal", "botToken": "...", ... } }`}),l?(0,P.jsx)(`p`,{className:`text-xs text-red-600 dark:text-red-400`,children:l}):(0,P.jsx)(I,{children:n.multiAccountJsonDesc})]})]})}function Me({wx:e,updateWeixin:t,ch:n,dmOpts:r,streamOpts:i,wxAccountsDraft:a,setWxAccountsDraft:o,wxAccountsError:s,onWxAccountsBlur:c,channelAgentRoutesWx:l,defaultAgentId:u,agentItems:d,onAgentRouteChange:f,routingDisabled:p}){let m=Se;return(0,P.jsxs)(`div`,{className:`space-y-4 border-t border-edge-subtle pt-4 dark:border-edge`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.weixinAllowFrom}),(0,P.jsx)(`textarea`,{className:_(m(),`min-h-[2.75rem] resize-y font-mono text-xs`),rows:2,placeholder:`wxid_..., openid_...`,value:e.allowFrom.join(`, `),onChange:e=>t({allowFrom:e.target.value.split(/[,\n]/).map(e=>e.trim()).filter(Boolean)})}),(0,P.jsx)(I,{children:n.weixinAllowFromDesc})]}),(0,P.jsx)(L,{label:n.dmPolicy,value:e.dmPolicy,onChange:e=>t({dmPolicy:e}),options:r}),(0,P.jsx)(L,{label:n.streamMode,value:e.streamMode,onChange:e=>t({streamMode:e}),options:i}),(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.historyLimit}),(0,P.jsx)(`input`,{type:`number`,min:10,max:200,className:m(),value:e.historyLimit,onChange:e=>t({historyLimit:parseInt(e.target.value,10)||50})})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.textChunkLimit}),(0,P.jsx)(`input`,{type:`number`,min:1e3,max:1e4,step:100,className:m(),value:e.textChunkLimit,onChange:e=>t({textChunkLimit:parseInt(e.target.value,10)||4e3})})]})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.weixinRouteTag}),(0,P.jsx)(`input`,{className:m(),value:e.routeTag,onChange:e=>t({routeTag:e.target.value}),placeholder:n.routeTagPlaceholder}),(0,P.jsx)(I,{children:n.weixinRouteTagDesc})]}),(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:e.debug,onChange:e=>t({debug:e.target.checked})}),n.weixinDebug]}),(0,P.jsx)(I,{children:n.weixinDebugDesc}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:n.weixinAccountsJson}),(0,P.jsx)(`textarea`,{className:_(m(),`min-h-[140px] resize-y font-mono text-xs`),spellCheck:!1,value:a,onChange:e=>o(e.target.value),onBlur:c,placeholder:`{ "personal": { "name": "...", "cdnBaseUrl": "...", "enabled": true } }`}),s?(0,P.jsx)(`p`,{className:`text-xs text-red-600 dark:text-red-400`,children:s}):(0,P.jsx)(I,{children:n.weixinAccountsJsonDesc})]}),(0,P.jsx)(ke,{accountIds:j(e),routes:l,defaultAgentId:u,agentItems:d,disabled:p,onChange:f,ch:n})]})}var R=t(((e,t)=>{t.exports=function(){return typeof Promise==`function`&&Promise.prototype&&Promise.prototype.then}})),z=t((e=>{var t,n=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];e.getSymbolSize=function(e){if(!e)throw Error(`"version" cannot be null or undefined`);if(e<1||e>40)throw Error(`"version" should be in range from 1 to 40`);return e*4+17},e.getSymbolTotalCodewords=function(e){return n[e]},e.getBCHDigit=function(e){let t=0;for(;e!==0;)t++,e>>>=1;return t},e.setToSJISFunction=function(e){if(typeof e!=`function`)throw Error(`"toSJISFunc" is not a valid function.`);t=e},e.isKanjiModeEnabled=function(){return t!==void 0},e.toSJIS=function(e){return t(e)}})),B=t((e=>{e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function t(t){if(typeof t!=`string`)throw Error(`Param is not a string`);switch(t.toLowerCase()){case`l`:case`low`:return e.L;case`m`:case`medium`:return e.M;case`q`:case`quartile`:return e.Q;case`h`:case`high`:return e.H;default:throw Error(`Unknown EC Level: `+t)}}e.isValid=function(e){return e&&e.bit!==void 0&&e.bit>=0&&e.bit<4},e.from=function(n,r){if(e.isValid(n))return n;try{return t(n)}catch{return r}}})),Ne=t(((e,t)=>{function n(){this.buffer=[],this.length=0}n.prototype={get:function(e){let t=Math.floor(e/8);return(this.buffer[t]>>>7-e%8&1)==1},put:function(e,t){for(let n=0;n<t;n++)this.putBit((e>>>t-n-1&1)==1)},getLengthInBits:function(){return this.length},putBit:function(e){let t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),e&&(this.buffer[t]|=128>>>this.length%8),this.length++}},t.exports=n})),Pe=t(((e,t)=>{function n(e){if(!e||e<1)throw Error(`BitMatrix size must be defined and greater than 0`);this.size=e,this.data=new Uint8Array(e*e),this.reservedBit=new Uint8Array(e*e)}n.prototype.set=function(e,t,n,r){let i=e*this.size+t;this.data[i]=n,r&&(this.reservedBit[i]=!0)},n.prototype.get=function(e,t){return this.data[e*this.size+t]},n.prototype.xor=function(e,t,n){this.data[e*this.size+t]^=n},n.prototype.isReserved=function(e,t){return this.reservedBit[e*this.size+t]},t.exports=n})),Fe=t((e=>{var t=z().getSymbolSize;e.getRowColCoords=function(e){if(e===1)return[];let n=Math.floor(e/7)+2,r=t(e),i=r===145?26:Math.ceil((r-13)/(2*n-2))*2,a=[r-7];for(let e=1;e<n-1;e++)a[e]=a[e-1]-i;return a.push(6),a.reverse()},e.getPositions=function(t){let n=[],r=e.getRowColCoords(t),i=r.length;for(let e=0;e<i;e++)for(let t=0;t<i;t++)e===0&&t===0||e===0&&t===i-1||e===i-1&&t===0||n.push([r[e],r[t]]);return n}})),Ie=t((e=>{var t=z().getSymbolSize,n=7;e.getPositions=function(e){let r=t(e);return[[0,0],[r-n,0],[0,r-n]]}})),Le=t((e=>{e.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var t={N1:3,N2:3,N3:40,N4:10};e.isValid=function(e){return e!=null&&e!==``&&!isNaN(e)&&e>=0&&e<=7},e.from=function(t){return e.isValid(t)?parseInt(t,10):void 0},e.getPenaltyN1=function(e){let n=e.size,r=0,i=0,a=0,o=null,s=null;for(let c=0;c<n;c++){i=a=0,o=s=null;for(let l=0;l<n;l++){let n=e.get(c,l);n===o?i++:(i>=5&&(r+=t.N1+(i-5)),o=n,i=1),n=e.get(l,c),n===s?a++:(a>=5&&(r+=t.N1+(a-5)),s=n,a=1)}i>=5&&(r+=t.N1+(i-5)),a>=5&&(r+=t.N1+(a-5))}return r},e.getPenaltyN2=function(e){let n=e.size,r=0;for(let t=0;t<n-1;t++)for(let i=0;i<n-1;i++){let n=e.get(t,i)+e.get(t,i+1)+e.get(t+1,i)+e.get(t+1,i+1);(n===4||n===0)&&r++}return r*t.N2},e.getPenaltyN3=function(e){let n=e.size,r=0,i=0,a=0;for(let t=0;t<n;t++){i=a=0;for(let o=0;o<n;o++)i=i<<1&2047|e.get(t,o),o>=10&&(i===1488||i===93)&&r++,a=a<<1&2047|e.get(o,t),o>=10&&(a===1488||a===93)&&r++}return r*t.N3},e.getPenaltyN4=function(e){let n=0,r=e.data.length;for(let t=0;t<r;t++)n+=e.data[t];return Math.abs(Math.ceil(n*100/r/5)-10)*t.N4};function n(t,n,r){switch(t){case e.Patterns.PATTERN000:return(n+r)%2==0;case e.Patterns.PATTERN001:return n%2==0;case e.Patterns.PATTERN010:return r%3==0;case e.Patterns.PATTERN011:return(n+r)%3==0;case e.Patterns.PATTERN100:return(Math.floor(n/2)+Math.floor(r/3))%2==0;case e.Patterns.PATTERN101:return n*r%2+n*r%3==0;case e.Patterns.PATTERN110:return(n*r%2+n*r%3)%2==0;case e.Patterns.PATTERN111:return(n*r%3+(n+r)%2)%2==0;default:throw Error(`bad maskPattern:`+t)}}e.applyMask=function(e,t){let r=t.size;for(let i=0;i<r;i++)for(let a=0;a<r;a++)t.isReserved(a,i)||t.xor(a,i,n(e,a,i))},e.getBestMask=function(t,n){let r=Object.keys(e.Patterns).length,i=0,a=1/0;for(let o=0;o<r;o++){n(o),e.applyMask(o,t);let r=e.getPenaltyN1(t)+e.getPenaltyN2(t)+e.getPenaltyN3(t)+e.getPenaltyN4(t);e.applyMask(o,t),r<a&&(a=r,i=o)}return i}})),Re=t((e=>{var t=B(),n=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],r=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];e.getBlocksCount=function(e,r){switch(r){case t.L:return n[(e-1)*4+0];case t.M:return n[(e-1)*4+1];case t.Q:return n[(e-1)*4+2];case t.H:return n[(e-1)*4+3];default:return}},e.getTotalCodewordsCount=function(e,n){switch(n){case t.L:return r[(e-1)*4+0];case t.M:return r[(e-1)*4+1];case t.Q:return r[(e-1)*4+2];case t.H:return r[(e-1)*4+3];default:return}}})),ze=t((e=>{var t=new Uint8Array(512),n=new Uint8Array(256);(function(){let e=1;for(let r=0;r<255;r++)t[r]=e,n[e]=r,e<<=1,e&256&&(e^=285);for(let e=255;e<512;e++)t[e]=t[e-255]})(),e.log=function(e){if(e<1)throw Error(`log(`+e+`)`);return n[e]},e.exp=function(e){return t[e]},e.mul=function(e,r){return e===0||r===0?0:t[n[e]+n[r]]}})),Be=t((e=>{var t=ze();e.mul=function(e,n){let r=new Uint8Array(e.length+n.length-1);for(let i=0;i<e.length;i++)for(let a=0;a<n.length;a++)r[i+a]^=t.mul(e[i],n[a]);return r},e.mod=function(e,n){let r=new Uint8Array(e);for(;r.length-n.length>=0;){let e=r[0];for(let i=0;i<n.length;i++)r[i]^=t.mul(n[i],e);let i=0;for(;i<r.length&&r[i]===0;)i++;r=r.slice(i)}return r},e.generateECPolynomial=function(n){let r=new Uint8Array([1]);for(let i=0;i<n;i++)r=e.mul(r,new Uint8Array([1,t.exp(i)]));return r}})),Ve=t(((e,t)=>{var n=Be();function r(e){this.genPoly=void 0,this.degree=e,this.degree&&this.initialize(this.degree)}r.prototype.initialize=function(e){this.degree=e,this.genPoly=n.generateECPolynomial(this.degree)},r.prototype.encode=function(e){if(!this.genPoly)throw Error(`Encoder not initialized`);let t=new Uint8Array(e.length+this.degree);t.set(e);let r=n.mod(t,this.genPoly),i=this.degree-r.length;if(i>0){let e=new Uint8Array(this.degree);return e.set(r,i),e}return r},t.exports=r})),He=t((e=>{e.isValid=function(e){return!isNaN(e)&&e>=1&&e<=40}})),V=t((e=>{var t=`[0-9]+`,n=`[A-Z $%*+\\-./:]+`,r=`(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+`;r=r.replace(/u/g,`\\u`);var i=`(?:(?![A-Z0-9 $%*+\\-./:]|`+r+`)(?:.|[\r
|
|
2
|
-
]))+`;e.KANJI=new RegExp(r,`g`),e.BYTE_KANJI=RegExp(`[^A-Z0-9 $%*+\\-./:]+`,`g`),e.BYTE=new RegExp(i,`g`),e.NUMERIC=new RegExp(t,`g`),e.ALPHANUMERIC=new RegExp(n,`g`);var a=RegExp(`^`+r+`$`),o=RegExp(`^`+t+`$`),s=RegExp(`^[A-Z0-9 $%*+\\-./:]+$`);e.testKanji=function(e){return a.test(e)},e.testNumeric=function(e){return o.test(e)},e.testAlphanumeric=function(e){return s.test(e)}})),H=t((e=>{var t=He(),n=V();e.NUMERIC={id:`Numeric`,bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:`Alphanumeric`,bit:2,ccBits:[9,11,13]},e.BYTE={id:`Byte`,bit:4,ccBits:[8,16,16]},e.KANJI={id:`Kanji`,bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(e,n){if(!e.ccBits)throw Error(`Invalid mode: `+e);if(!t.isValid(n))throw Error(`Invalid version: `+n);return n>=1&&n<10?e.ccBits[0]:n<27?e.ccBits[1]:e.ccBits[2]},e.getBestModeForData=function(t){return n.testNumeric(t)?e.NUMERIC:n.testAlphanumeric(t)?e.ALPHANUMERIC:n.testKanji(t)?e.KANJI:e.BYTE},e.toString=function(e){if(e&&e.id)return e.id;throw Error(`Invalid mode`)},e.isValid=function(e){return e&&e.bit&&e.ccBits};function r(t){if(typeof t!=`string`)throw Error(`Param is not a string`);switch(t.toLowerCase()){case`numeric`:return e.NUMERIC;case`alphanumeric`:return e.ALPHANUMERIC;case`kanji`:return e.KANJI;case`byte`:return e.BYTE;default:throw Error(`Unknown mode: `+t)}}e.from=function(t,n){if(e.isValid(t))return t;try{return r(t)}catch{return n}}})),U=t((e=>{var t=z(),n=Re(),r=B(),i=H(),a=He(),o=7973,s=t.getBCHDigit(o);function c(t,n,r){for(let i=1;i<=40;i++)if(n<=e.getCapacity(i,r,t))return i}function l(e,t){return i.getCharCountIndicator(e,t)+4}function u(e,t){let n=0;return e.forEach(function(e){let r=l(e.mode,t);n+=r+e.getBitsLength()}),n}function d(t,n){for(let r=1;r<=40;r++)if(u(t,r)<=e.getCapacity(r,n,i.MIXED))return r}e.from=function(e,t){return a.isValid(e)?parseInt(e,10):t},e.getCapacity=function(e,r,o){if(!a.isValid(e))throw Error(`Invalid QR Code version`);o===void 0&&(o=i.BYTE);let s=(t.getSymbolTotalCodewords(e)-n.getTotalCodewordsCount(e,r))*8;if(o===i.MIXED)return s;let c=s-l(o,e);switch(o){case i.NUMERIC:return Math.floor(c/10*3);case i.ALPHANUMERIC:return Math.floor(c/11*2);case i.KANJI:return Math.floor(c/13);case i.BYTE:default:return Math.floor(c/8)}},e.getBestVersionForData=function(e,t){let n,i=r.from(t,r.M);if(Array.isArray(e)){if(e.length>1)return d(e,i);if(e.length===0)return 1;n=e[0]}else n=e;return c(n.mode,n.getLength(),i)},e.getEncodedBits=function(e){if(!a.isValid(e)||e<7)throw Error(`Invalid QR Code version`);let n=e<<12;for(;t.getBCHDigit(n)-s>=0;)n^=o<<t.getBCHDigit(n)-s;return e<<12|n}})),Ue=t((e=>{var t=z(),n=1335,r=21522,i=t.getBCHDigit(n);e.getEncodedBits=function(e,a){let o=e.bit<<3|a,s=o<<10;for(;t.getBCHDigit(s)-i>=0;)s^=n<<t.getBCHDigit(s)-i;return(o<<10|s)^r}})),W=t(((e,t)=>{var n=H();function r(e){this.mode=n.NUMERIC,this.data=e.toString()}r.getBitsLength=function(e){return 10*Math.floor(e/3)+(e%3?e%3*3+1:0)},r.prototype.getLength=function(){return this.data.length},r.prototype.getBitsLength=function(){return r.getBitsLength(this.data.length)},r.prototype.write=function(e){let t,n,r;for(t=0;t+3<=this.data.length;t+=3)n=this.data.substr(t,3),r=parseInt(n,10),e.put(r,10);let i=this.data.length-t;i>0&&(n=this.data.substr(t),r=parseInt(n,10),e.put(r,i*3+1))},t.exports=r})),We=t(((e,t)=>{var n=H(),r=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:`.split(``);function i(e){this.mode=n.ALPHANUMERIC,this.data=e}i.getBitsLength=function(e){return 11*Math.floor(e/2)+e%2*6},i.prototype.getLength=function(){return this.data.length},i.prototype.getBitsLength=function(){return i.getBitsLength(this.data.length)},i.prototype.write=function(e){let t;for(t=0;t+2<=this.data.length;t+=2){let n=r.indexOf(this.data[t])*45;n+=r.indexOf(this.data[t+1]),e.put(n,11)}this.data.length%2&&e.put(r.indexOf(this.data[t]),6)},t.exports=i})),G=t(((e,t)=>{var n=H();function r(e){this.mode=n.BYTE,typeof e==`string`?this.data=new TextEncoder().encode(e):this.data=new Uint8Array(e)}r.getBitsLength=function(e){return e*8},r.prototype.getLength=function(){return this.data.length},r.prototype.getBitsLength=function(){return r.getBitsLength(this.data.length)},r.prototype.write=function(e){for(let t=0,n=this.data.length;t<n;t++)e.put(this.data[t],8)},t.exports=r})),Ge=t(((e,t)=>{var n=H(),r=z();function i(e){this.mode=n.KANJI,this.data=e}i.getBitsLength=function(e){return e*13},i.prototype.getLength=function(){return this.data.length},i.prototype.getBitsLength=function(){return i.getBitsLength(this.data.length)},i.prototype.write=function(e){let t;for(t=0;t<this.data.length;t++){let n=r.toSJIS(this.data[t]);if(n>=33088&&n<=40956)n-=33088;else if(n>=57408&&n<=60351)n-=49472;else throw Error(`Invalid SJIS character: `+this.data[t]+`
|
|
3
|
-
Make sure your charset is UTF-8`);n=(n>>>8&255)*192+(n&255),e.put(n,13)}},t.exports=i})),K=t(((e,t)=>{var n={single_source_shortest_paths:function(e,t,r){var i={},a={};a[t]=0;var o=n.PriorityQueue.make();o.push(t,0);for(var s,c,l,u,d,f,p,m,h;!o.empty();)for(l in s=o.pop(),c=s.value,u=s.cost,d=e[c]||{},d)d.hasOwnProperty(l)&&(f=d[l],p=u+f,m=a[l],h=a[l]===void 0,(h||m>p)&&(a[l]=p,o.push(l,p),i[l]=c));if(r!==void 0&&a[r]===void 0){var g=[`Could not find a path from `,t,` to `,r,`.`].join(``);throw Error(g)}return i},extract_shortest_path_from_predecessor_list:function(e,t){for(var n=[],r=t;r;)n.push(r),e[r],r=e[r];return n.reverse(),n},find_path:function(e,t,r){var i=n.single_source_shortest_paths(e,t,r);return n.extract_shortest_path_from_predecessor_list(i,r)},PriorityQueue:{make:function(e){var t=n.PriorityQueue,r={},i;for(i in e||={},t)t.hasOwnProperty(i)&&(r[i]=t[i]);return r.queue=[],r.sorter=e.sorter||t.default_sorter,r},default_sorter:function(e,t){return e.cost-t.cost},push:function(e,t){var n={value:e,cost:t};this.queue.push(n),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};t!==void 0&&(t.exports=n)})),Ke=t((e=>{var t=H(),n=W(),r=We(),i=G(),a=Ge(),o=V(),s=z(),c=K();function l(e){return unescape(encodeURIComponent(e)).length}function u(e,t,n){let r=[],i;for(;(i=e.exec(n))!==null;)r.push({data:i[0],index:i.index,mode:t,length:i[0].length});return r}function d(e){let n=u(o.NUMERIC,t.NUMERIC,e),r=u(o.ALPHANUMERIC,t.ALPHANUMERIC,e),i,a;return s.isKanjiModeEnabled()?(i=u(o.BYTE,t.BYTE,e),a=u(o.KANJI,t.KANJI,e)):(i=u(o.BYTE_KANJI,t.BYTE,e),a=[]),n.concat(r,i,a).sort(function(e,t){return e.index-t.index}).map(function(e){return{data:e.data,mode:e.mode,length:e.length}})}function f(e,o){switch(o){case t.NUMERIC:return n.getBitsLength(e);case t.ALPHANUMERIC:return r.getBitsLength(e);case t.KANJI:return a.getBitsLength(e);case t.BYTE:return i.getBitsLength(e)}}function p(e){return e.reduce(function(e,t){let n=e.length-1>=0?e[e.length-1]:null;return n&&n.mode===t.mode?(e[e.length-1].data+=t.data,e):(e.push(t),e)},[])}function m(e){let n=[];for(let r=0;r<e.length;r++){let i=e[r];switch(i.mode){case t.NUMERIC:n.push([i,{data:i.data,mode:t.ALPHANUMERIC,length:i.length},{data:i.data,mode:t.BYTE,length:i.length}]);break;case t.ALPHANUMERIC:n.push([i,{data:i.data,mode:t.BYTE,length:i.length}]);break;case t.KANJI:n.push([i,{data:i.data,mode:t.BYTE,length:l(i.data)}]);break;case t.BYTE:n.push([{data:i.data,mode:t.BYTE,length:l(i.data)}])}}return n}function h(e,n){let r={},i={start:{}},a=[`start`];for(let o=0;o<e.length;o++){let s=e[o],c=[];for(let e=0;e<s.length;e++){let l=s[e],u=``+o+e;c.push(u),r[u]={node:l,lastCount:0},i[u]={};for(let e=0;e<a.length;e++){let o=a[e];r[o]&&r[o].node.mode===l.mode?(i[o][u]=f(r[o].lastCount+l.length,l.mode)-f(r[o].lastCount,l.mode),r[o].lastCount+=l.length):(r[o]&&(r[o].lastCount=l.length),i[o][u]=f(l.length,l.mode)+4+t.getCharCountIndicator(l.mode,n))}}a=c}for(let e=0;e<a.length;e++)i[a[e]].end=0;return{map:i,table:r}}function g(e,o){let c,l=t.getBestModeForData(e);if(c=t.from(o,l),c!==t.BYTE&&c.bit<l.bit)throw Error(`"`+e+`" cannot be encoded with mode `+t.toString(c)+`.
|
|
4
|
-
Suggested mode is: `+t.toString(l));switch(c===t.KANJI&&!s.isKanjiModeEnabled()&&(c=t.BYTE),c){case t.NUMERIC:return new n(e);case t.ALPHANUMERIC:return new r(e);case t.KANJI:return new a(e);case t.BYTE:return new i(e)}}e.fromArray=function(e){return e.reduce(function(e,t){return typeof t==`string`?e.push(g(t,null)):t.data&&e.push(g(t.data,t.mode)),e},[])},e.fromString=function(t,n){let r=h(m(d(t,s.isKanjiModeEnabled())),n),i=c.find_path(r.map,`start`,`end`),a=[];for(let e=1;e<i.length-1;e++)a.push(r.table[i[e]].node);return e.fromArray(p(a))},e.rawSplit=function(t){return e.fromArray(d(t,s.isKanjiModeEnabled()))}})),q=t((e=>{var t=z(),n=B(),r=Ne(),i=Pe(),a=Fe(),o=Ie(),s=Le(),c=Re(),l=Ve(),u=U(),d=Ue(),f=H(),p=Ke();function m(e,t){let n=e.size,r=o.getPositions(t);for(let t=0;t<r.length;t++){let i=r[t][0],a=r[t][1];for(let t=-1;t<=7;t++)if(!(i+t<=-1||n<=i+t))for(let r=-1;r<=7;r++)a+r<=-1||n<=a+r||(t>=0&&t<=6&&(r===0||r===6)||r>=0&&r<=6&&(t===0||t===6)||t>=2&&t<=4&&r>=2&&r<=4?e.set(i+t,a+r,!0,!0):e.set(i+t,a+r,!1,!0))}}function h(e){let t=e.size;for(let n=8;n<t-8;n++){let t=n%2==0;e.set(n,6,t,!0),e.set(6,n,t,!0)}}function g(e,t){let n=a.getPositions(t);for(let t=0;t<n.length;t++){let r=n[t][0],i=n[t][1];for(let t=-2;t<=2;t++)for(let n=-2;n<=2;n++)t===-2||t===2||n===-2||n===2||t===0&&n===0?e.set(r+t,i+n,!0,!0):e.set(r+t,i+n,!1,!0)}}function _(e,t){let n=e.size,r=u.getEncodedBits(t),i,a,o;for(let t=0;t<18;t++)i=Math.floor(t/3),a=t%3+n-8-3,o=(r>>t&1)==1,e.set(i,a,o,!0),e.set(a,i,o,!0)}function v(e,t,n){let r=e.size,i=d.getEncodedBits(t,n),a,o;for(a=0;a<15;a++)o=(i>>a&1)==1,a<6?e.set(a,8,o,!0):a<8?e.set(a+1,8,o,!0):e.set(r-15+a,8,o,!0),a<8?e.set(8,r-a-1,o,!0):a<9?e.set(8,15-a-1+1,o,!0):e.set(8,15-a-1,o,!0);e.set(r-8,8,1,!0)}function y(e,t){let n=e.size,r=-1,i=n-1,a=7,o=0;for(let s=n-1;s>0;s-=2)for(s===6&&s--;;){for(let n=0;n<2;n++)if(!e.isReserved(i,s-n)){let r=!1;o<t.length&&(r=(t[o]>>>a&1)==1),e.set(i,s-n,r),a--,a===-1&&(o++,a=7)}if(i+=r,i<0||n<=i){i-=r,r=-r;break}}}function b(e,n,i){let a=new r;i.forEach(function(t){a.put(t.mode.bit,4),a.put(t.getLength(),f.getCharCountIndicator(t.mode,e)),t.write(a)});let o=(t.getSymbolTotalCodewords(e)-c.getTotalCodewordsCount(e,n))*8;for(a.getLengthInBits()+4<=o&&a.put(0,4);a.getLengthInBits()%8!=0;)a.putBit(0);let s=(o-a.getLengthInBits())/8;for(let e=0;e<s;e++)a.put(e%2?17:236,8);return x(a,e,n)}function x(e,n,r){let i=t.getSymbolTotalCodewords(n),a=i-c.getTotalCodewordsCount(n,r),o=c.getBlocksCount(n,r),s=o-i%o,u=Math.floor(i/o),d=Math.floor(a/o),f=d+1,p=u-d,m=new l(p),h=0,g=Array(o),_=Array(o),v=0,y=new Uint8Array(e.buffer);for(let e=0;e<o;e++){let t=e<s?d:f;g[e]=y.slice(h,h+t),_[e]=m.encode(g[e]),h+=t,v=Math.max(v,t)}let b=new Uint8Array(i),x=0,S,C;for(S=0;S<v;S++)for(C=0;C<o;C++)S<g[C].length&&(b[x++]=g[C][S]);for(S=0;S<p;S++)for(C=0;C<o;C++)b[x++]=_[C][S];return b}function S(e,n,r,a){let o;if(Array.isArray(e))o=p.fromArray(e);else if(typeof e==`string`){let t=n;if(!t){let n=p.rawSplit(e);t=u.getBestVersionForData(n,r)}o=p.fromString(e,t||40)}else throw Error(`Invalid data`);let c=u.getBestVersionForData(o,r);if(!c)throw Error(`The amount of data is too big to be stored in a QR Code`);if(!n)n=c;else if(n<c)throw Error(`
|
|
5
|
-
The chosen QR Code version cannot contain this amount of data.
|
|
6
|
-
Minimum version required to store current data is: `+c+`.
|
|
7
|
-
`);let l=b(n,r,o),d=new i(t.getSymbolSize(n));return m(d,n),h(d),g(d,n),v(d,r,0),n>=7&&_(d,n),y(d,l),isNaN(a)&&(a=s.getBestMask(d,v.bind(null,d,r))),s.applyMask(a,d),v(d,r,a),{modules:d,version:n,errorCorrectionLevel:r,maskPattern:a,segments:o}}e.create=function(e,r){if(e===void 0||e===``)throw Error(`No input text`);let i=n.M,a,o;return r!==void 0&&(i=n.from(r.errorCorrectionLevel,n.M),a=u.from(r.version),o=s.from(r.maskPattern),r.toSJISFunc&&t.setToSJISFunction(r.toSJISFunc)),S(e,a,i,o)}})),qe=t((e=>{function t(e){if(typeof e==`number`&&(e=e.toString()),typeof e!=`string`)throw Error(`Color should be defined as hex string`);let t=e.slice().replace(`#`,``).split(``);if(t.length<3||t.length===5||t.length>8)throw Error(`Invalid hex color: `+e);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(e){return[e,e]}))),t.length===6&&t.push(`F`,`F`);let n=parseInt(t.join(``),16);return{r:n>>24&255,g:n>>16&255,b:n>>8&255,a:n&255,hex:`#`+t.slice(0,6).join(``)}}e.getOptions=function(e){e||={},e.color||={};let n=e.margin===void 0||e.margin===null||e.margin<0?4:e.margin,r=e.width&&e.width>=21?e.width:void 0,i=e.scale||4;return{width:r,scale:r?4:i,margin:n,color:{dark:t(e.color.dark||`#000000ff`),light:t(e.color.light||`#ffffffff`)},type:e.type,rendererOpts:e.rendererOpts||{}}},e.getScale=function(e,t){return t.width&&t.width>=e+t.margin*2?t.width/(e+t.margin*2):t.scale},e.getImageWidth=function(t,n){let r=e.getScale(t,n);return Math.floor((t+n.margin*2)*r)},e.qrToImageData=function(t,n,r){let i=n.modules.size,a=n.modules.data,o=e.getScale(i,r),s=Math.floor((i+r.margin*2)*o),c=r.margin*o,l=[r.color.light,r.color.dark];for(let e=0;e<s;e++)for(let n=0;n<s;n++){let u=(e*s+n)*4,d=r.color.light;if(e>=c&&n>=c&&e<s-c&&n<s-c){let t=Math.floor((e-c)/o),r=Math.floor((n-c)/o);d=l[+!!a[t*i+r]]}t[u++]=d.r,t[u++]=d.g,t[u++]=d.b,t[u]=d.a}}})),Je=t((e=>{var t=qe();function n(e,t,n){e.clearRect(0,0,t.width,t.height),t.style||={},t.height=n,t.width=n,t.style.height=n+`px`,t.style.width=n+`px`}function r(){try{return document.createElement(`canvas`)}catch{throw Error(`You need to specify a canvas element`)}}e.render=function(e,i,a){let o=a,s=i;o===void 0&&(!i||!i.getContext)&&(o=i,i=void 0),i||(s=r()),o=t.getOptions(o);let c=t.getImageWidth(e.modules.size,o),l=s.getContext(`2d`),u=l.createImageData(c,c);return t.qrToImageData(u.data,e,o),n(l,s,c),l.putImageData(u,0,0),s},e.renderToDataURL=function(t,n,r){let i=r;i===void 0&&(!n||!n.getContext)&&(i=n,n=void 0),i||={};let a=e.render(t,n,i),o=i.type||`image/png`,s=i.rendererOpts||{};return a.toDataURL(o,s.quality)}})),J=t((e=>{var t=qe();function n(e,t){let n=e.a/255,r=t+`="`+e.hex+`"`;return n<1?r+` `+t+`-opacity="`+n.toFixed(2).slice(1)+`"`:r}function r(e,t,n){let r=e+t;return n!==void 0&&(r+=` `+n),r}function i(e,t,n){let i=``,a=0,o=!1,s=0;for(let c=0;c<e.length;c++){let l=Math.floor(c%t),u=Math.floor(c/t);!l&&!o&&(o=!0),e[c]?(s++,c>0&&l>0&&e[c-1]||(i+=o?r(`M`,l+n,.5+u+n):r(`m`,a,0),a=0,o=!1),l+1<t&&e[c+1]||(i+=r(`h`,s),s=0)):a++}return i}e.render=function(e,r,a){let o=t.getOptions(r),s=e.modules.size,c=e.modules.data,l=s+o.margin*2,u=o.color.light.a?`<path `+n(o.color.light,`fill`)+` d="M0 0h`+l+`v`+l+`H0z"/>`:``,d=`<path `+n(o.color.dark,`stroke`)+` d="`+i(c,s,o.margin)+`"/>`,f=`viewBox="0 0 `+l+` `+l+`"`,p=`<svg xmlns="http://www.w3.org/2000/svg" `+(o.width?`width="`+o.width+`" height="`+o.width+`" `:``)+f+` shape-rendering="crispEdges">`+u+d+`</svg>
|
|
8
|
-
`;return typeof a==`function`&&a(null,p),p}})),Ye=e(t((e=>{var t=R(),n=q(),r=Je(),i=J();function a(e,r,i,a,o){let s=[].slice.call(arguments,1),c=s.length,l=typeof s[c-1]==`function`;if(!l&&!t())throw Error(`Callback required as last argument`);if(l){if(c<2)throw Error(`Too few arguments provided`);c===2?(o=i,i=r,r=a=void 0):c===3&&(r.getContext&&o===void 0?(o=a,a=void 0):(o=a,a=i,i=r,r=void 0))}else{if(c<1)throw Error(`Too few arguments provided`);return c===1?(i=r,r=a=void 0):c===2&&!r.getContext&&(a=i,i=r,r=void 0),new Promise(function(t,o){try{t(e(n.create(i,a),r,a))}catch(e){o(e)}})}try{let t=n.create(i,a);o(null,e(t,r,a))}catch(e){o(e)}}e.create=n.create,e.toCanvas=a.bind(null,r.render),e.toDataURL=a.bind(null,r.renderToDataURL),e.toString=a.bind(null,function(e,t,n){return i.render(e,n)})}))(),1);function Xe({open:e,onOpenChange:t,ch:n,onLoginSuccess:r,moreSettings:i}){let[a,o]=(0,k.useState)(!1),[s,l]=(0,k.useState)(null),[d,f]=(0,k.useState)(null),[p,m]=(0,k.useState)(null),[h,v]=(0,k.useState)(null),[y,b]=(0,k.useState)(null),[S,w]=(0,k.useState)(!1),T=(0,k.useCallback)(async()=>{m(null),v(null),l(null),o(!0);try{let e=await ye();f(e.qrcodeUrl),l(e.sessionKey)}catch(e){m(e instanceof Error?e.message:`Start failed`)}finally{o(!1)}},[]);(0,k.useEffect)(()=>{if(!e){l(null),f(null),m(null),b(null),w(!1),v(null);return}T()},[e,T]),(0,k.useEffect)(()=>{if(!s)return;let e=!1,i,a=async()=>{try{let a=await be(s);if(e)return;if(a.phase===`polling`){f(a.qrcodeUrl),a.qrStatus===`scaned`?v(n.weixinQrLoginScanned):v(null);return}if(a.phase===`done`){i!==void 0&&(window.clearInterval(i),i=void 0),l(null),a.ok?(f(null),t(!1),await r()):(m(a.message),f(null));return}a.phase===`unknown`&&v(null)}catch(t){e||(i!==void 0&&window.clearInterval(i),m(t instanceof Error?t.message:`Request failed`),l(null),f(null))}};return i=window.setInterval(()=>void a(),2e3),a(),()=>{e=!0,i!==void 0&&window.clearInterval(i)}},[s,n.weixinQrLoginScanned,n.weixinQrLoginSuccess,r,t]),(0,k.useEffect)(()=>{if(!d){b(null),w(!1);return}let e=!1;return w(!1),Ye.toDataURL(d,{width:208,margin:2,errorCorrectionLevel:`M`,color:{dark:`#000000ff`,light:`#ffffffff`}}).then(t=>{e||b(t)}).catch(()=>{e||(w(!0),b(null))}),()=>{e=!0}},[d]);let te=!!(d&&s);return(0,P.jsx)(C,{open:e,onOpenChange:t,children:(0,P.jsxs)(ce,{children:[(0,P.jsx)(ne,{className:`xopc-dialog-overlay fixed inset-0 z-[60] bg-scrim backdrop-blur-[1px]`}),(0,P.jsxs)(ae,{className:_(`fixed left-1/2 top-1/2 z-[60] max-h-[min(90vh,52rem)] w-[min(100%-2rem,32rem)] -translate-x-1/2 -translate-y-1/2`,`overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge`),onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsx)(re,{asChild:!0,children:(0,P.jsx)(`button`,{type:`button`,className:`absolute right-3 top-3 z-20 rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40`,"aria-label":n.weixinQrModalCloseAria,children:(0,P.jsx)(u,{className:`size-4`})})}),(0,P.jsx)(ee,{className:`sr-only`,children:n.weixinQrModalTitle}),(0,P.jsx)(x,{className:`sr-only`,children:n.weixinQrModalSubtitle}),(0,P.jsxs)(`div`,{className:`text-center`,children:[(0,P.jsx)(`p`,{className:`text-lg font-semibold tracking-tight text-fg`,children:n.weixinQrModalTitle}),(0,P.jsx)(`p`,{className:`mt-1.5 text-sm text-fg-muted`,children:n.weixinQrModalSubtitle})]}),(0,P.jsxs)(`div`,{className:`mt-6 flex min-h-[200px] flex-col items-center justify-center`,children:[a&&!te?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:n.weixinQrLoginBusy}):null,p?(0,P.jsx)(`p`,{className:`text-center text-sm text-red-600 dark:text-red-400`,children:p}):null,h&&!p?(0,P.jsx)(`p`,{className:`mb-3 text-center text-sm text-accent`,children:h}):null,te&&d&&!p?(0,P.jsxs)(`div`,{className:`flex w-full flex-col items-center gap-3`,children:[y&&!S?(0,P.jsx)(`img`,{src:y,alt:``,className:`h-52 w-52 rounded-lg border border-edge-subtle bg-white object-contain p-3 dark:border-edge`}):null,!y&&!S?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:n.weixinQrEncoding}):null,S?(0,P.jsxs)(`div`,{className:`flex w-full flex-col items-center gap-3`,children:[(0,P.jsx)(`p`,{className:`max-w-[16rem] text-center text-sm text-fg-muted`,children:n.weixinQrImageError}),(0,P.jsxs)(`a`,{href:d,target:`_blank`,rel:`noreferrer`,className:`inline-flex items-center gap-1.5 text-sm text-accent underline-offset-2 hover:underline`,children:[(0,P.jsx)(c,{className:`size-3.5 shrink-0`}),n.weixinQrOpenLink]})]}):null]}):null]}),(0,P.jsx)(`div`,{className:`mt-6`,children:(0,P.jsx)(g,{type:`button`,variant:`secondary`,className:`h-11 w-full rounded-full border-0 bg-fg text-surface-panel hover:opacity-90 dark:bg-fg dark:text-surface-panel`,disabled:a,onClick:()=>void T(),children:a?n.weixinQrLoginBusy:n.weixinQrRegenerate})}),i?(0,P.jsx)(`div`,{className:`mt-6 border-t border-edge-subtle pt-4 dark:border-edge-subtle`,children:i}):null]})]})})}function Ze(){let e=Se,t=d(e=>e.language),n=o(t),r=n.channelsSettings,s=!!f(e=>e.token),[p,m]=(0,k.useState)(null),[v,y]=(0,k.useState)(null),[w,E]=(0,k.useState)(!1),[le,D]=(0,k.useState)(null),[ue,O]=(0,k.useState)(!1),[de,fe]=(0,k.useState)(!1),[pe,A]=(0,k.useState)(!1),[me,j]=(0,k.useState)(!1),[M,N]=(0,k.useState)(null),[ye,be]=(0,k.useState)(null),[Ce,L]=(0,k.useState)(!1),[R,z]=(0,k.useState)(!1),[B,Ne]=(0,k.useState)(!1),[Pe,Fe]=(0,k.useState)(!1),[Ie,Le]=(0,k.useState)(!1),[Re,ze]=(0,k.useState)(!1),[Be,Ve]=(0,k.useState)(!1),[He,V]=(0,k.useState)(``),[H,U]=(0,k.useState)(``),[Ue,W]=(0,k.useState)(``),[We,G]=(0,k.useState)(``),[Ge,K]=(0,k.useState)(``),[Ke,q]=(0,k.useState)(``),{data:qe}=i(s?`gateway-chat-agents-ch`:null,oe,{revalidateOnFocus:!1}),{data:Je,error:J,isLoading:Ye,mutate:Ze}=se(s),Y=(0,k.useMemo)(()=>Je?.payload?.config===void 0?null:ve(Je.payload.config),[Je]),Qe=(0,k.useMemo)(()=>!p||!v?!1:JSON.stringify(p)!==JSON.stringify(v),[p,v]);(0,k.useEffect)(()=>{if(!s){m(null),y(null);return}Y!==null&&(Qe||(m(Y),y(structuredClone(Y)),V(JSON.stringify(Y.telegram.accounts??{},null,2)),U(``),W(JSON.stringify(Y.weixin.accounts??{},null,2)),G(``),K(JSON.stringify(Y.feishu?.accounts??{},null,2)),q(``),O(!1)))},[s,Y,Qe]);let $e=!!(s&&Ye&&Je===void 0&&!J),et=J instanceof Error?J.message:J?String(J):null,tt=(0,k.useCallback)((e,t,n)=>{m(r=>{if(!r)return null;let i=e===`telegram`?`telegram`:e===`weixin`?`weixin`:`feishu`;return{...r,channelAgentRoutes:{...r.channelAgentRoutes,[i]:{...r.channelAgentRoutes[i],[t]:n.trim().toLowerCase()}}}})},[]),X=(0,k.useCallback)(e=>{m(t=>t?{...t,telegram:{...t.telegram,...e}}:null)},[]),nt=(0,k.useCallback)(e=>{m(t=>t?{...t,weixin:{...t.weixin,...e}}:null)},[]),Z=(0,k.useCallback)(e=>{m(t=>t?{...t,feishu:{...t.feishu,...e}}:null)},[]),rt=(0,k.useCallback)(async()=>{if(!p||w)return!1;E(!0),D(null),O(!1);try{let e=await xe(p);m(e);let t=structuredClone(e);return y(t),V(JSON.stringify(t.telegram.accounts??{},null,2)),U(``),W(JSON.stringify(t.weixin.accounts??{},null,2)),G(``),K(JSON.stringify(t.feishu?.accounts??{},null,2)),q(``),O(!0),window.setTimeout(()=>O(!1),2500),!0}catch(e){return D(e instanceof Error?e.message:r.saveError),!1}finally{E(!1)}},[p,w,r.saveError]),it=(0,k.useCallback)(async(e,t)=>{if(!p||w)return;let n=p,i=e===`weixin`?{...p,weixin:{...p.weixin,enabled:t}}:e===`telegram`?{...p,telegram:{...p.telegram,enabled:t}}:{...p,feishu:{...p.feishu,enabled:t}};m(i),E(!0),D(null);try{let e=await xe(i);m(e);let t=structuredClone(e);y(t),V(JSON.stringify(t.telegram.accounts??{},null,2)),W(JSON.stringify(t.weixin.accounts??{},null,2)),K(JSON.stringify(t.feishu?.accounts??{},null,2))}catch(e){D(e instanceof Error?e.message:r.saveError),m(n)}finally{E(!1)}},[p,w,r.saveError]),at=(0,k.useCallback)(async()=>{if(!p||!M||w)return;let e=_e(),t=M===`weixin`?{...p,weixin:e.weixin}:M===`telegram`?{...p,telegram:e.telegram}:{...p,feishu:e.feishu};E(!0),D(null);try{let e=await xe(t);m(e);let n=structuredClone(e);y(n),V(JSON.stringify(n.telegram.accounts??{},null,2)),W(JSON.stringify(n.weixin.accounts??{},null,2)),U(``),G(``),K(JSON.stringify(n.feishu?.accounts??{},null,2)),q(``),N(null),O(!0),window.setTimeout(()=>O(!1),2500)}catch(e){D(e instanceof Error?e.message:r.saveError)}finally{E(!1)}},[p,M,w,r.saveError]),ot=(0,k.useCallback)(async()=>{let e=p?.telegram.botToken;e&&(await navigator.clipboard.writeText(e).catch(()=>{}),Le(!0),window.setTimeout(()=>Le(!1),2e3))},[p?.telegram.botToken]),st=(0,k.useCallback)(async()=>{let e=p?.feishu?.appSecret;e&&(await navigator.clipboard.writeText(e).catch(()=>{}),ze(!0),window.setTimeout(()=>ze(!1),2e3))},[p]),ct=(0,k.useCallback)(async()=>{let e=p?.feishu;if(!e)return;let t={connectionMode:e.connectionMode,verificationToken:e.verificationToken||``,encryptKey:e.encryptKey||``,webhookHost:e.webhookHost||``,webhookPort:e.webhookPort||0,webhookPath:e.webhookPath||``};await navigator.clipboard.writeText(JSON.stringify(t,null,2)).catch(()=>{}),Ve(!0),window.setTimeout(()=>Ve(!1),2e3)},[p]),lt=(0,k.useCallback)(()=>{if(!p)return;let e=He.trim();if(!e){X({accounts:{}}),U(``);return}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw Error(r.jsonObjectAccounts);X({accounts:t}),U(``)}catch(e){U(e instanceof Error?e.message:r.jsonInvalid)}},[p,He,X,r.jsonObjectAccounts,r.jsonInvalid]),ut=(0,k.useCallback)(()=>{if(!p)return;let e=Ue.trim();if(!e){nt({accounts:{}}),G(``);return}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw Error(r.jsonObjectAccounts);nt({accounts:t}),G(``)}catch(e){G(e instanceof Error?e.message:r.jsonInvalid)}},[p,Ue,nt,r.jsonObjectAccounts,r.jsonInvalid]),dt=(0,k.useCallback)(()=>{if(!p)return;let e=Ge.trim();if(!e){Z({accounts:{}}),q(``);return}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw Error(r.jsonObjectAccounts);Z({accounts:t}),q(``)}catch(e){q(e instanceof Error?e.message:r.jsonInvalid)}},[p,Ge,Z,r.jsonObjectAccounts,r.jsonInvalid]),ft=(0,k.useMemo)(()=>[`pairing`,`allowlist`,`open`,`disabled`].map(e=>({value:e,label:r.policy.dm[e]})),[r.policy.dm]),pt=(0,k.useMemo)(()=>[`open`,`disabled`,`allowlist`].map(e=>({value:e,label:r.policy.group[e]})),[r.policy.group]),mt=(0,k.useMemo)(()=>[`off`,`first`,`all`].map(e=>({value:e,label:r.policy.reply[e]})),[r.policy.reply]),ht=(0,k.useMemo)(()=>[`off`,`partial`,`block`].map(e=>({value:e,label:r.policy.stream[e]})),[r.policy.stream]);if(!s)return(0,P.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:[(0,P.jsx)(`h1`,{className:`text-lg font-semibold text-fg`,children:n.settingsSections.channels}),(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:r.needToken})]});if($e)return(0,P.jsxs)(`div`,{className:`mx-auto w-full max-w-app-main px-4 py-8`,children:[(0,P.jsx)(`div`,{className:`h-8 w-48 animate-pulse rounded bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mt-6 h-32 animate-pulse rounded-xl bg-surface-hover`}),(0,P.jsx)(`p`,{className:`mt-4 text-sm text-fg-muted`,children:r.loading})]});if(!p)return(0,P.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-8`,children:[(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:le??et??r.loadError}),(0,P.jsx)(g,{type:`button`,variant:`secondary`,onClick:()=>void Ze(),children:r.retry})]});let Q=p.telegram,gt=p.weixin,$=p.feishu,_t=De(gt),vt=Ee(Q),yt=Oe($),bt=(0,P.jsxs)(`details`,{className:`group rounded-xl border border-edge-subtle bg-surface-base open:pb-3 dark:border-edge`,children:[(0,P.jsx)(`summary`,{className:`cursor-pointer list-none px-3 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-surface-hover [&::-webkit-details-marker]:hidden`,children:(0,P.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,P.jsx)(S,{className:`size-4 shrink-0 text-fg-muted transition-transform group-open:rotate-180`}),r.advancedShow]})}),(0,P.jsxs)(`div`,{className:`space-y-4 border-t border-edge-subtle px-3 pb-3 pt-3 dark:border-edge-subtle`,children:[(0,P.jsx)(`p`,{className:`text-xs leading-relaxed text-fg-muted`,children:r.weixinAdvancedHint}),(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-start gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox mt-0.5`,checked:gt.enabled,onChange:e=>nt({enabled:e.target.checked})}),(0,P.jsx)(`span`,{children:r.enableWeixinAria})]}),(0,P.jsx)(`div`,{className:`[&>div]:border-0 [&>div]:pt-0`,children:(0,P.jsx)(Me,{wx:gt,updateWeixin:nt,ch:r,dmOpts:ft,streamOpts:ht,wxAccountsDraft:Ue,setWxAccountsDraft:W,wxAccountsError:We,onWxAccountsBlur:ut,channelAgentRoutesWx:p.channelAgentRoutes.weixin,defaultAgentId:p.defaultAgentId,agentItems:qe?.items??[],onAgentRouteChange:(e,t)=>tt(`weixin`,e,t),routingDisabled:w})}),(0,P.jsx)(g,{type:`button`,variant:`primary`,className:`w-full`,disabled:!Qe||w,onClick:async()=>{await rt()},children:w?r.saving:r.save})]})]});return(0,P.jsx)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6`,children:(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`header`,{className:`flex flex-col gap-1`,children:[(0,P.jsx)(`h1`,{className:`text-lg font-semibold tracking-tight text-fg`,children:n.settingsSections.channels}),(0,P.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:r.subtitle}),(0,P.jsxs)(`a`,{href:te(t,`channels`),target:`_blank`,rel:`noreferrer`,className:`mt-1 inline-flex items-center gap-1 text-sm text-accent hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40`,children:[r.docsLink,(0,P.jsx)(c,{className:`size-3.5`})]})]}),Qe?(0,P.jsx)(`p`,{className:`text-xs text-amber-800 dark:text-amber-200`,children:r.unsavedHint}):null,ue?(0,P.jsx)(`p`,{className:`text-xs text-fg-muted`,children:r.saved}):null,le?(0,P.jsx)(`p`,{className:`text-sm text-red-600 dark:text-red-400`,children:le}):null,ye?(0,P.jsx)(`p`,{className:`text-xs text-accent`,children:ye}):null,(0,P.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,P.jsx)(Ae,{icon:(0,P.jsx)(h,{className:`size-6 text-accent`,strokeWidth:1.75}),title:r.weixinTitle,subtitle:r.weixinSubtitle,configured:_t,enabled:gt.enabled,toggleDisabled:w,onToggle:e=>void it(`weixin`,e),onConfigure:()=>fe(!0),onEdit:()=>fe(!0),onRemove:()=>N(`weixin`),ch:r}),(0,P.jsx)(Ae,{icon:(0,P.jsx)(b,{className:`size-6 text-accent`,strokeWidth:1.75}),title:r.telegramTitle,subtitle:r.telegramSubtitle,configured:vt,enabled:Q.enabled,toggleDisabled:w,onToggle:e=>void it(`telegram`,e),onConfigure:()=>A(!0),onEdit:()=>A(!0),onRemove:()=>N(`telegram`),ch:r}),(0,P.jsx)(Ae,{icon:(0,P.jsx)(h,{className:`size-6 text-accent`,strokeWidth:1.75}),title:r.feishuTitle,subtitle:r.feishuSubtitle,configured:yt,enabled:$.enabled,toggleDisabled:w,onToggle:e=>void it(`feishu`,e),onConfigure:()=>j(!0),onEdit:()=>j(!0),onRemove:()=>N(`feishu`),ch:r})]}),(0,P.jsx)(Xe,{open:de,onOpenChange:fe,ch:r,onLoginSuccess:async()=>{await Ze(),be(r.weixinQrLoginSuccess),window.setTimeout(()=>be(null),4e3)},moreSettings:bt}),(0,P.jsx)(C,{open:pe,onOpenChange:A,children:(0,P.jsxs)(ce,{children:[(0,P.jsx)(ne,{className:`xopc-dialog-overlay fixed inset-0 z-[60] bg-scrim backdrop-blur-[1px]`}),(0,P.jsxs)(ae,{className:_(`fixed left-1/2 top-1/2 z-[60] max-h-[min(90vh,48rem)] w-[min(100%-2rem,36rem)] -translate-x-1/2 -translate-y-1/2`,`overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge`),onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(ee,{className:`text-lg font-semibold tracking-tight text-fg`,children:r.telegramTitle}),(0,P.jsx)(x,{className:`mt-1 text-sm text-fg-muted`,children:r.telegramSubtitle})]}),(0,P.jsx)(re,{asChild:!0,children:(0,P.jsx)(`button`,{type:`button`,className:`rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40`,"aria-label":r.modalCancel,children:(0,P.jsx)(u,{className:`size-4`})})})]}),(0,P.jsxs)(`label`,{className:`mt-6 flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:Q.enabled,onChange:e=>X({enabled:e.target.checked})}),(0,P.jsx)(`span`,{children:r.enableTelegramAria})]}),(0,P.jsxs)(`div`,{className:`mt-6 space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsxs)(F,{children:[r.telegramToken,(0,P.jsx)(`span`,{className:`text-red-600 dark:text-red-400`,children:` *`})]}),(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:R?`text`:`password`,autoComplete:`off`,readOnly:!R&&!!Q.botToken,value:R?Q.botToken:Q.botToken?`*`.repeat(Math.max(1,Q.botToken.length)):``,onChange:e=>{!R&&Q.botToken||X({botToken:e.target.value})},placeholder:`123456789:ABCdefGHIjklMNOpqrsTUVwxyz`}),Q.botToken?(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>void ot(),children:[Ie?(0,P.jsx)(T,{className:`size-3.5`}):(0,P.jsx)(a,{className:`size-3.5`}),Ie?r.copied:r.copy]}):null,(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>z(e=>!e),children:[R?(0,P.jsx)(ie,{className:`size-3.5`}):(0,P.jsx)(l,{className:`size-3.5`}),R?r.hide:r.show]})]}),(0,P.jsx)(I,{children:r.telegramTokenDesc})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.allowFromDm}),(0,P.jsx)(`textarea`,{className:_(e(),`min-h-[2.75rem] resize-y font-mono text-xs`),rows:2,placeholder:`123456789, 987654321`,value:Te(Q.allowFrom),onChange:e=>X({allowFrom:we(e.target.value)})}),(0,P.jsx)(I,{children:r.allowFromDmDesc})]}),p?(0,P.jsx)(ke,{accountIds:he(Q),routes:p.channelAgentRoutes.telegram,defaultAgentId:p.defaultAgentId,agentItems:qe?.items??[],disabled:w,onChange:(e,t)=>tt(`telegram`,e,t),ch:r}):null,(0,P.jsxs)(g,{type:`button`,variant:`ghost`,className:`-ml-2 h-auto justify-start px-2 py-1 text-sm text-fg-muted hover:text-fg`,onClick:()=>L(e=>!e),children:[(0,P.jsx)(S,{className:_(`mr-1 size-4 transition-transform`,Ce&&`rotate-180`)}),Ce?r.advancedHide:r.advancedShow]}),Ce?(0,P.jsx)(je,{tg:Q,updateTelegram:X,ch:r,dmOpts:ft,groupOpts:pt,replyOpts:mt,streamOpts:ht,tgAccountsDraft:He,setTgAccountsDraft:V,tgAccountsError:H,onTgAccountsBlur:lt}):null]}),(0,P.jsxs)(`div`,{className:`mt-8 flex flex-wrap justify-end gap-2 border-t border-edge-subtle pt-4 dark:border-edge-subtle`,children:[(0,P.jsx)(g,{type:`button`,variant:`secondary`,onClick:()=>A(!1),children:r.modalCancel}),(0,P.jsx)(g,{type:`button`,variant:`primary`,disabled:!Qe||w,onClick:async()=>{await rt()&&A(!1)},children:w?r.saving:r.save})]})]})]})}),(0,P.jsx)(C,{open:me,onOpenChange:j,children:(0,P.jsxs)(ce,{children:[(0,P.jsx)(ne,{className:`xopc-dialog-overlay fixed inset-0 z-[60] bg-scrim backdrop-blur-[1px]`}),(0,P.jsxs)(ae,{className:_(`fixed left-1/2 top-1/2 z-[60] max-h-[min(90vh,48rem)] w-[min(100%-2rem,36rem)] -translate-x-1/2 -translate-y-1/2`,`overflow-y-auto rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge`),onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,P.jsxs)(`div`,{children:[(0,P.jsx)(ee,{className:`text-lg font-semibold tracking-tight text-fg`,children:r.feishuTitle}),(0,P.jsx)(x,{className:`mt-1 text-sm text-fg-muted`,children:r.feishuSubtitle})]}),(0,P.jsx)(re,{asChild:!0,children:(0,P.jsx)(`button`,{type:`button`,className:`rounded-lg p-1.5 text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40`,"aria-label":r.modalCancel,children:(0,P.jsx)(u,{className:`size-4`})})})]}),(0,P.jsxs)(`label`,{className:`mt-6 flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:$.enabled,onChange:e=>Z({enabled:e.target.checked})}),(0,P.jsx)(`span`,{children:r.enableFeishuAria})]}),(0,P.jsxs)(`div`,{className:`mt-6 space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsxs)(F,{children:[r.feishuAppId,(0,P.jsx)(`span`,{className:`text-red-600 dark:text-red-400`,children:` *`})]}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),value:$.appId,onChange:e=>Z({appId:e.target.value}),placeholder:`cli_xxx`}),(0,P.jsx)(I,{children:r.feishuAppIdDesc})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsxs)(F,{children:[r.feishuAppSecret,(0,P.jsx)(`span`,{className:`text-red-600 dark:text-red-400`,children:` *`})]}),(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:B?`text`:`password`,autoComplete:`off`,readOnly:!B&&!!$.appSecret,value:B?$.appSecret:$.appSecret?`*`.repeat(Math.max(1,$.appSecret.length)):``,onChange:e=>{!B&&$.appSecret||Z({appSecret:e.target.value})},placeholder:`••••••••`}),$.appSecret?(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>void st(),children:[Re?(0,P.jsx)(T,{className:`size-3.5`}):(0,P.jsx)(a,{className:`size-3.5`}),Re?r.copied:r.copy]}):null,(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>Ne(e=>!e),children:[B?(0,P.jsx)(ie,{className:`size-3.5`}):(0,P.jsx)(l,{className:`size-3.5`}),B?r.hide:r.show]})]}),(0,P.jsx)(I,{children:r.feishuAppSecretDesc})]}),(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.feishuDomain}),(0,P.jsxs)(`select`,{className:e(),value:String($.domain||`feishu`),onChange:e=>Z({domain:e.target.value}),children:[(0,P.jsx)(`option`,{value:`feishu`,children:`feishu`}),(0,P.jsx)(`option`,{value:`lark`,children:`lark`})]})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.connectionMode}),(0,P.jsxs)(`select`,{className:e(),value:$.connectionMode,onChange:e=>Z({connectionMode:e.target.value}),children:[(0,P.jsx)(`option`,{value:`websocket`,children:`websocket`}),(0,P.jsx)(`option`,{value:`webhook`,children:`webhook`})]}),(0,P.jsx)(I,{children:r.connectionModeDesc})]})]}),$.connectionMode===`webhook`?(0,P.jsxs)(`div`,{className:`rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,P.jsx)(`div`,{className:`text-sm font-medium text-fg`,children:r.webhookTitle}),(0,P.jsxs)(`div`,{className:`flex gap-2`,children:[(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>Fe(e=>!e),children:[Pe?(0,P.jsx)(ie,{className:`size-3.5`}):(0,P.jsx)(l,{className:`size-3.5`}),Pe?r.hide:r.show]}),(0,P.jsxs)(g,{type:`button`,variant:`secondary`,className:`px-2 py-1 text-xs`,onClick:()=>void ct(),children:[Be?(0,P.jsx)(T,{className:`size-3.5`}):(0,P.jsx)(a,{className:`size-3.5`}),Be?r.copied:r.copy]})]})]}),(0,P.jsxs)(`div`,{className:`mt-3 grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.verificationToken}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:Pe?`text`:`password`,autoComplete:`off`,value:$.verificationToken??``,onChange:e=>Z({verificationToken:e.target.value})}),(0,P.jsx)(I,{children:r.verificationTokenDesc})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.encryptKey}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:Pe?`text`:`password`,autoComplete:`off`,value:$.encryptKey??``,onChange:e=>Z({encryptKey:e.target.value})}),(0,P.jsx)(I,{children:r.encryptKeyDesc})]})]}),(0,P.jsxs)(`div`,{className:`mt-3 grid gap-3 sm:grid-cols-3`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5 sm:col-span-2`,children:[(0,P.jsx)(F,{children:r.webhookHost}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),value:$.webhookHost??``,onChange:e=>Z({webhookHost:e.target.value}),placeholder:`127.0.0.1`})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.webhookPort}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:`number`,inputMode:`numeric`,value:String($.webhookPort??``),onChange:e=>Z({webhookPort:Number(e.target.value||`0`)||0}),placeholder:`3000`})]})]}),(0,P.jsxs)(`div`,{className:`mt-3 flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.webhookPath}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),value:$.webhookPath??``,onChange:e=>Z({webhookPath:e.target.value}),placeholder:`/feishu/events`}),(0,P.jsx)(I,{children:r.webhookPathDesc})]})]}):null,(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.renderMode}),(0,P.jsxs)(`select`,{className:e(),value:$.renderMode,onChange:e=>Z({renderMode:e.target.value}),children:[(0,P.jsx)(`option`,{value:`auto`,children:`auto`}),(0,P.jsx)(`option`,{value:`raw`,children:`raw`}),(0,P.jsx)(`option`,{value:`card`,children:`card`})]})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.reactionNotifications}),(0,P.jsxs)(`select`,{className:e(),value:$.reactionNotifications,onChange:e=>Z({reactionNotifications:e.target.value}),children:[(0,P.jsx)(`option`,{value:`off`,children:`off`}),(0,P.jsx)(`option`,{value:`own`,children:`own`}),(0,P.jsx)(`option`,{value:`all`,children:`all`})]})]})]}),(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:$.streaming,onChange:e=>Z({streaming:e.target.checked})}),r.enableStreaming]}),(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.dmPolicy}),(0,P.jsx)(`select`,{className:e(),value:$.dmPolicy,onChange:e=>Z({dmPolicy:e.target.value}),children:ft.map(e=>(0,P.jsx)(`option`,{value:e.value,children:e.label},e.value))})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.groupPolicy}),(0,P.jsx)(`select`,{className:e(),value:$.groupPolicy,onChange:e=>Z({groupPolicy:e.target.value}),children:pt.map(e=>(0,P.jsx)(`option`,{value:e.value,children:e.label},e.value))})]})]}),(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:$.requireMention,onChange:e=>Z({requireMention:e.target.checked})}),r.requireMention]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.allowFromDm}),(0,P.jsx)(`textarea`,{className:_(e(),`min-h-[2.75rem] resize-y font-mono text-xs`),rows:2,placeholder:`ou_xxx, on_xxx`,value:Te($.allowFrom),onChange:e=>Z({allowFrom:we(e.target.value)})}),(0,P.jsx)(I,{children:r.allowFromDmDesc})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.allowFromGroups}),(0,P.jsx)(`textarea`,{className:_(e(),`min-h-[2.75rem] resize-y font-mono text-xs`),rows:2,placeholder:`oc_xxx, oc_yyy`,value:Te($.groupAllowFrom),onChange:e=>Z({groupAllowFrom:we(e.target.value)})}),(0,P.jsx)(I,{children:r.allowFromGroupsDesc})]}),(0,P.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.historyLimit}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:`number`,inputMode:`numeric`,value:String($.historyLimit),onChange:e=>Z({historyLimit:Number(e.target.value||`0`)||0})})]}),(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.textChunkLimit}),(0,P.jsx)(`input`,{className:_(e(),`min-w-0 flex-1 font-mono text-xs`),type:`number`,inputMode:`numeric`,value:String($.textChunkLimit),onChange:e=>Z({textChunkLimit:Number(e.target.value||`0`)||0})})]})]}),(0,P.jsxs)(`div`,{className:`rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle`,children:[(0,P.jsx)(`div`,{className:`text-sm font-medium text-fg`,children:r.feishuToolsTitle}),(0,P.jsx)(`div`,{className:`mt-2 grid gap-2 sm:grid-cols-2`,children:[[`doc`,r.feishuToolDoc],[`wiki`,r.feishuToolWiki],[`drive`,r.feishuToolDrive],[`perm`,r.feishuToolPerm],[`bitable`,r.feishuToolBitable],[`scopes`,r.feishuToolScopes]].map(([e,t])=>(0,P.jsxs)(`label`,{className:`flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:!!$.tools?.[e],onChange:t=>Z({tools:{...$.tools,[e]:t.target.checked}})}),t]},e))}),(0,P.jsx)(`div`,{className:`mt-2`,children:(0,P.jsx)(I,{children:r.feishuToolsDesc})})]}),(0,P.jsxs)(`div`,{className:`rounded-xl border border-edge-subtle bg-surface px-4 py-3 dark:border-edge-subtle`,children:[(0,P.jsx)(`div`,{className:`text-sm font-medium text-fg`,children:r.feishuActionsTitle}),(0,P.jsxs)(`label`,{className:`mt-2 flex cursor-pointer items-center gap-2 text-sm text-fg`,children:[(0,P.jsx)(`input`,{type:`checkbox`,className:`ui-checkbox`,checked:!!$.actions?.reactions,onChange:e=>Z({actions:{...$.actions,reactions:e.target.checked}})}),r.feishuActionReactions]})]}),p?(0,P.jsx)(ke,{accountIds:ge($),routes:p.channelAgentRoutes.feishu,defaultAgentId:p.defaultAgentId,agentItems:qe?.items??[],disabled:w,onChange:(e,t)=>tt(`feishu`,e,t),ch:r}):null,(0,P.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,P.jsx)(F,{children:r.multiAccountJson}),(0,P.jsx)(`textarea`,{className:_(e(),`min-h-[140px] resize-y font-mono text-xs`),spellCheck:!1,value:Ge,onChange:e=>K(e.target.value),onBlur:dt,placeholder:`{ "default": { "appId": "...", "appSecret": "...", "enabled": true } }`}),Ke?(0,P.jsx)(`p`,{className:`text-xs text-red-600 dark:text-red-400`,children:Ke}):(0,P.jsx)(I,{children:r.multiAccountJsonDesc})]})]}),(0,P.jsxs)(`div`,{className:`mt-8 flex flex-wrap justify-end gap-2 border-t border-edge-subtle pt-4 dark:border-edge-subtle`,children:[(0,P.jsx)(g,{type:`button`,variant:`secondary`,onClick:()=>j(!1),children:r.modalCancel}),(0,P.jsx)(g,{type:`button`,variant:`primary`,disabled:!Qe||w,onClick:async()=>{await rt()&&j(!1)},children:w?r.saving:r.save})]})]})]})}),(0,P.jsx)(C,{open:M!==null,onOpenChange:e=>!e&&N(null),children:(0,P.jsxs)(ce,{children:[(0,P.jsx)(ne,{className:`xopc-dialog-overlay fixed inset-0 z-[70] bg-scrim backdrop-blur-[1px]`}),(0,P.jsxs)(ae,{className:_(`fixed left-1/2 top-1/2 z-[70] w-[min(100%-2rem,28rem)] -translate-x-1/2 -translate-y-1/2`,`rounded-2xl border border-edge bg-surface-panel p-6 shadow-popover outline-none dark:border-edge`),onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsx)(ee,{className:`text-base font-semibold text-fg`,children:r.removeChannelTitle}),(0,P.jsx)(x,{className:`mt-2 text-sm text-fg-muted`,children:M?r.removeChannelConfirm.replace(`{{name}}`,M===`weixin`?r.weixinTitle:M===`telegram`?r.telegramTitle:r.feishuTitle):`\xA0`}),(0,P.jsxs)(`div`,{className:`mt-6 flex justify-end gap-2`,children:[(0,P.jsx)(g,{type:`button`,variant:`secondary`,onClick:()=>N(null),children:r.modalCancel}),(0,P.jsx)(g,{type:`button`,variant:`secondary`,className:`border-danger/40 bg-danger text-white hover:bg-danger/90 dark:border-danger/40`,disabled:w,onClick:()=>void at(),children:w?r.saving:r.removeChannelAction})]})]})]})})]})})}export{Ze as ChannelsSettingsPanel};
|
|
9
|
-
//# sourceMappingURL=channels-settings-h3eQwIPi.js.map
|