pi-web-ui 0.70.0 → 0.72.0
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/CHANGELOG.md +324 -0
- package/dist/server/agent-service.js +121 -22
- package/dist/server/client-state.js +56 -0
- package/dist/server/dsh/dsh-agent-service.js +59 -0
- package/dist/server/index.js +4 -0
- package/dist/server/locales.js +1 -1
- package/dist/server/model-admin.js +37 -9
- package/dist/server/protocol-version.js +1 -1
- package/package.json +5 -1
- package/themes/cyberpunk.css +9 -0
- package/themes/dazzle.css +9 -0
- package/themes/md-preview.css +9 -0
- package/themes/translucent.css +78 -0
- package/themes/transparent.css +78 -0
- package/themes/white.css +9 -0
- package/web/dist/assets/{TerminalPanel-UxgczH4c.js → TerminalPanel-SG88Uj0n.js} +1 -1
- package/web/dist/assets/index-CBZtMKV2.js +335 -0
- package/web/dist/assets/index-DAu6etAV.css +10 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-BH5QutUc.css +0 -10
- package/web/dist/assets/index-CaiIOwy7.js +0 -335
|
@@ -177,6 +177,21 @@ export class ModelAdminService {
|
|
|
177
177
|
const data = this.readProviderKeys();
|
|
178
178
|
return data[provider]?.activeKeyName ?? null;
|
|
179
179
|
}
|
|
180
|
+
/** Whether a named key still exists for a provider (no side effects, no
|
|
181
|
+
* notices). Restore paths use this to drop stale per-project references
|
|
182
|
+
* silently instead of going through activate (which notifies). */
|
|
183
|
+
hasProviderKey(provider, keyName) {
|
|
184
|
+
const pid = provider.trim();
|
|
185
|
+
const targetName = keyName.trim();
|
|
186
|
+
if (!pid || !targetName)
|
|
187
|
+
return false;
|
|
188
|
+
try {
|
|
189
|
+
return this.readProviderKeys()[pid]?.keys.some((k) => k.name === targetName) ?? false;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
180
195
|
/** Seed a provider's key list from an EXISTING auth.json credential (legacy
|
|
181
196
|
* configs written before the multi-key store existed) so the store stays
|
|
182
197
|
* authoritative and the UI shows the current active key immediately even
|
|
@@ -373,36 +388,44 @@ export class ModelAdminService {
|
|
|
373
388
|
this.host.flushSnapshot();
|
|
374
389
|
}
|
|
375
390
|
/** Make a stored API key the ACTIVE one for a built-in provider by NAME (the
|
|
376
|
-
* server resolves the stored value from the name).
|
|
377
|
-
|
|
391
|
+
* server resolves the stored value from the name). Returns true when the
|
|
392
|
+
* key is (now) active, false when it doesn't exist or the switch failed.
|
|
393
|
+
* `silent` suppresses all notices — for automatic project restores, which
|
|
394
|
+
* must self-heal stale references without spamming the user. */
|
|
395
|
+
async activateProviderKey(provider, keyName, opts) {
|
|
378
396
|
const pid = provider.trim();
|
|
379
397
|
const targetName = keyName.trim();
|
|
398
|
+
const silent = opts?.silent === true;
|
|
399
|
+
const notice = (msg) => {
|
|
400
|
+
if (!silent)
|
|
401
|
+
this.host.emit(msg);
|
|
402
|
+
};
|
|
380
403
|
try {
|
|
381
404
|
const data = this.readProviderKeys();
|
|
382
405
|
const entry = data[pid];
|
|
383
406
|
const target = entry?.keys.find((k) => k.name === targetName);
|
|
384
407
|
if (!target) {
|
|
385
|
-
|
|
408
|
+
notice({
|
|
386
409
|
type: "notice",
|
|
387
410
|
level: "error",
|
|
388
411
|
text: `${pid} 的密钥「${targetName}」不存在`,
|
|
389
412
|
textEn: `Key "${targetName}" for ${pid} does not exist`,
|
|
390
413
|
});
|
|
391
|
-
return;
|
|
414
|
+
return false;
|
|
392
415
|
}
|
|
393
416
|
if (entry.activeKeyName === targetName) {
|
|
394
|
-
|
|
417
|
+
notice({
|
|
395
418
|
type: "notice",
|
|
396
419
|
level: "info",
|
|
397
420
|
text: `「${targetName}」已是当前密钥`,
|
|
398
421
|
textEn: `"${targetName}" is already the active key`,
|
|
399
422
|
});
|
|
400
|
-
return;
|
|
423
|
+
return true;
|
|
401
424
|
}
|
|
402
425
|
entry.activeKeyName = targetName;
|
|
403
426
|
this.writeProviderKeys(data);
|
|
404
427
|
await this.applyActiveKey(pid, target.apiKey);
|
|
405
|
-
|
|
428
|
+
notice({
|
|
406
429
|
type: "notice",
|
|
407
430
|
level: "info",
|
|
408
431
|
text: `⚡ 已切换到 ${pid} 的「${targetName}」`,
|
|
@@ -411,16 +434,21 @@ export class ModelAdminService {
|
|
|
411
434
|
await this.host.pushModels();
|
|
412
435
|
await this.listProviders();
|
|
413
436
|
this.listProviderKeys();
|
|
437
|
+
return true;
|
|
414
438
|
}
|
|
415
439
|
catch (err) {
|
|
416
|
-
|
|
440
|
+
notice({
|
|
417
441
|
type: "notice",
|
|
418
442
|
level: "error",
|
|
419
443
|
text: `切换密钥失败:${err.message}`,
|
|
420
444
|
textEn: `Failed to switch key: ${err.message}`,
|
|
421
445
|
});
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
finally {
|
|
449
|
+
if (!silent)
|
|
450
|
+
this.host.flushSnapshot();
|
|
422
451
|
}
|
|
423
|
-
this.host.flushSnapshot();
|
|
424
452
|
}
|
|
425
453
|
/** Remove a stored API key by NAME. If it was active, the first remaining key
|
|
426
454
|
* becomes active (or the provider returns to unconfigured when no key is left). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.72.0",
|
|
4
4
|
"description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"deploy/",
|
|
22
22
|
"extensions/",
|
|
23
23
|
"plugins/catalog.json",
|
|
24
|
+
"CHANGELOG.md",
|
|
24
25
|
"README.md",
|
|
25
26
|
"LICENSE"
|
|
26
27
|
],
|
|
@@ -62,6 +63,9 @@
|
|
|
62
63
|
"test:unit": "vitest run",
|
|
63
64
|
"test:smoke": "node tests/run-smoke.mjs",
|
|
64
65
|
"check:protocol": "node scripts/check-protocol-sync.mjs",
|
|
66
|
+
"i18n:diff": "node scripts/i18n-diff.mjs",
|
|
67
|
+
"release:notes": "node scripts/release-notes.mjs",
|
|
68
|
+
"changelog:i18n": "node scripts/release-notes.mjs --unreleased",
|
|
65
69
|
"test:freeze": "node tests/freeze-test.mjs",
|
|
66
70
|
"start": "node dist/server/index.js",
|
|
67
71
|
"format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
|
package/themes/cyberpunk.css
CHANGED
|
@@ -85,4 +85,13 @@
|
|
|
85
85
|
--bg-image: none;
|
|
86
86
|
--bg-image-dim: 0.78;
|
|
87
87
|
--bg-image-blur: 0px;
|
|
88
|
+
--wallpaper-panel-alpha: 62%;
|
|
89
|
+
--topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
90
|
+
--statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
91
|
+
--panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
92
|
+
--card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
93
|
+
--chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
94
|
+
--msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
95
|
+
--inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
96
|
+
--menu-bg: var(--bg-elev2);
|
|
88
97
|
}
|
package/themes/dazzle.css
CHANGED
|
@@ -85,4 +85,13 @@
|
|
|
85
85
|
--bg-image: none;
|
|
86
86
|
--bg-image-dim: 0.78;
|
|
87
87
|
--bg-image-blur: 0px;
|
|
88
|
+
--wallpaper-panel-alpha: 62%;
|
|
89
|
+
--topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
90
|
+
--statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
91
|
+
--panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
92
|
+
--card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
93
|
+
--chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
94
|
+
--msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
95
|
+
--inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
96
|
+
--menu-bg: var(--bg-elev2);
|
|
88
97
|
}
|
package/themes/md-preview.css
CHANGED
|
@@ -85,6 +85,15 @@
|
|
|
85
85
|
--bg-image: none;
|
|
86
86
|
--bg-image-dim: 0.78;
|
|
87
87
|
--bg-image-blur: 0px;
|
|
88
|
+
--wallpaper-panel-alpha: 62%;
|
|
89
|
+
--topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
90
|
+
--statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
91
|
+
--panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
92
|
+
--card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
93
|
+
--chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
94
|
+
--msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
95
|
+
--inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
96
|
+
--menu-bg: var(--bg-elev2);
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
/* ---- ambient gradient(镜像 .fp-markdown 预览底色,覆盖整个窗口)---- */
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* theme-name: 半透明 */
|
|
2
|
+
/* theme-name-en: Translucent */
|
|
3
|
+
/*
|
|
4
|
+
* 半透明主题——专为聊天背景图(壁纸,issue #100)设计:
|
|
5
|
+
* 调色板与默认暗色一致,但把所有底板统一降到半透明(顶栏/底栏/左右面板、
|
|
6
|
+
* 卡片/控件/代码面、输入框盒子、终端视图都走同一 --wallpaper-panel-alpha),
|
|
7
|
+
* 让壁纸从各处透出、整体融合成一张画。配壁纸用最佳;不配壁纸时这些区域会
|
|
8
|
+
* 透出纯色底(--bg),观感略偏暗沉,属预期。
|
|
9
|
+
*
|
|
10
|
+
* 统一透图率:--wallpaper-panel-alpha: 45%(45% 容器色 + 55% 透图)。
|
|
11
|
+
* 已覆盖的面:顶栏/底栏/左右面板、左右折叠按钮(.panel-collapse-btn /
|
|
12
|
+
* .panel-rail)、工具调用卡及其参数/输出块(.toolcall / .toolcall-args pre /
|
|
13
|
+
* .toolcall-output pre)、bash 块(.bashblock/.termline)、消息代码块
|
|
14
|
+
* (.codeblock pre)、全部消息气泡(.thinking/.toolcall/.bashblock/
|
|
15
|
+
* .skillcard/.attachcard/.queued-bubble/.retry-notice/.msg-collapsed(含 hover))、
|
|
16
|
+
* 快捷短语(.quick-chip)、新对话提示词模板卡(.empty-template)、顶栏
|
|
17
|
+
* chips / 视图切换(.chip/.view-switch)——走 styles.css
|
|
18
|
+
* 的 --card-bg/--chip-bg/--inputbox-bg,随 --wallpaper-panel-alpha 统一联动;
|
|
19
|
+
* 中间的聊天/消息区用 --msgs-bg(同式 45%),气泡立在统一玻璃面上略实
|
|
20
|
+
* 一层形成层次。**下拉弹窗保持实色**:声音/语言/主题/模型选择/思考强度等
|
|
21
|
+
* 点出来的 .dd-menu 背景用 --menu-bg(这里覆盖回 var(--bg-elev2) 实色,
|
|
22
|
+
* 弹窗内容多为密集列表,实色保可读)。终端视图(xterm canvas/容器)读
|
|
23
|
+
* --term-bg,这里同样设半透明。
|
|
24
|
+
* 各变量都可单独覆盖回实色(如 var(--bg-elev))即关闭对应面的透图;
|
|
25
|
+
* --msgs-bg 覆盖回 transparent 可恢复「消息区全透、壁纸从卡片间隙露出」。
|
|
26
|
+
*/
|
|
27
|
+
:root {
|
|
28
|
+
color-scheme: dark;
|
|
29
|
+
--bg: #0d0e12;
|
|
30
|
+
--bg-elev: #14161c;
|
|
31
|
+
--bg-elev2: #1a1d26;
|
|
32
|
+
--border: #262a35;
|
|
33
|
+
--border-soft: #1e2230;
|
|
34
|
+
--text: #e6e8ef;
|
|
35
|
+
--text-dim: #9aa1b4;
|
|
36
|
+
--text-faint: #6b7284;
|
|
37
|
+
--accent: #8b5cf6;
|
|
38
|
+
--accent-soft: rgba(139, 92, 246, 0.14);
|
|
39
|
+
--green: #34d399;
|
|
40
|
+
--green-soft: rgba(52, 211, 153, 0.12);
|
|
41
|
+
--red: #f87171;
|
|
42
|
+
--red-soft: rgba(248, 113, 113, 0.12);
|
|
43
|
+
--amber: #fbbf24;
|
|
44
|
+
--term-bg: #0b0d12;
|
|
45
|
+
--term-fg: #e6e8ef;
|
|
46
|
+
--term-cursor: #8b5cf6;
|
|
47
|
+
--term-cursor-accent: #0b0d12;
|
|
48
|
+
--term-selection: rgba(139, 92, 246, 0.35);
|
|
49
|
+
--term-black: #1a1d26;
|
|
50
|
+
--term-red: #f87171;
|
|
51
|
+
--term-green: #34d399;
|
|
52
|
+
--term-yellow: #fbbf24;
|
|
53
|
+
--term-blue: #60a5fa;
|
|
54
|
+
--term-magenta: #c084fc;
|
|
55
|
+
--term-cyan: #22d3ee;
|
|
56
|
+
--term-white: #e6e8ef;
|
|
57
|
+
--term-bright-black: #6b7284;
|
|
58
|
+
--term-bright-red: #f87171;
|
|
59
|
+
--term-bright-green: #34d399;
|
|
60
|
+
--term-bright-yellow: #fbbf24;
|
|
61
|
+
--term-bright-blue: #60a5fa;
|
|
62
|
+
--term-bright-magenta: #c084fc;
|
|
63
|
+
--term-bright-cyan: #22d3ee;
|
|
64
|
+
--term-bright-white: #ffffff;
|
|
65
|
+
|
|
66
|
+
/* ---- 壁纸适配:三大区域(顶栏/底栏/左右面板)背景链式引用此变量,
|
|
67
|
+
从默认 62% 降到 45% → 容器色更薄、图更透(45% 容器色 + 55% 透图)---- */
|
|
68
|
+
--wallpaper-panel-alpha: 45%;
|
|
69
|
+
/* 下拉弹窗(声音/语言/主题/模型/思考强度/版本更新):实色底保密集列表可读
|
|
70
|
+
(与 styles.css 默认一致,这里显式锁定,防止跟随壁纸半透)。 */
|
|
71
|
+
--menu-bg: var(--bg-elev2);
|
|
72
|
+
/* 压暗略放轻(默认 0.78):让图更鲜活,文字靠压暗与半透明底板仍可读 */
|
|
73
|
+
--bg-image-dim: 0.72;
|
|
74
|
+
/* 输入框盒子:styles.css 默认已与控件级底板同式跟随 --wallpaper-panel-alpha,
|
|
75
|
+
这里不单独覆盖;想比整体厚/薄就设一个独立值 */
|
|
76
|
+
/* 终端视图:xterm canvas + 容器都读 --term-bg,改成半透明随整体透图 */
|
|
77
|
+
--term-bg: color-mix(in srgb, #0b0d12 45%, transparent);
|
|
78
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/* theme-name: 全透明 */
|
|
2
|
+
/* theme-name-en: Transparent */
|
|
3
|
+
/*
|
|
4
|
+
* 全透明主题——「半透明」的极致版(专配壁纸,issue #100):
|
|
5
|
+
* 调色板与默认暗色一致,但把壁纸机制里所有表面变量的透图率压到 0
|
|
6
|
+
* (--wallpaper-panel-alpha: 0% → --topbar-bg / --statusbar-bg / --panel-bg /
|
|
7
|
+
* --card-bg / --chip-bg / --inputbox-bg / --msgs-bg 全部变成 transparent),
|
|
8
|
+
* 顶栏/底栏/左右面板/消息区/输入框/全部气泡/代码块/终端视图统统直接见壁纸,
|
|
9
|
+
* 界面只剩边框与文字定结构。代价是文字全靠 --bg-image-dim 压暗撑着——
|
|
10
|
+
* 这里压暗加重到 0.85(默认 0.78),亮区壁纸下文字仍可读。
|
|
11
|
+
*
|
|
12
|
+
* 全透后 hover/浮动反馈不能依赖容器色(已是 0%),本文件尾段把这些实色
|
|
13
|
+
* hover 统一改成 25% 半透底(折叠摘要、展开条、折叠键、复制键、滚到底按钮);
|
|
14
|
+
* 强调色 hover(accent-soft)与语义按钮(发送/停止/杀进程)不受影响。
|
|
15
|
+
* 下拉弹窗(声音/语言/主题/模型/思考强度等 .dd-menu)保持实色
|
|
16
|
+
* (--menu-bg: var(--bg-elev2)),密集列表不随界面透图。
|
|
17
|
+
* 配壁纸用最佳;不配壁纸时界面直接透出 --bg 纯色(= 默认暗色,无差别)。
|
|
18
|
+
*/
|
|
19
|
+
:root {
|
|
20
|
+
color-scheme: dark;
|
|
21
|
+
--bg: #0d0e12;
|
|
22
|
+
--bg-elev: #14161c;
|
|
23
|
+
--bg-elev2: #1a1d26;
|
|
24
|
+
--border: #262a35;
|
|
25
|
+
--border-soft: #1e2230;
|
|
26
|
+
--text: #e6e8ef;
|
|
27
|
+
--text-dim: #9aa1b4;
|
|
28
|
+
--text-faint: #6b7284;
|
|
29
|
+
--accent: #8b5cf6;
|
|
30
|
+
--accent-soft: rgba(139, 92, 246, 0.14);
|
|
31
|
+
--green: #34d399;
|
|
32
|
+
--green-soft: rgba(52, 211, 153, 0.12);
|
|
33
|
+
--red: #f87171;
|
|
34
|
+
--red-soft: rgba(248, 113, 113, 0.12);
|
|
35
|
+
--amber: #fbbf24;
|
|
36
|
+
--term-bg: transparent;
|
|
37
|
+
--term-fg: #e6e8ef;
|
|
38
|
+
--term-cursor: #8b5cf6;
|
|
39
|
+
--term-cursor-accent: #0b0d12;
|
|
40
|
+
--term-selection: rgba(139, 92, 246, 0.35);
|
|
41
|
+
--term-black: #1a1d26;
|
|
42
|
+
--term-red: #f87171;
|
|
43
|
+
--term-green: #34d399;
|
|
44
|
+
--term-yellow: #fbbf24;
|
|
45
|
+
--term-blue: #60a5fa;
|
|
46
|
+
--term-magenta: #c084fc;
|
|
47
|
+
--term-cyan: #22d3ee;
|
|
48
|
+
--term-white: #e6e8ef;
|
|
49
|
+
--term-bright-black: #6b7284;
|
|
50
|
+
--term-bright-red: #f87171;
|
|
51
|
+
--term-bright-green: #34d399;
|
|
52
|
+
--term-bright-yellow: #fbbf24;
|
|
53
|
+
--term-bright-blue: #60a5fa;
|
|
54
|
+
--term-bright-magenta: #c084fc;
|
|
55
|
+
--term-bright-cyan: #22d3ee;
|
|
56
|
+
--term-bright-white: #ffffff;
|
|
57
|
+
|
|
58
|
+
/* ---- 全透明核心:0% 容器色 = 全部 color-mix 表面(三大区域 / 卡片 /
|
|
59
|
+
控件 / 输入框 / 消息区)直接变 transparent;终端 --term-bg 上面已设
|
|
60
|
+
transparent。想留一点点玻璃感就把这里提到 10~15%。---- */
|
|
61
|
+
--wallpaper-panel-alpha: 0%;
|
|
62
|
+
/* 下拉弹窗(声音/语言/主题/模型/思考强度):实色底保密集列表可读 */
|
|
63
|
+
--menu-bg: var(--bg-elev2);
|
|
64
|
+
/* 压暗加重:全透后没有容器色兜底,文字只靠压暗保可读 */
|
|
65
|
+
--bg-image-dim: 0.85;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* hover / 浮动静置反馈:0% 容器色下这些实色 hover 必消失,统一给 25% 半透
|
|
69
|
+
底(仍透图、可辨反馈)。强调色 hover(accent-soft)与语义按钮不受影响;
|
|
70
|
+
下拉弹窗已在实色菜单内,其 hover 保留 styles.css 默认实色。 */
|
|
71
|
+
.msg-collapsed:hover,
|
|
72
|
+
.panel-rail:hover,
|
|
73
|
+
.chead-toggle:hover,
|
|
74
|
+
.chead-copy:hover,
|
|
75
|
+
.empty-templates-reset:hover,
|
|
76
|
+
.scroll-bottom {
|
|
77
|
+
background: color-mix(in srgb, var(--bg-elev) 25%, transparent);
|
|
78
|
+
}
|
package/themes/white.css
CHANGED
|
@@ -85,6 +85,15 @@
|
|
|
85
85
|
--bg-image: none;
|
|
86
86
|
--bg-image-dim: 0.78;
|
|
87
87
|
--bg-image-blur: 0px;
|
|
88
|
+
--wallpaper-panel-alpha: 62%;
|
|
89
|
+
--topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
90
|
+
--statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
91
|
+
--panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
92
|
+
--card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
93
|
+
--chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
94
|
+
--msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
95
|
+
--inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
|
|
96
|
+
--menu-bg: var(--bg-elev2);
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
/* ---- syntax highlighting (overrides static github-dark import) ---- */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as l,j as n}from"./markdown-Cpo0pNcR.js";import{u as P,b as O,T as M,a as W,F as Y,c as z,d as Z,e as H,f as ee,g as ne,h as te,i as se,r as ae}from"./index-
|
|
1
|
+
import{a as l,j as n}from"./markdown-Cpo0pNcR.js";import{u as P,b as O,T as M,a as W,F as Y,c as z,d as Z,e as H,f as ee,g as ne,h as te,i as se,r as ae}from"./index-CBZtMKV2.js";import{D as re,o as ie}from"./xterm-B96xOxS9.js";import"./react-CtudoG1_.js";function le(t){let c=null;return{clean:t.replace(/\r?\n?\[pi-term-exit:(-?\d+)\]\r?\n?/g,(a,x)=>(c=Number(x),`\r
|
|
2
2
|
`)).replace(/\r?\n?\x1b\[90m\[(?:进程已退出,退出码 |Process exited with code )-?\d+\]\x1b\[0m\r?\n?/g,`\r
|
|
3
3
|
`),exitCode:c}}function ce({conversationId:t,terminalId:c,command:p,cwd:a,title:x,active:u,running:v,exitCode:j,send:h,register:C}){const T=l.useRef(null),y=l.useRef(null),{locale:o}=P(),N=l.useRef(o);N.current=o;const E=p?JSON.stringify(p):"";l.useEffect(()=>{const m=T.current;if(!m)return;const r=new re({theme:O(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),b=new ie;r.loadAddon(b),r.open(m),y.current={term:r,fit:b},u&&r.focus();const g=()=>{r.options.theme=O()};window.addEventListener(M,g),r.attachCustomKeyEventHandler(d=>{if(d.type!=="keydown")return!0;const S=d.key?.toLowerCase();if((d.ctrlKey||d.metaKey)&&S==="v")return!1;if(d.ctrlKey&&!d.shiftKey&&!d.altKey&&S==="c"&&r.hasSelection()){const D=r.textarea;return D&&(D.value=r.getSelection(),D.select()),!1}return!0});const _=C(t,c,{write:d=>r.write(le(d).clean),dispose:()=>r.dispose()}),$=()=>{try{b.fit(),h({type:"terminal_resize",terminalId:c,conversationId:t,cols:r.cols,rows:r.rows})}catch{}},B=requestAnimationFrame(()=>{try{b.fit()}catch{}h(p?{type:"run_command",terminalId:c,conversationId:t,command:p,cols:r.cols,rows:r.rows}:{type:"terminal_create",terminalId:c,title:x,locale:N.current,conversationId:t,cwd:a,cols:r.cols,rows:r.rows})}),R=r.onData(d=>{h({type:"terminal_input",terminalId:c,conversationId:t,data:d})});let k=null;return typeof ResizeObserver<"u"&&(k=new ResizeObserver(()=>{m.offsetWidth>0&&m.offsetHeight>0&&$()}),k.observe(m)),()=>{cancelAnimationFrame(B),R.dispose(),window.removeEventListener(M,g),k?.disconnect(),_(),r.dispose(),y.current=null}},[t,c,E,h,C]),l.useEffect(()=>{if(!u)return;const m=requestAnimationFrame(()=>{const r=y.current;if(r){try{r.fit.fit(),h({type:"terminal_resize",terminalId:c,conversationId:t,cols:r.term.cols,rows:r.term.rows})}catch{}r.term.focus()}});return()=>cancelAnimationFrame(m)},[u]);const{t:F}=P(),f=l.useRef(void 0);return l.useEffect(()=>{if(v===f.current||(f.current=v,v!==!1))return;const m=y.current;m&&m.term.write(`\r
|
|
4
4
|
\x1B[90m${F("exitBanner",{code:j??""})}\x1B[0m\r
|