@co0ontty/wand 1.21.9 → 1.21.11
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/config.d.ts +1 -1
- package/dist/config.js +13 -0
- package/dist/env-utils.d.ts +9 -0
- package/dist/env-utils.js +47 -0
- package/dist/process-manager.js +3 -3
- package/dist/server.js +1 -0
- package/dist/structured-session-manager.js +3 -2
- package/dist/types.d.ts +6 -0
- package/dist/web-ui/content/scripts.js +147 -3
- package/dist/web-ui/content/styles.css +116 -0
- package/dist/web-ui/content/vendor/qrcode/qrcode.bundle.js +9 -0
- package/dist/web-ui/index.js +1 -0
- package/package.json +3 -2
package/dist/config.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { WandStorage } from "./storage.js";
|
|
|
7
7
|
* 升级路径:老 JSON 里仍存有这些字段时,首次启动会被搬到 DB(见 migrateLegacyPreferencesToDb),
|
|
8
8
|
* 然后下一次 saveConfig 写回 JSON 时它们会被剥离(见 stripPreferenceFields)。
|
|
9
9
|
*/
|
|
10
|
-
export declare const PREFERENCE_KEYS: readonly ["defaultMode", "defaultCwd", "defaultModel", "structuredRunner", "language", "cardDefaults"];
|
|
10
|
+
export declare const PREFERENCE_KEYS: readonly ["defaultMode", "defaultCwd", "defaultModel", "structuredRunner", "language", "cardDefaults", "inheritEnv"];
|
|
11
11
|
export type PreferenceKey = (typeof PREFERENCE_KEYS)[number];
|
|
12
12
|
export declare function isPreferenceKey(key: string): key is PreferenceKey;
|
|
13
13
|
export declare const defaultConfig: () => WandConfig;
|
package/dist/config.js
CHANGED
|
@@ -19,6 +19,7 @@ export const PREFERENCE_KEYS = [
|
|
|
19
19
|
"structuredRunner",
|
|
20
20
|
"language",
|
|
21
21
|
"cardDefaults",
|
|
22
|
+
"inheritEnv",
|
|
22
23
|
];
|
|
23
24
|
const PREFERENCE_KEY_SET = new Set(PREFERENCE_KEYS);
|
|
24
25
|
function preferenceStorageKey(key) {
|
|
@@ -43,6 +44,7 @@ export const defaultConfig = () => ({
|
|
|
43
44
|
cardDefaults: defaultCardExpandDefaults(),
|
|
44
45
|
defaultModel: "",
|
|
45
46
|
structuredRunner: "cli",
|
|
47
|
+
inheritEnv: true,
|
|
46
48
|
commandPresets: [
|
|
47
49
|
{
|
|
48
50
|
label: "Claude",
|
|
@@ -201,6 +203,10 @@ export function applyStoragePreferences(config, storage) {
|
|
|
201
203
|
const v = storage.getPreference(preferenceStorageKey("cardDefaults"), defaults.cardDefaults);
|
|
202
204
|
config.cardDefaults = normalizeCardDefaults(v);
|
|
203
205
|
}
|
|
206
|
+
if (storage.hasPreference(preferenceStorageKey("inheritEnv"))) {
|
|
207
|
+
const v = storage.getPreference(preferenceStorageKey("inheritEnv"), defaults.inheritEnv ?? true);
|
|
208
|
+
config.inheritEnv = v === false ? false : true;
|
|
209
|
+
}
|
|
204
210
|
return config;
|
|
205
211
|
}
|
|
206
212
|
/** Write a single preference value to DB and (in-place) update the live config object. */
|
|
@@ -244,6 +250,12 @@ export function writePreferenceToStorage(config, storage, key, value) {
|
|
|
244
250
|
config.cardDefaults = normalized;
|
|
245
251
|
break;
|
|
246
252
|
}
|
|
253
|
+
case "inheritEnv": {
|
|
254
|
+
const v = value === false ? false : true;
|
|
255
|
+
storage.setPreference(dbKey, v);
|
|
256
|
+
config.inheritEnv = v;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
247
259
|
}
|
|
248
260
|
}
|
|
249
261
|
function defaultCardExpandDefaults() {
|
|
@@ -349,6 +361,7 @@ function mergeWithDefaults(input) {
|
|
|
349
361
|
cardDefaults: normalizeCardDefaults(input.cardDefaults),
|
|
350
362
|
defaultModel: typeof input.defaultModel === "string" ? input.defaultModel.trim() : defaults.defaultModel,
|
|
351
363
|
structuredRunner: (input.structuredRunner === "sdk" || input.structuredRunner === "cli") ? input.structuredRunner : defaults.structuredRunner,
|
|
364
|
+
inheritEnv: typeof input.inheritEnv === "boolean" ? input.inheritEnv : (defaults.inheritEnv ?? true),
|
|
352
365
|
};
|
|
353
366
|
}
|
|
354
367
|
export function isExecutionMode(value) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 根据 inheritEnv 配置组装子进程的环境变量。
|
|
3
|
+
*
|
|
4
|
+
* - inheritEnv=true(默认):继承父进程全部 env,再合并 extras 覆盖。
|
|
5
|
+
* - inheritEnv=false:仅保留 MINIMAL_ENV_KEYS 中存在的字段,再合并 extras 覆盖。
|
|
6
|
+
*
|
|
7
|
+
* extras 中的 undefined 字段会被剔除(spawn 不允许 env 值为 undefined)。
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildChildEnv(inheritEnv: boolean, extras?: Record<string, string | undefined>): NodeJS.ProcessEnv;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
/**
|
|
3
|
+
* 用于子进程 spawn 时的环境变量白名单(当用户关闭"继承环境变量"时使用)。
|
|
4
|
+
* 仅保留运行 CLI 工具所需的最小集合,避免把 API key、token 等敏感凭据继承到子命令。
|
|
5
|
+
*/
|
|
6
|
+
const MINIMAL_ENV_KEYS = [
|
|
7
|
+
"PATH",
|
|
8
|
+
"HOME",
|
|
9
|
+
"USER",
|
|
10
|
+
"LOGNAME",
|
|
11
|
+
"SHELL",
|
|
12
|
+
"LANG",
|
|
13
|
+
"LC_ALL",
|
|
14
|
+
"LC_CTYPE",
|
|
15
|
+
"TERM",
|
|
16
|
+
"TZ",
|
|
17
|
+
"TMPDIR",
|
|
18
|
+
"TMP",
|
|
19
|
+
"TEMP",
|
|
20
|
+
"PWD",
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* 根据 inheritEnv 配置组装子进程的环境变量。
|
|
24
|
+
*
|
|
25
|
+
* - inheritEnv=true(默认):继承父进程全部 env,再合并 extras 覆盖。
|
|
26
|
+
* - inheritEnv=false:仅保留 MINIMAL_ENV_KEYS 中存在的字段,再合并 extras 覆盖。
|
|
27
|
+
*
|
|
28
|
+
* extras 中的 undefined 字段会被剔除(spawn 不允许 env 值为 undefined)。
|
|
29
|
+
*/
|
|
30
|
+
export function buildChildEnv(inheritEnv, extras = {}) {
|
|
31
|
+
const base = {};
|
|
32
|
+
if (inheritEnv) {
|
|
33
|
+
Object.assign(base, process.env);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
for (const key of MINIMAL_ENV_KEYS) {
|
|
37
|
+
const v = process.env[key];
|
|
38
|
+
if (typeof v === "string")
|
|
39
|
+
base[key] = v;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const [k, v] of Object.entries(extras)) {
|
|
43
|
+
if (typeof v === "string")
|
|
44
|
+
base[k] = v;
|
|
45
|
+
}
|
|
46
|
+
return base;
|
|
47
|
+
}
|
package/dist/process-manager.js
CHANGED
|
@@ -9,6 +9,7 @@ import { SessionLogger } from "./session-logger.js";
|
|
|
9
9
|
import { ClaudePtyBridge } from "./claude-pty-bridge.js";
|
|
10
10
|
import { truncateMessagesForTransport } from "./message-truncator.js";
|
|
11
11
|
import { appendWindow, hasExplicitConfirmSyntax, hasPermissionActionContext, normalizePromptText, PTY_OUTPUT_MAX_SIZE } from "./pty-text-utils.js";
|
|
12
|
+
import { buildChildEnv } from "./env-utils.js";
|
|
12
13
|
import { prepareSessionWorktree } from "./git-worktree.js";
|
|
13
14
|
import { getResumeCommandSessionId } from "./resume-policy.js";
|
|
14
15
|
function resolveProviderFromCommand(command) {
|
|
@@ -659,12 +660,11 @@ export class ProcessManager extends EventEmitter {
|
|
|
659
660
|
try {
|
|
660
661
|
child = pty.spawn(this.config.shell, shellArgs, {
|
|
661
662
|
cwd: resolvedCwd,
|
|
662
|
-
env: {
|
|
663
|
-
...process.env,
|
|
663
|
+
env: buildChildEnv(this.config.inheritEnv !== false, {
|
|
664
664
|
WAND_MODE: effectiveMode,
|
|
665
665
|
WAND_AUTO_CONFIRM: effectiveMode === "full-access" ? "1" : "0",
|
|
666
666
|
WAND_AUTO_EDIT: effectiveMode === "auto-edit" ? "1" : "0"
|
|
667
|
-
},
|
|
667
|
+
}),
|
|
668
668
|
name: "xterm-color",
|
|
669
669
|
// 使用 record 上由前端协商好的真实尺寸,避免"先 120 列、几百毫秒后再 resize"
|
|
670
670
|
// 期间 Claude/Codex 用错列宽渲染出 \x1b[120G 这类绝对列定位序列。
|
package/dist/server.js
CHANGED
|
@@ -554,6 +554,7 @@ export async function startServer(config, configPath) {
|
|
|
554
554
|
? path.join(SERVER_MODULE_DIR, "web-ui", "content")
|
|
555
555
|
: path.join(RUNTIME_ROOT_DIR, "src", "web-ui", "content");
|
|
556
556
|
app.use("/vendor/wterm", express.static(path.join(contentDir, "vendor", "wterm"), vendorCacheOpts));
|
|
557
|
+
app.use("/vendor/qrcode", express.static(path.join(contentDir, "vendor", "qrcode"), vendorCacheOpts));
|
|
557
558
|
// ── Web UI and PWA endpoints ──
|
|
558
559
|
app.get("/", (_req, res) => {
|
|
559
560
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
@@ -4,6 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { prepareSessionWorktree } from "./git-worktree.js";
|
|
6
6
|
import { truncateMessagesForTransport } from "./message-truncator.js";
|
|
7
|
+
import { buildChildEnv } from "./env-utils.js";
|
|
7
8
|
function defaultStructuredRunner(provider) {
|
|
8
9
|
return provider === "codex" ? "codex-cli-exec" : "claude-cli-print";
|
|
9
10
|
}
|
|
@@ -756,7 +757,7 @@ export class StructuredSessionManager {
|
|
|
756
757
|
const spawnedAt = new Date().toISOString();
|
|
757
758
|
const child = spawn("codex", args, {
|
|
758
759
|
cwd: session.cwd,
|
|
759
|
-
env:
|
|
760
|
+
env: buildChildEnv(this.config.inheritEnv !== false),
|
|
760
761
|
stdio: ["pipe", "pipe", "pipe"],
|
|
761
762
|
});
|
|
762
763
|
this.logger?.appendStructuredSpawn(sessionId, {
|
|
@@ -1085,7 +1086,7 @@ export class StructuredSessionManager {
|
|
|
1085
1086
|
const spawnedAt = new Date().toISOString();
|
|
1086
1087
|
const child = spawn("claude", args, {
|
|
1087
1088
|
cwd: session.cwd,
|
|
1088
|
-
env:
|
|
1089
|
+
env: buildChildEnv(this.config.inheritEnv !== false),
|
|
1089
1090
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1090
1091
|
});
|
|
1091
1092
|
this.logger?.appendStructuredSpawn(sessionId, {
|
package/dist/types.d.ts
CHANGED
|
@@ -93,6 +93,12 @@ export interface WandConfig {
|
|
|
93
93
|
defaultModel?: string;
|
|
94
94
|
/** 结构化会话使用的 runner: "cli"(默认,spawn claude -p)或 "sdk"(@anthropic-ai/claude-agent-sdk)。 */
|
|
95
95
|
structuredRunner?: "cli" | "sdk";
|
|
96
|
+
/**
|
|
97
|
+
* 启动 PTY / 结构化子进程时是否继承父进程的环境变量(process.env)。默认 true。
|
|
98
|
+
* 关闭后子进程仅获得最小可用环境(PATH/HOME/SHELL/LANG/LC_ALL/TERM 等)外加 WAND_* 控制变量,
|
|
99
|
+
* 用于隔离敏感凭据或避免 API key 泄漏到子命令。
|
|
100
|
+
*/
|
|
101
|
+
inheritEnv?: boolean;
|
|
96
102
|
}
|
|
97
103
|
export interface ClaudeModelInfo {
|
|
98
104
|
/** 传给 --model 的值(别名或完整模型 ID) */
|
|
@@ -1233,6 +1233,13 @@
|
|
|
1233
1233
|
'<p id="login-error" class="error-message hidden" role="alert"></p>' +
|
|
1234
1234
|
'</div>' +
|
|
1235
1235
|
'<button id="login-button" class="btn btn-primary btn-block">进入控制台</button>' +
|
|
1236
|
+
(hasNativeSwitchServer() ?
|
|
1237
|
+
'<button id="login-switch-server-button" class="btn btn-ghost btn-block login-switch-server" type="button">' +
|
|
1238
|
+
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="8" rx="2"/><rect x="2" y="13" width="20" height="8" rx="2"/><line x1="6" y1="7" x2="6.01" y2="7"/><line x1="6" y1="17" x2="6.01" y2="17"/></svg>' +
|
|
1239
|
+
'<span>切换服务器</span>' +
|
|
1240
|
+
'</button>'
|
|
1241
|
+
: ''
|
|
1242
|
+
) +
|
|
1236
1243
|
'</div>' +
|
|
1237
1244
|
'</div>' +
|
|
1238
1245
|
'</div>';
|
|
@@ -1300,6 +1307,13 @@
|
|
|
1300
1307
|
'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>' +
|
|
1301
1308
|
'<span>安装</span>' +
|
|
1302
1309
|
'</button>' +
|
|
1310
|
+
(hasNativeSwitchServer() ?
|
|
1311
|
+
'<button id="switch-server-button" class="btn btn-ghost btn-sm sidebar-switch-server" type="button" title="切换服务器">' +
|
|
1312
|
+
'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="8" rx="2"/><rect x="2" y="13" width="20" height="8" rx="2"/><line x1="6" y1="7" x2="6.01" y2="7"/><line x1="6" y1="17" x2="6.01" y2="17"/></svg>' +
|
|
1313
|
+
'<span>切换</span>' +
|
|
1314
|
+
'</button>'
|
|
1315
|
+
: ''
|
|
1316
|
+
) +
|
|
1303
1317
|
'<button id="logout-button" class="btn btn-ghost btn-sm sidebar-logout" type="button" title="退出登录">' +
|
|
1304
1318
|
'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>' +
|
|
1305
1319
|
'<span>退出</span>' +
|
|
@@ -1338,6 +1352,7 @@
|
|
|
1338
1352
|
'<button class="topbar-more-item" data-action="settings" type="button" role="menuitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span>设置</span></button>' +
|
|
1339
1353
|
'<button class="topbar-more-item" data-action="refresh" type="button" role="menuitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg><span>刷新</span></button>' +
|
|
1340
1354
|
'<button class="topbar-more-item' + (state.showInstallPrompt && state.deferredPrompt ? '' : ' hidden') + '" id="topbar-install-item" data-action="install" type="button" role="menuitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg><span>安装应用</span></button>' +
|
|
1355
|
+
(hasNativeSwitchServer() ? '<button class="topbar-more-item" data-action="switch-server" type="button" role="menuitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="8" rx="2"/><rect x="2" y="13" width="20" height="8" rx="2"/><line x1="6" y1="7" x2="6.01" y2="7"/><line x1="6" y1="17" x2="6.01" y2="17"/></svg><span>切换服务器</span></button>' : '') +
|
|
1341
1356
|
'<button class="topbar-more-item topbar-more-item-danger" data-action="logout" type="button" role="menuitem"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg><span>退出</span></button>' +
|
|
1342
1357
|
'</div>' +
|
|
1343
1358
|
'</div>' +
|
|
@@ -1982,6 +1997,13 @@
|
|
|
1982
1997
|
'<code id="android-connect-code" class="settings-connect-url-text">-</code>' +
|
|
1983
1998
|
'<button id="copy-connect-code-button" class="btn btn-secondary btn-sm" type="button" title="复制连接码">复制</button>' +
|
|
1984
1999
|
'</div>' +
|
|
2000
|
+
'<div class="settings-connect-qr-box">' +
|
|
2001
|
+
'<div class="settings-connect-qr-wrap" id="android-connect-qr-wrap" title="点击放大">' +
|
|
2002
|
+
'<canvas id="android-connect-qr" width="180" height="180"></canvas>' +
|
|
2003
|
+
'<div class="settings-connect-qr-empty" id="android-connect-qr-empty">生成中…</div>' +
|
|
2004
|
+
'</div>' +
|
|
2005
|
+
'<p class="settings-connect-qr-hint">用 Wand App 扫一扫,即可一键填入服务器地址与连接码。</p>' +
|
|
2006
|
+
'</div>' +
|
|
1985
2007
|
'</div>' +
|
|
1986
2008
|
'</div>' +
|
|
1987
2009
|
|
|
@@ -2142,6 +2164,16 @@
|
|
|
2142
2164
|
'</select>' +
|
|
2143
2165
|
'<p class="field-hint" style="margin-top:4px;">SDK 模式使用官方 Agent SDK 替代 CLI subprocess,接口更整洁,功能等价。保存后对新建会话立即生效。</p>' +
|
|
2144
2166
|
'</div>' +
|
|
2167
|
+
'<div class="settings-toggle-row">' +
|
|
2168
|
+
'<div class="settings-toggle-text">' +
|
|
2169
|
+
'<label class="settings-toggle-title" for="cfg-inherit-env">继承环境变量</label>' +
|
|
2170
|
+
'<span class="settings-toggle-desc">启动 PTY / 结构化子进程时,把当前服务进程的环境变量传给 claude / codex。关闭后子进程仅获得最小可用环境(PATH/HOME/SHELL/LANG/TERM 等),可用于隔离 API key 等敏感凭据。</span>' +
|
|
2171
|
+
'</div>' +
|
|
2172
|
+
'<label class="settings-switch">' +
|
|
2173
|
+
'<input id="cfg-inherit-env" type="checkbox" class="switch-toggle" />' +
|
|
2174
|
+
'<span class="switch-slider"></span>' +
|
|
2175
|
+
'</label>' +
|
|
2176
|
+
'</div>' +
|
|
2145
2177
|
'<div class="field">' +
|
|
2146
2178
|
'<label class="field-label" for="cfg-default-model">默认模型</label>' +
|
|
2147
2179
|
'<div class="settings-row-with-action">' +
|
|
@@ -3799,6 +3831,8 @@
|
|
|
3799
3831
|
var loginButton = document.getElementById("login-button");
|
|
3800
3832
|
if (loginButton) {
|
|
3801
3833
|
loginButton.addEventListener("click", login);
|
|
3834
|
+
var loginSwitchServerBtn = document.getElementById("login-switch-server-button");
|
|
3835
|
+
if (loginSwitchServerBtn) loginSwitchServerBtn.addEventListener("click", switchServer);
|
|
3802
3836
|
var passwordEl = document.getElementById("password");
|
|
3803
3837
|
var togglePasswordButton = document.getElementById("toggle-password-button");
|
|
3804
3838
|
if (togglePasswordButton && passwordEl) {
|
|
@@ -3961,6 +3995,8 @@
|
|
|
3961
3995
|
});
|
|
3962
3996
|
var logoutBtn = document.getElementById("logout-button");
|
|
3963
3997
|
if (logoutBtn) logoutBtn.addEventListener("click", logout);
|
|
3998
|
+
var switchServerBtn = document.getElementById("switch-server-button");
|
|
3999
|
+
if (switchServerBtn) switchServerBtn.addEventListener("click", switchServer);
|
|
3964
4000
|
var settingsBtn = document.getElementById("settings-button");
|
|
3965
4001
|
if (settingsBtn) settingsBtn.addEventListener("click", openSettingsModal);
|
|
3966
4002
|
var closeSettingsBtn = document.getElementById("close-settings-button");
|
|
@@ -4398,6 +4434,9 @@
|
|
|
4398
4434
|
case "logout":
|
|
4399
4435
|
logout();
|
|
4400
4436
|
break;
|
|
4437
|
+
case "switch-server":
|
|
4438
|
+
switchServer();
|
|
4439
|
+
break;
|
|
4401
4440
|
}
|
|
4402
4441
|
});
|
|
4403
4442
|
// Close on outside click
|
|
@@ -5908,6 +5947,15 @@
|
|
|
5908
5947
|
});
|
|
5909
5948
|
}
|
|
5910
5949
|
|
|
5950
|
+
function hasNativeSwitchServer() {
|
|
5951
|
+
return typeof WandNative !== "undefined" && typeof WandNative.switchServer === "function";
|
|
5952
|
+
}
|
|
5953
|
+
|
|
5954
|
+
function switchServer() {
|
|
5955
|
+
if (!hasNativeSwitchServer()) return;
|
|
5956
|
+
try { WandNative.switchServer(); } catch (e) {}
|
|
5957
|
+
}
|
|
5958
|
+
|
|
5911
5959
|
function logout() {
|
|
5912
5960
|
fetch("/api/logout", { method: "POST", credentials: "same-origin" }).catch(function() {});
|
|
5913
5961
|
stopPolling();
|
|
@@ -7326,6 +7374,78 @@
|
|
|
7326
7374
|
}
|
|
7327
7375
|
|
|
7328
7376
|
|
|
7377
|
+
function renderConnectQrCode(code) {
|
|
7378
|
+
var canvas = document.getElementById("android-connect-qr");
|
|
7379
|
+
var empty = document.getElementById("android-connect-qr-empty");
|
|
7380
|
+
var lib = window.QRCodeLib;
|
|
7381
|
+
if (!canvas) return;
|
|
7382
|
+
if (!lib || typeof lib.toCanvas !== "function") {
|
|
7383
|
+
if (empty) empty.textContent = "二维码库未加载";
|
|
7384
|
+
return;
|
|
7385
|
+
}
|
|
7386
|
+
try {
|
|
7387
|
+
lib.toCanvas(canvas, code, {
|
|
7388
|
+
width: 220,
|
|
7389
|
+
margin: 1,
|
|
7390
|
+
errorCorrectionLevel: "M",
|
|
7391
|
+
color: { dark: "#1f1b17", light: "#ffffff00" }
|
|
7392
|
+
}, function(err) {
|
|
7393
|
+
if (err) {
|
|
7394
|
+
if (empty) {
|
|
7395
|
+
empty.textContent = "二维码生成失败";
|
|
7396
|
+
empty.style.display = "";
|
|
7397
|
+
}
|
|
7398
|
+
canvas.style.visibility = "hidden";
|
|
7399
|
+
return;
|
|
7400
|
+
}
|
|
7401
|
+
if (empty) empty.style.display = "none";
|
|
7402
|
+
canvas.style.visibility = "visible";
|
|
7403
|
+
});
|
|
7404
|
+
} catch (e) {
|
|
7405
|
+
if (empty) {
|
|
7406
|
+
empty.textContent = "二维码生成失败";
|
|
7407
|
+
empty.style.display = "";
|
|
7408
|
+
}
|
|
7409
|
+
canvas.style.visibility = "hidden";
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
|
|
7413
|
+
function showConnectQrModal(code) {
|
|
7414
|
+
var lib = window.QRCodeLib;
|
|
7415
|
+
if (!lib || typeof lib.toCanvas !== "function") return;
|
|
7416
|
+
// Reuse existing overlay if open
|
|
7417
|
+
var existing = document.getElementById("connect-qr-modal");
|
|
7418
|
+
if (existing) existing.remove();
|
|
7419
|
+
var overlay = document.createElement("div");
|
|
7420
|
+
overlay.id = "connect-qr-modal";
|
|
7421
|
+
overlay.className = "connect-qr-modal-overlay";
|
|
7422
|
+
overlay.innerHTML =
|
|
7423
|
+
'<div class="connect-qr-modal-card">' +
|
|
7424
|
+
'<canvas id="connect-qr-modal-canvas"></canvas>' +
|
|
7425
|
+
'<p class="connect-qr-modal-hint">用 Wand App 扫一扫,连接当前服务器</p>' +
|
|
7426
|
+
'<button type="button" class="btn btn-secondary btn-sm connect-qr-modal-close">关闭</button>' +
|
|
7427
|
+
'</div>';
|
|
7428
|
+
document.body.appendChild(overlay);
|
|
7429
|
+
var modalCanvas = overlay.querySelector("#connect-qr-modal-canvas");
|
|
7430
|
+
var size = Math.min(window.innerWidth, window.innerHeight) * 0.7;
|
|
7431
|
+
if (size < 240) size = 240;
|
|
7432
|
+
if (size > 480) size = 480;
|
|
7433
|
+
try {
|
|
7434
|
+
lib.toCanvas(modalCanvas, code, {
|
|
7435
|
+
width: size,
|
|
7436
|
+
margin: 2,
|
|
7437
|
+
errorCorrectionLevel: "M",
|
|
7438
|
+
color: { dark: "#1f1b17", light: "#ffffff" }
|
|
7439
|
+
});
|
|
7440
|
+
} catch (e) {}
|
|
7441
|
+
function close() { overlay.remove(); }
|
|
7442
|
+
overlay.addEventListener("click", function(e) {
|
|
7443
|
+
if (e.target === overlay) close();
|
|
7444
|
+
});
|
|
7445
|
+
var closeBtn = overlay.querySelector(".connect-qr-modal-close");
|
|
7446
|
+
if (closeBtn) closeBtn.addEventListener("click", close);
|
|
7447
|
+
}
|
|
7448
|
+
|
|
7329
7449
|
function copyToClipboard(text, triggerBtn, successCallback) {
|
|
7330
7450
|
if (!text) return;
|
|
7331
7451
|
function onSuccess() {
|
|
@@ -7511,12 +7631,32 @@
|
|
|
7511
7631
|
|
|
7512
7632
|
// App connect code (encrypted)
|
|
7513
7633
|
var connectCodeEl = document.getElementById("android-connect-code");
|
|
7634
|
+
var connectQrCanvas = document.getElementById("android-connect-qr");
|
|
7635
|
+
var connectQrEmpty = document.getElementById("android-connect-qr-empty");
|
|
7636
|
+
var connectQrWrap = document.getElementById("android-connect-qr-wrap");
|
|
7514
7637
|
if (connectCodeEl) {
|
|
7515
7638
|
connectCodeEl.textContent = "加载中...";
|
|
7639
|
+
if (connectQrEmpty) connectQrEmpty.textContent = "生成中…";
|
|
7640
|
+
if (connectQrCanvas) connectQrCanvas.style.visibility = "hidden";
|
|
7516
7641
|
fetch("/api/app-connect-code").then(function(r) { return r.json(); }).then(function(d) {
|
|
7517
|
-
if (d.code)
|
|
7518
|
-
|
|
7519
|
-
|
|
7642
|
+
if (d.code) {
|
|
7643
|
+
connectCodeEl.textContent = d.code;
|
|
7644
|
+
state.androidConnectCode = d.code;
|
|
7645
|
+
renderConnectQrCode(d.code);
|
|
7646
|
+
} else {
|
|
7647
|
+
connectCodeEl.textContent = "生成失败";
|
|
7648
|
+
if (connectQrEmpty) connectQrEmpty.textContent = "生成失败";
|
|
7649
|
+
}
|
|
7650
|
+
}).catch(function() {
|
|
7651
|
+
connectCodeEl.textContent = "获取失败";
|
|
7652
|
+
if (connectQrEmpty) connectQrEmpty.textContent = "获取失败";
|
|
7653
|
+
});
|
|
7654
|
+
}
|
|
7655
|
+
if (connectQrWrap && !connectQrWrap.dataset.bound) {
|
|
7656
|
+
connectQrWrap.dataset.bound = "1";
|
|
7657
|
+
connectQrWrap.addEventListener("click", function() {
|
|
7658
|
+
if (state.androidConnectCode) showConnectQrModal(state.androidConnectCode);
|
|
7659
|
+
});
|
|
7520
7660
|
}
|
|
7521
7661
|
|
|
7522
7662
|
// Config fields
|
|
@@ -7539,6 +7679,9 @@
|
|
|
7539
7679
|
var srEl = document.getElementById("cfg-structured-runner");
|
|
7540
7680
|
if (srEl) srEl.value = cfg.structuredRunner || "cli";
|
|
7541
7681
|
|
|
7682
|
+
var inheritEnvEl = document.getElementById("cfg-inherit-env");
|
|
7683
|
+
if (inheritEnvEl) inheritEnvEl.checked = cfg.inheritEnv !== false;
|
|
7684
|
+
|
|
7542
7685
|
// Default model
|
|
7543
7686
|
state.configDefaultModel = cfg.defaultModel || "";
|
|
7544
7687
|
updateSettingsDefaultModelSelect();
|
|
@@ -7598,6 +7741,7 @@
|
|
|
7598
7741
|
language: (document.getElementById("cfg-language") || {}).value || "",
|
|
7599
7742
|
defaultModel: (document.getElementById("cfg-default-model") || {}).value || "",
|
|
7600
7743
|
structuredRunner: (document.getElementById("cfg-structured-runner") || {}).value || "cli",
|
|
7744
|
+
inheritEnv: (document.getElementById("cfg-inherit-env") || {}).checked !== false,
|
|
7601
7745
|
};
|
|
7602
7746
|
|
|
7603
7747
|
var previousDefaultModel = (state.config && state.config.defaultModel) || "";
|
|
@@ -558,6 +558,32 @@
|
|
|
558
558
|
color: var(--text-secondary);
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
+
.sidebar-switch-server {
|
|
562
|
+
color: var(--text-muted);
|
|
563
|
+
opacity: 0.7;
|
|
564
|
+
transition: opacity var(--transition-fast), color var(--transition-fast);
|
|
565
|
+
}
|
|
566
|
+
.sidebar-switch-server:hover {
|
|
567
|
+
opacity: 1;
|
|
568
|
+
color: var(--primary, var(--text-secondary));
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.login-switch-server {
|
|
572
|
+
margin-top: 10px;
|
|
573
|
+
display: inline-flex;
|
|
574
|
+
align-items: center;
|
|
575
|
+
justify-content: center;
|
|
576
|
+
gap: 6px;
|
|
577
|
+
font-size: 13px;
|
|
578
|
+
color: var(--text-secondary);
|
|
579
|
+
}
|
|
580
|
+
.login-switch-server svg {
|
|
581
|
+
opacity: 0.75;
|
|
582
|
+
}
|
|
583
|
+
.login-switch-server:hover {
|
|
584
|
+
color: var(--primary, var(--text-primary));
|
|
585
|
+
}
|
|
586
|
+
|
|
561
587
|
.sidebar-title {
|
|
562
588
|
font-size: 0.875rem;
|
|
563
589
|
font-weight: 600;
|
|
@@ -9737,6 +9763,96 @@
|
|
|
9737
9763
|
-webkit-user-select: all;
|
|
9738
9764
|
}
|
|
9739
9765
|
|
|
9766
|
+
.settings-connect-qr-box {
|
|
9767
|
+
display: flex;
|
|
9768
|
+
flex-direction: column;
|
|
9769
|
+
align-items: center;
|
|
9770
|
+
gap: 10px;
|
|
9771
|
+
margin-top: 14px;
|
|
9772
|
+
}
|
|
9773
|
+
|
|
9774
|
+
.settings-connect-qr-wrap {
|
|
9775
|
+
position: relative;
|
|
9776
|
+
width: 200px;
|
|
9777
|
+
height: 200px;
|
|
9778
|
+
padding: 10px;
|
|
9779
|
+
background: #fff;
|
|
9780
|
+
border: 1px solid var(--border-subtle);
|
|
9781
|
+
border-radius: 16px;
|
|
9782
|
+
box-shadow: 0 4px 12px rgba(125, 91, 57, 0.08);
|
|
9783
|
+
cursor: pointer;
|
|
9784
|
+
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
9785
|
+
display: flex;
|
|
9786
|
+
align-items: center;
|
|
9787
|
+
justify-content: center;
|
|
9788
|
+
}
|
|
9789
|
+
|
|
9790
|
+
.settings-connect-qr-wrap:hover {
|
|
9791
|
+
transform: translateY(-1px);
|
|
9792
|
+
box-shadow: 0 6px 16px rgba(125, 91, 57, 0.12);
|
|
9793
|
+
}
|
|
9794
|
+
|
|
9795
|
+
.settings-connect-qr-wrap canvas {
|
|
9796
|
+
display: block;
|
|
9797
|
+
max-width: 100%;
|
|
9798
|
+
max-height: 100%;
|
|
9799
|
+
}
|
|
9800
|
+
|
|
9801
|
+
.settings-connect-qr-empty {
|
|
9802
|
+
position: absolute;
|
|
9803
|
+
inset: 0;
|
|
9804
|
+
display: flex;
|
|
9805
|
+
align-items: center;
|
|
9806
|
+
justify-content: center;
|
|
9807
|
+
font-size: 12px;
|
|
9808
|
+
color: var(--text-secondary);
|
|
9809
|
+
pointer-events: none;
|
|
9810
|
+
}
|
|
9811
|
+
|
|
9812
|
+
.settings-connect-qr-hint {
|
|
9813
|
+
margin: 0;
|
|
9814
|
+
font-size: 12px;
|
|
9815
|
+
color: var(--text-secondary);
|
|
9816
|
+
text-align: center;
|
|
9817
|
+
max-width: 280px;
|
|
9818
|
+
}
|
|
9819
|
+
|
|
9820
|
+
.connect-qr-modal-overlay {
|
|
9821
|
+
position: fixed;
|
|
9822
|
+
inset: 0;
|
|
9823
|
+
background: rgba(20, 14, 8, 0.55);
|
|
9824
|
+
backdrop-filter: blur(6px);
|
|
9825
|
+
-webkit-backdrop-filter: blur(6px);
|
|
9826
|
+
z-index: 9999;
|
|
9827
|
+
display: flex;
|
|
9828
|
+
align-items: center;
|
|
9829
|
+
justify-content: center;
|
|
9830
|
+
padding: 24px;
|
|
9831
|
+
}
|
|
9832
|
+
|
|
9833
|
+
.connect-qr-modal-card {
|
|
9834
|
+
background: #fff;
|
|
9835
|
+
border-radius: 20px;
|
|
9836
|
+
padding: 24px;
|
|
9837
|
+
display: flex;
|
|
9838
|
+
flex-direction: column;
|
|
9839
|
+
align-items: center;
|
|
9840
|
+
gap: 14px;
|
|
9841
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
|
|
9842
|
+
}
|
|
9843
|
+
|
|
9844
|
+
.connect-qr-modal-card canvas {
|
|
9845
|
+
display: block;
|
|
9846
|
+
border-radius: 8px;
|
|
9847
|
+
}
|
|
9848
|
+
|
|
9849
|
+
.connect-qr-modal-hint {
|
|
9850
|
+
margin: 0;
|
|
9851
|
+
font-size: 13px;
|
|
9852
|
+
color: var(--text-secondary);
|
|
9853
|
+
text-align: center;
|
|
9854
|
+
}
|
|
9855
|
+
|
|
9740
9856
|
.settings-divider {
|
|
9741
9857
|
border: none;
|
|
9742
9858
|
border-top: 1px solid var(--border-subtle);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";var QRCodeLib=(()=>{var qe=Object.create;var j=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var Fe=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,ze=Object.prototype.hasOwnProperty;var g=(n,t)=>()=>(t||n((t={exports:{}}).exports,t),t.exports),Ve=(n,t)=>{for(var e in t)j(n,e,{get:t[e],enumerable:!0})},_t=(n,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Fe(t))!ze.call(n,o)&&o!==e&&j(n,o,{get:()=>t[o],enumerable:!(r=De(t,o))||r.enumerable});return n};var He=(n,t,e)=>(e=n!=null?qe(ke(n)):{},_t(t||!n||!n.__esModule?j(e,"default",{value:n,enumerable:!0}):e,n)),Ke=n=>_t(j({},"__esModule",{value:!0}),n);var Ut=g((Vn,xt)=>{xt.exports=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}});var I=g(P=>{var ut,Je=[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];P.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17};P.getSymbolTotalCodewords=function(t){return Je[t]};P.getBCHDigit=function(n){let t=0;for(;n!==0;)t++,n>>>=1;return t};P.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');ut=t};P.isKanjiModeEnabled=function(){return typeof ut<"u"};P.toSJIS=function(t){return ut(t)}});var G=g(m=>{m.L={bit:1};m.M={bit:0};m.Q={bit:3};m.H={bit:2};function Ye(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return m.L;case"m":case"medium":return m.M;case"q":case"quartile":return m.Q;case"h":case"high":return m.H;default:throw new Error("Unknown EC Level: "+n)}}m.isValid=function(t){return t&&typeof t.bit<"u"&&t.bit>=0&&t.bit<4};m.from=function(t,e){if(m.isValid(t))return t;try{return Ye(t)}catch{return e}}});var Ft=g((Jn,Dt)=>{function qt(){this.buffer=[],this.length=0}qt.prototype={get:function(n){let t=Math.floor(n/8);return(this.buffer[t]>>>7-n%8&1)===1},put:function(n,t){for(let e=0;e<t;e++)this.putBit((n>>>t-e-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(n){let t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),n&&(this.buffer[t]|=128>>>this.length%8),this.length++}};Dt.exports=qt});var zt=g((Yn,kt)=>{function k(n){if(!n||n<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=n,this.data=new Uint8Array(n*n),this.reservedBit=new Uint8Array(n*n)}k.prototype.set=function(n,t,e,r){let o=n*this.size+t;this.data[o]=e,r&&(this.reservedBit[o]=!0)};k.prototype.get=function(n,t){return this.data[n*this.size+t]};k.prototype.xor=function(n,t,e){this.data[n*this.size+t]^=e};k.prototype.isReserved=function(n,t){return this.reservedBit[n*this.size+t]};kt.exports=k});var Vt=g(Q=>{var Oe=I().getSymbolSize;Q.getRowColCoords=function(t){if(t===1)return[];let e=Math.floor(t/7)+2,r=Oe(t),o=r===145?26:Math.ceil((r-13)/(2*e-2))*2,i=[r-7];for(let s=1;s<e-1;s++)i[s]=i[s-1]-o;return i.push(6),i.reverse()};Q.getPositions=function(t){let e=[],r=Q.getRowColCoords(t),o=r.length;for(let i=0;i<o;i++)for(let s=0;s<o;s++)i===0&&s===0||i===0&&s===o-1||i===o-1&&s===0||e.push([r[i],r[s]]);return e}});var Jt=g(Kt=>{var je=I().getSymbolSize,Ht=7;Kt.getPositions=function(t){let e=je(t);return[[0,0],[e-Ht,0],[0,e-Ht]]}});var Yt=g(d=>{d.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var b={N1:3,N2:3,N3:40,N4:10};d.isValid=function(t){return t!=null&&t!==""&&!isNaN(t)&&t>=0&&t<=7};d.from=function(t){return d.isValid(t)?parseInt(t,10):void 0};d.getPenaltyN1=function(t){let e=t.size,r=0,o=0,i=0,s=null,u=null;for(let c=0;c<e;c++){o=i=0,s=u=null;for(let l=0;l<e;l++){let a=t.get(c,l);a===s?o++:(o>=5&&(r+=b.N1+(o-5)),s=a,o=1),a=t.get(l,c),a===u?i++:(i>=5&&(r+=b.N1+(i-5)),u=a,i=1)}o>=5&&(r+=b.N1+(o-5)),i>=5&&(r+=b.N1+(i-5))}return r};d.getPenaltyN2=function(t){let e=t.size,r=0;for(let o=0;o<e-1;o++)for(let i=0;i<e-1;i++){let s=t.get(o,i)+t.get(o,i+1)+t.get(o+1,i)+t.get(o+1,i+1);(s===4||s===0)&&r++}return r*b.N2};d.getPenaltyN3=function(t){let e=t.size,r=0,o=0,i=0;for(let s=0;s<e;s++){o=i=0;for(let u=0;u<e;u++)o=o<<1&2047|t.get(s,u),u>=10&&(o===1488||o===93)&&r++,i=i<<1&2047|t.get(u,s),u>=10&&(i===1488||i===93)&&r++}return r*b.N3};d.getPenaltyN4=function(t){let e=0,r=t.data.length;for(let i=0;i<r;i++)e+=t.data[i];return Math.abs(Math.ceil(e*100/r/5)-10)*b.N4};function Ge(n,t,e){switch(n){case d.Patterns.PATTERN000:return(t+e)%2===0;case d.Patterns.PATTERN001:return t%2===0;case d.Patterns.PATTERN010:return e%3===0;case d.Patterns.PATTERN011:return(t+e)%3===0;case d.Patterns.PATTERN100:return(Math.floor(t/2)+Math.floor(e/3))%2===0;case d.Patterns.PATTERN101:return t*e%2+t*e%3===0;case d.Patterns.PATTERN110:return(t*e%2+t*e%3)%2===0;case d.Patterns.PATTERN111:return(t*e%3+(t+e)%2)%2===0;default:throw new Error("bad maskPattern:"+n)}}d.applyMask=function(t,e){let r=e.size;for(let o=0;o<r;o++)for(let i=0;i<r;i++)e.isReserved(i,o)||e.xor(i,o,Ge(t,i,o))};d.getBestMask=function(t,e){let r=Object.keys(d.Patterns).length,o=0,i=1/0;for(let s=0;s<r;s++){e(s),d.applyMask(s,t);let u=d.getPenaltyN1(t)+d.getPenaltyN2(t)+d.getPenaltyN3(t)+d.getPenaltyN4(t);d.applyMask(s,t),u<i&&(i=u,o=s)}return o}});var lt=g(ct=>{var N=G(),$=[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],W=[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];ct.getBlocksCount=function(t,e){switch(e){case N.L:return $[(t-1)*4+0];case N.M:return $[(t-1)*4+1];case N.Q:return $[(t-1)*4+2];case N.H:return $[(t-1)*4+3];default:return}};ct.getTotalCodewordsCount=function(t,e){switch(e){case N.L:return W[(t-1)*4+0];case N.M:return W[(t-1)*4+1];case N.Q:return W[(t-1)*4+2];case N.H:return W[(t-1)*4+3];default:return}}});var Ot=g(X=>{var z=new Uint8Array(512),Z=new Uint8Array(256);(function(){let t=1;for(let e=0;e<255;e++)z[e]=t,Z[t]=e,t<<=1,t&256&&(t^=285);for(let e=255;e<512;e++)z[e]=z[e-255]})();X.log=function(t){if(t<1)throw new Error("log("+t+")");return Z[t]};X.exp=function(t){return z[t]};X.mul=function(t,e){return t===0||e===0?0:z[Z[t]+Z[e]]}});var jt=g(V=>{var at=Ot();V.mul=function(t,e){let r=new Uint8Array(t.length+e.length-1);for(let o=0;o<t.length;o++)for(let i=0;i<e.length;i++)r[o+i]^=at.mul(t[o],e[i]);return r};V.mod=function(t,e){let r=new Uint8Array(t);for(;r.length-e.length>=0;){let o=r[0];for(let s=0;s<e.length;s++)r[s]^=at.mul(e[s],o);let i=0;for(;i<r.length&&r[i]===0;)i++;r=r.slice(i)}return r};V.generateECPolynomial=function(t){let e=new Uint8Array([1]);for(let r=0;r<t;r++)e=V.mul(e,new Uint8Array([1,at.exp(r)]));return e}});var $t=g((Zn,Qt)=>{var Gt=jt();function ft(n){this.genPoly=void 0,this.degree=n,this.degree&&this.initialize(this.degree)}ft.prototype.initialize=function(t){this.degree=t,this.genPoly=Gt.generateECPolynomial(this.degree)};ft.prototype.encode=function(t){if(!this.genPoly)throw new Error("Encoder not initialized");let e=new Uint8Array(t.length+this.degree);e.set(t);let r=Gt.mod(e,this.genPoly),o=this.degree-r.length;if(o>0){let i=new Uint8Array(this.degree);return i.set(r,o),i}return r};Qt.exports=ft});var gt=g(Wt=>{Wt.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}});var dt=g(B=>{var Zt="[0-9]+",Qe="[A-Z $%*+\\-./:]+",H="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";H=H.replace(/u/g,"\\u");var $e="(?:(?![A-Z0-9 $%*+\\-./:]|"+H+`)(?:.|[\r
|
|
2
|
+
]))+`;B.KANJI=new RegExp(H,"g");B.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");B.BYTE=new RegExp($e,"g");B.NUMERIC=new RegExp(Zt,"g");B.ALPHANUMERIC=new RegExp(Qe,"g");var We=new RegExp("^"+H+"$"),Ze=new RegExp("^"+Zt+"$"),Xe=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");B.testKanji=function(t){return We.test(t)};B.testNumeric=function(t){return Ze.test(t)};B.testAlphanumeric=function(t){return Xe.test(t)}});var M=g(p=>{var ve=gt(),ht=dt();p.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]};p.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]};p.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]};p.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]};p.MIXED={bit:-1};p.getCharCountIndicator=function(t,e){if(!t.ccBits)throw new Error("Invalid mode: "+t);if(!ve.isValid(e))throw new Error("Invalid version: "+e);return e>=1&&e<10?t.ccBits[0]:e<27?t.ccBits[1]:t.ccBits[2]};p.getBestModeForData=function(t){return ht.testNumeric(t)?p.NUMERIC:ht.testAlphanumeric(t)?p.ALPHANUMERIC:ht.testKanji(t)?p.KANJI:p.BYTE};p.toString=function(t){if(t&&t.id)return t.id;throw new Error("Invalid mode")};p.isValid=function(t){return t&&t.bit&&t.ccBits};function tn(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"numeric":return p.NUMERIC;case"alphanumeric":return p.ALPHANUMERIC;case"kanji":return p.KANJI;case"byte":return p.BYTE;default:throw new Error("Unknown mode: "+n)}}p.from=function(t,e){if(p.isValid(t))return t;try{return tn(t)}catch{return e}}});var ne=g(R=>{var v=I(),en=lt(),Xt=G(),S=M(),pt=gt(),te=7973,vt=v.getBCHDigit(te);function nn(n,t,e){for(let r=1;r<=40;r++)if(t<=R.getCapacity(r,e,n))return r}function ee(n,t){return S.getCharCountIndicator(n,t)+4}function rn(n,t){let e=0;return n.forEach(function(r){let o=ee(r.mode,t);e+=o+r.getBitsLength()}),e}function on(n,t){for(let e=1;e<=40;e++)if(rn(n,e)<=R.getCapacity(e,t,S.MIXED))return e}R.from=function(t,e){return pt.isValid(t)?parseInt(t,10):e};R.getCapacity=function(t,e,r){if(!pt.isValid(t))throw new Error("Invalid QR Code version");typeof r>"u"&&(r=S.BYTE);let o=v.getSymbolTotalCodewords(t),i=en.getTotalCodewordsCount(t,e),s=(o-i)*8;if(r===S.MIXED)return s;let u=s-ee(r,t);switch(r){case S.NUMERIC:return Math.floor(u/10*3);case S.ALPHANUMERIC:return Math.floor(u/11*2);case S.KANJI:return Math.floor(u/13);case S.BYTE:default:return Math.floor(u/8)}};R.getBestVersionForData=function(t,e){let r,o=Xt.from(e,Xt.M);if(Array.isArray(t)){if(t.length>1)return on(t,o);if(t.length===0)return 1;r=t[0]}else r=t;return nn(r.mode,r.getLength(),o)};R.getEncodedBits=function(t){if(!pt.isValid(t)||t<7)throw new Error("Invalid QR Code version");let e=t<<12;for(;v.getBCHDigit(e)-vt>=0;)e^=te<<v.getBCHDigit(e)-vt;return t<<12|e}});var se=g(ie=>{var wt=I(),oe=1335,sn=21522,re=wt.getBCHDigit(oe);ie.getEncodedBits=function(t,e){let r=t.bit<<3|e,o=r<<10;for(;wt.getBCHDigit(o)-re>=0;)o^=oe<<wt.getBCHDigit(o)-re;return(r<<10|o)^sn}});var ce=g((rr,ue)=>{var un=M();function x(n){this.mode=un.NUMERIC,this.data=n.toString()}x.getBitsLength=function(t){return 10*Math.floor(t/3)+(t%3?t%3*3+1:0)};x.prototype.getLength=function(){return this.data.length};x.prototype.getBitsLength=function(){return x.getBitsLength(this.data.length)};x.prototype.write=function(t){let e,r,o;for(e=0;e+3<=this.data.length;e+=3)r=this.data.substr(e,3),o=parseInt(r,10),t.put(o,10);let i=this.data.length-e;i>0&&(r=this.data.substr(e),o=parseInt(r,10),t.put(o,i*3+1))};ue.exports=x});var ae=g((or,le)=>{var cn=M(),mt=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function U(n){this.mode=cn.ALPHANUMERIC,this.data=n}U.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)};U.prototype.getLength=function(){return this.data.length};U.prototype.getBitsLength=function(){return U.getBitsLength(this.data.length)};U.prototype.write=function(t){let e;for(e=0;e+2<=this.data.length;e+=2){let r=mt.indexOf(this.data[e])*45;r+=mt.indexOf(this.data[e+1]),t.put(r,11)}this.data.length%2&&t.put(mt.indexOf(this.data[e]),6)};le.exports=U});var ge=g((ir,fe)=>{var ln=M();function q(n){this.mode=ln.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}q.getBitsLength=function(t){return t*8};q.prototype.getLength=function(){return this.data.length};q.prototype.getBitsLength=function(){return q.getBitsLength(this.data.length)};q.prototype.write=function(n){for(let t=0,e=this.data.length;t<e;t++)n.put(this.data[t],8)};fe.exports=q});var he=g((sr,de)=>{var an=M(),fn=I();function D(n){this.mode=an.KANJI,this.data=n}D.getBitsLength=function(t){return t*13};D.prototype.getLength=function(){return this.data.length};D.prototype.getBitsLength=function(){return D.getBitsLength(this.data.length)};D.prototype.write=function(n){let t;for(t=0;t<this.data.length;t++){let e=fn.toSJIS(this.data[t]);if(e>=33088&&e<=40956)e-=33088;else if(e>=57408&&e<=60351)e-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+`
|
|
3
|
+
Make sure your charset is UTF-8`);e=(e>>>8&255)*192+(e&255),n.put(e,13)}};de.exports=D});var pe=g((ur,yt)=>{"use strict";var K={single_source_shortest_paths:function(n,t,e){var r={},o={};o[t]=0;var i=K.PriorityQueue.make();i.push(t,0);for(var s,u,c,l,a,w,h,y,A;!i.empty();){s=i.pop(),u=s.value,l=s.cost,a=n[u]||{};for(c in a)a.hasOwnProperty(c)&&(w=a[c],h=l+w,y=o[c],A=typeof o[c]>"u",(A||y>h)&&(o[c]=h,i.push(c,h),r[c]=u))}if(typeof e<"u"&&typeof o[e]>"u"){var T=["Could not find a path from ",t," to ",e,"."].join("");throw new Error(T)}return r},extract_shortest_path_from_predecessor_list:function(n,t){for(var e=[],r=t,o;r;)e.push(r),o=n[r],r=n[r];return e.reverse(),e},find_path:function(n,t,e){var r=K.single_source_shortest_paths(n,t,e);return K.extract_shortest_path_from_predecessor_list(r,e)},PriorityQueue:{make:function(n){var t=K.PriorityQueue,e={},r;n=n||{};for(r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e.queue=[],e.sorter=n.sorter||t.default_sorter,e},default_sorter:function(n,t){return n.cost-t.cost},push:function(n,t){var e={value:n,cost:t};this.queue.push(e),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};typeof yt<"u"&&(yt.exports=K)});var Te=g(F=>{var f=M(),ye=ce(),Ee=ae(),Ce=ge(),Be=he(),J=dt(),tt=I(),gn=pe();function we(n){return unescape(encodeURIComponent(n)).length}function Y(n,t,e){let r=[],o;for(;(o=n.exec(e))!==null;)r.push({data:o[0],index:o.index,mode:t,length:o[0].length});return r}function Ae(n){let t=Y(J.NUMERIC,f.NUMERIC,n),e=Y(J.ALPHANUMERIC,f.ALPHANUMERIC,n),r,o;return tt.isKanjiModeEnabled()?(r=Y(J.BYTE,f.BYTE,n),o=Y(J.KANJI,f.KANJI,n)):(r=Y(J.BYTE_KANJI,f.BYTE,n),o=[]),t.concat(e,r,o).sort(function(s,u){return s.index-u.index}).map(function(s){return{data:s.data,mode:s.mode,length:s.length}})}function Et(n,t){switch(t){case f.NUMERIC:return ye.getBitsLength(n);case f.ALPHANUMERIC:return Ee.getBitsLength(n);case f.KANJI:return Be.getBitsLength(n);case f.BYTE:return Ce.getBitsLength(n)}}function dn(n){return n.reduce(function(t,e){let r=t.length-1>=0?t[t.length-1]:null;return r&&r.mode===e.mode?(t[t.length-1].data+=e.data,t):(t.push(e),t)},[])}function hn(n){let t=[];for(let e=0;e<n.length;e++){let r=n[e];switch(r.mode){case f.NUMERIC:t.push([r,{data:r.data,mode:f.ALPHANUMERIC,length:r.length},{data:r.data,mode:f.BYTE,length:r.length}]);break;case f.ALPHANUMERIC:t.push([r,{data:r.data,mode:f.BYTE,length:r.length}]);break;case f.KANJI:t.push([r,{data:r.data,mode:f.BYTE,length:we(r.data)}]);break;case f.BYTE:t.push([{data:r.data,mode:f.BYTE,length:we(r.data)}])}}return t}function pn(n,t){let e={},r={start:{}},o=["start"];for(let i=0;i<n.length;i++){let s=n[i],u=[];for(let c=0;c<s.length;c++){let l=s[c],a=""+i+c;u.push(a),e[a]={node:l,lastCount:0},r[a]={};for(let w=0;w<o.length;w++){let h=o[w];e[h]&&e[h].node.mode===l.mode?(r[h][a]=Et(e[h].lastCount+l.length,l.mode)-Et(e[h].lastCount,l.mode),e[h].lastCount+=l.length):(e[h]&&(e[h].lastCount=l.length),r[h][a]=Et(l.length,l.mode)+4+f.getCharCountIndicator(l.mode,t))}}o=u}for(let i=0;i<o.length;i++)r[o[i]].end=0;return{map:r,table:e}}function me(n,t){let e,r=f.getBestModeForData(n);if(e=f.from(t,r),e!==f.BYTE&&e.bit<r.bit)throw new Error('"'+n+'" cannot be encoded with mode '+f.toString(e)+`.
|
|
4
|
+
Suggested mode is: `+f.toString(r));switch(e===f.KANJI&&!tt.isKanjiModeEnabled()&&(e=f.BYTE),e){case f.NUMERIC:return new ye(n);case f.ALPHANUMERIC:return new Ee(n);case f.KANJI:return new Be(n);case f.BYTE:return new Ce(n)}}F.fromArray=function(t){return t.reduce(function(e,r){return typeof r=="string"?e.push(me(r,null)):r.data&&e.push(me(r.data,r.mode)),e},[])};F.fromString=function(t,e){let r=Ae(t,tt.isKanjiModeEnabled()),o=hn(r),i=pn(o,e),s=gn.find_path(i.map,"start","end"),u=[];for(let c=1;c<s.length-1;c++)u.push(i.table[s[c]].node);return F.fromArray(dn(u))};F.rawSplit=function(t){return F.fromArray(Ae(t,tt.isKanjiModeEnabled()))}});var Ne=g(Ie=>{var nt=I(),Ct=G(),wn=Ft(),mn=zt(),yn=Vt(),En=Jt(),Tt=Yt(),It=lt(),Cn=$t(),et=ne(),Bn=se(),An=M(),Bt=Te();function Tn(n,t){let e=n.size,r=En.getPositions(t);for(let o=0;o<r.length;o++){let i=r[o][0],s=r[o][1];for(let u=-1;u<=7;u++)if(!(i+u<=-1||e<=i+u))for(let c=-1;c<=7;c++)s+c<=-1||e<=s+c||(u>=0&&u<=6&&(c===0||c===6)||c>=0&&c<=6&&(u===0||u===6)||u>=2&&u<=4&&c>=2&&c<=4?n.set(i+u,s+c,!0,!0):n.set(i+u,s+c,!1,!0))}}function In(n){let t=n.size;for(let e=8;e<t-8;e++){let r=e%2===0;n.set(e,6,r,!0),n.set(6,e,r,!0)}}function Nn(n,t){let e=yn.getPositions(t);for(let r=0;r<e.length;r++){let o=e[r][0],i=e[r][1];for(let s=-2;s<=2;s++)for(let u=-2;u<=2;u++)s===-2||s===2||u===-2||u===2||s===0&&u===0?n.set(o+s,i+u,!0,!0):n.set(o+s,i+u,!1,!0)}}function Mn(n,t){let e=n.size,r=et.getEncodedBits(t),o,i,s;for(let u=0;u<18;u++)o=Math.floor(u/3),i=u%3+e-8-3,s=(r>>u&1)===1,n.set(o,i,s,!0),n.set(i,o,s,!0)}function At(n,t,e){let r=n.size,o=Bn.getEncodedBits(t,e),i,s;for(i=0;i<15;i++)s=(o>>i&1)===1,i<6?n.set(i,8,s,!0):i<8?n.set(i+1,8,s,!0):n.set(r-15+i,8,s,!0),i<8?n.set(8,r-i-1,s,!0):i<9?n.set(8,15-i-1+1,s,!0):n.set(8,15-i-1,s,!0);n.set(r-8,8,1,!0)}function Sn(n,t){let e=n.size,r=-1,o=e-1,i=7,s=0;for(let u=e-1;u>0;u-=2)for(u===6&&u--;;){for(let c=0;c<2;c++)if(!n.isReserved(o,u-c)){let l=!1;s<t.length&&(l=(t[s]>>>i&1)===1),n.set(o,u-c,l),i--,i===-1&&(s++,i=7)}if(o+=r,o<0||e<=o){o-=r,r=-r;break}}}function Pn(n,t,e){let r=new wn;e.forEach(function(c){r.put(c.mode.bit,4),r.put(c.getLength(),An.getCharCountIndicator(c.mode,n)),c.write(r)});let o=nt.getSymbolTotalCodewords(n),i=It.getTotalCodewordsCount(n,t),s=(o-i)*8;for(r.getLengthInBits()+4<=s&&r.put(0,4);r.getLengthInBits()%8!==0;)r.putBit(0);let u=(s-r.getLengthInBits())/8;for(let c=0;c<u;c++)r.put(c%2?17:236,8);return bn(r,n,t)}function bn(n,t,e){let r=nt.getSymbolTotalCodewords(t),o=It.getTotalCodewordsCount(t,e),i=r-o,s=It.getBlocksCount(t,e),u=r%s,c=s-u,l=Math.floor(r/s),a=Math.floor(i/s),w=a+1,h=l-a,y=new Cn(h),A=0,T=new Array(s),Rt=new Array(s),ot=0,Ue=new Uint8Array(n.buffer);for(let _=0;_<s;_++){let st=_<c?a:w;T[_]=Ue.slice(A,A+st),Rt[_]=y.encode(T[_]),A+=st,ot=Math.max(ot,st)}let it=new Uint8Array(r),Lt=0,E,C;for(E=0;E<ot;E++)for(C=0;C<s;C++)E<T[C].length&&(it[Lt++]=T[C][E]);for(E=0;E<h;E++)for(C=0;C<s;C++)it[Lt++]=Rt[C][E];return it}function Rn(n,t,e,r){let o;if(Array.isArray(n))o=Bt.fromArray(n);else if(typeof n=="string"){let l=t;if(!l){let a=Bt.rawSplit(n);l=et.getBestVersionForData(a,e)}o=Bt.fromString(n,l||40)}else throw new Error("Invalid data");let i=et.getBestVersionForData(o,e);if(!i)throw new Error("The amount of data is too big to be stored in a QR Code");if(!t)t=i;else if(t<i)throw new Error(`
|
|
5
|
+
The chosen QR Code version cannot contain this amount of data.
|
|
6
|
+
Minimum version required to store current data is: `+i+`.
|
|
7
|
+
`);let s=Pn(t,e,o),u=nt.getSymbolSize(t),c=new mn(u);return Tn(c,t),In(c),Nn(c,t),At(c,e,0),t>=7&&Mn(c,t),Sn(c,s),isNaN(r)&&(r=Tt.getBestMask(c,At.bind(null,c,e))),Tt.applyMask(r,c),At(c,e,r),{modules:c,version:t,errorCorrectionLevel:e,maskPattern:r,segments:o}}Ie.create=function(t,e){if(typeof t>"u"||t==="")throw new Error("No input text");let r=Ct.M,o,i;return typeof e<"u"&&(r=Ct.from(e.errorCorrectionLevel,Ct.M),o=et.from(e.version),i=Tt.from(e.maskPattern),e.toSJISFunc&&nt.setToSJISFunction(e.toSJISFunc)),Rn(t,o,r,i)}});var Nt=g(L=>{function Me(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let t=n.slice().replace("#","").split("");if(t.length<3||t.length===5||t.length>8)throw new Error("Invalid hex color: "+n);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(r){return[r,r]}))),t.length===6&&t.push("F","F");let e=parseInt(t.join(""),16);return{r:e>>24&255,g:e>>16&255,b:e>>8&255,a:e&255,hex:"#"+t.slice(0,6).join("")}}L.getOptions=function(t){t||(t={}),t.color||(t.color={});let e=typeof t.margin>"u"||t.margin===null||t.margin<0?4:t.margin,r=t.width&&t.width>=21?t.width:void 0,o=t.scale||4;return{width:r,scale:r?4:o,margin:e,color:{dark:Me(t.color.dark||"#000000ff"),light:Me(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}};L.getScale=function(t,e){return e.width&&e.width>=t+e.margin*2?e.width/(t+e.margin*2):e.scale};L.getImageWidth=function(t,e){let r=L.getScale(t,e);return Math.floor((t+e.margin*2)*r)};L.qrToImageData=function(t,e,r){let o=e.modules.size,i=e.modules.data,s=L.getScale(o,r),u=Math.floor((o+r.margin*2)*s),c=r.margin*s,l=[r.color.light,r.color.dark];for(let a=0;a<u;a++)for(let w=0;w<u;w++){let h=(a*u+w)*4,y=r.color.light;if(a>=c&&w>=c&&a<u-c&&w<u-c){let A=Math.floor((a-c)/s),T=Math.floor((w-c)/s);y=l[i[A*o+T]?1:0]}t[h++]=y.r,t[h++]=y.g,t[h++]=y.b,t[h]=y.a}}});var Se=g(rt=>{var Mt=Nt();function Ln(n,t,e){n.clearRect(0,0,t.width,t.height),t.style||(t.style={}),t.height=e,t.width=e,t.style.height=e+"px",t.style.width=e+"px"}function _n(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}rt.render=function(t,e,r){let o=r,i=e;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),e||(i=_n()),o=Mt.getOptions(o);let s=Mt.getImageWidth(t.modules.size,o),u=i.getContext("2d"),c=u.createImageData(s,s);return Mt.qrToImageData(c.data,t,o),Ln(u,i,s),u.putImageData(c,0,0),i};rt.renderToDataURL=function(t,e,r){let o=r;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),o||(o={});let i=rt.render(t,e,o),s=o.type||"image/png",u=o.rendererOpts||{};return i.toDataURL(s,u.quality)}});var Re=g(be=>{var xn=Nt();function Pe(n,t){let e=n.a/255,r=t+'="'+n.hex+'"';return e<1?r+" "+t+'-opacity="'+e.toFixed(2).slice(1)+'"':r}function St(n,t,e){let r=n+t;return typeof e<"u"&&(r+=" "+e),r}function Un(n,t,e){let r="",o=0,i=!1,s=0;for(let u=0;u<n.length;u++){let c=Math.floor(u%t),l=Math.floor(u/t);!c&&!i&&(i=!0),n[u]?(s++,u>0&&c>0&&n[u-1]||(r+=i?St("M",c+e,.5+l+e):St("m",o,0),o=0,i=!1),c+1<t&&n[u+1]||(r+=St("h",s),s=0)):o++}return r}be.render=function(t,e,r){let o=xn.getOptions(e),i=t.modules.size,s=t.modules.data,u=i+o.margin*2,c=o.color.light.a?"<path "+Pe(o.color.light,"fill")+' d="M0 0h'+u+"v"+u+'H0z"/>':"",l="<path "+Pe(o.color.dark,"stroke")+' d="'+Un(s,i,o.margin)+'"/>',a='viewBox="0 0 '+u+" "+u+'"',h='<svg xmlns="http://www.w3.org/2000/svg" '+(o.width?'width="'+o.width+'" height="'+o.width+'" ':"")+a+' shape-rendering="crispEdges">'+c+l+`</svg>
|
|
8
|
+
`;return typeof r=="function"&&r(null,h),h}});var _e=g(O=>{var qn=Ut(),Pt=Ne(),Le=Se(),Dn=Re();function bt(n,t,e,r,o){let i=[].slice.call(arguments,1),s=i.length,u=typeof i[s-1]=="function";if(!u&&!qn())throw new Error("Callback required as last argument");if(u){if(s<2)throw new Error("Too few arguments provided");s===2?(o=e,e=t,t=r=void 0):s===3&&(t.getContext&&typeof o>"u"?(o=r,r=void 0):(o=r,r=e,e=t,t=void 0))}else{if(s<1)throw new Error("Too few arguments provided");return s===1?(e=t,t=r=void 0):s===2&&!t.getContext&&(r=e,e=t,t=void 0),new Promise(function(c,l){try{let a=Pt.create(e,r);c(n(a,t,r))}catch(a){l(a)}})}try{let c=Pt.create(e,r);o(null,n(c,t,r))}catch(c){o(c)}}O.create=Pt.create;O.toCanvas=bt.bind(null,Le.render);O.toDataURL=bt.bind(null,Le.renderToDataURL);O.toString=bt.bind(null,function(n,t,e){return Dn.render(n,e)})});var kn={};Ve(kn,{default:()=>Fn});var xe=He(_e(),1),Fn=xe.default;return Ke(kn);})();
|
|
9
|
+
window.QRCodeLib = QRCodeLib.default || QRCodeLib;
|
package/dist/web-ui/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@co0ontty/wand",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.11",
|
|
4
4
|
"description": "A web terminal for local CLI tools like Claude.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"preferGlobal": true,
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "node scripts/bundle-wterm.js && tsc -p tsconfig.json && npm run build:copy-content",
|
|
19
|
+
"build": "node scripts/bundle-wterm.js && node scripts/bundle-qrcode.js && tsc -p tsconfig.json && npm run build:copy-content",
|
|
20
20
|
"build:copy-content": "cp -r src/web-ui/content dist/web-ui/",
|
|
21
21
|
"dev": "tsx src/cli.ts web",
|
|
22
22
|
"check": "tsc --noEmit -p tsconfig.json",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@types/node": "^22.13.14",
|
|
52
52
|
"@types/ws": "^8.18.1",
|
|
53
53
|
"esbuild": "^0.28.0",
|
|
54
|
+
"qrcode": "^1.5.4",
|
|
54
55
|
"tsx": "^4.19.3",
|
|
55
56
|
"typescript": "^5.8.2"
|
|
56
57
|
}
|