pi-web-ui 0.92.0 → 0.94.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +74 -2
  2. package/README.md +69 -14
  3. package/README.zh-CN.md +36 -10
  4. package/bin/pi-web-ui.mjs +18 -6
  5. package/dist/server/agent-service.js +577 -127
  6. package/dist/server/auth-cookie.js +26 -0
  7. package/dist/server/claim-files-tool.js +6 -7
  8. package/dist/server/client-state.js +125 -8
  9. package/dist/server/conversation-read-tool.js +2 -1
  10. package/dist/server/delegate-task.js +10 -3
  11. package/dist/server/dsh/dsh-agent-service.js +43 -1
  12. package/dist/server/files-service.js +79 -27
  13. package/dist/server/http-proxy.js +72 -0
  14. package/dist/server/index.js +84 -17
  15. package/dist/server/patch-node-pty.js +11 -0
  16. package/dist/server/plugins.js +1 -0
  17. package/dist/server/protocol-version.js +1 -1
  18. package/dist/server/read-tool.js +37 -3
  19. package/dist/server/resolve-global-sdk.js +72 -0
  20. package/dist/server/sdk-origin.js +64 -0
  21. package/dist/server/serialize.js +59 -21
  22. package/dist/server/settings-service.js +12 -1
  23. package/dist/server/skill-tool.js +2 -1
  24. package/dist/server/soft-cap.js +38 -4
  25. package/dist/server/subagents.js +30 -13
  26. package/dist/server/terminals.js +38 -18
  27. package/dist/server/themes.js +15 -0
  28. package/dist/server/tool-info.js +89 -0
  29. package/dist/server/tool-manager.js +107 -14
  30. package/package.json +2 -2
  31. package/plugins/catalog.json +10 -0
  32. package/themes/ayu-light.css +136 -0
  33. package/themes/catppuccin-latte.css +4 -0
  34. package/themes/catppuccin.css +4 -0
  35. package/themes/codex.css +136 -0
  36. package/themes/cyberpunk.css +4 -0
  37. package/themes/dazzle.css +4 -0
  38. package/themes/everforest-light.css +136 -0
  39. package/themes/geist.css +136 -0
  40. package/themes/gruvbox-light.css +136 -0
  41. package/themes/kanagawa-lotus.css +136 -0
  42. package/themes/md-preview.css +4 -0
  43. package/themes/mist.css +4 -0
  44. package/themes/nord.css +4 -0
  45. package/themes/one-dark.css +4 -0
  46. package/themes/paper.css +4 -0
  47. package/themes/rose-pine-dawn.css +136 -0
  48. package/themes/sakura.css +4 -0
  49. package/themes/solarized-light.css +4 -0
  50. package/themes/tokyo-night.css +4 -0
  51. package/themes/white.css +4 -0
  52. package/web/dist/assets/{TerminalPanel-RACpk6AX.js → TerminalPanel-B-CMQuzm.js} +1 -1
  53. package/web/dist/assets/index-18jK6al2.js +364 -0
  54. package/web/dist/assets/index-B3S9MxnN.css +1 -0
  55. package/web/dist/index.html +2 -2
  56. package/web/dist/assets/index-BgrnP9Jz.js +0 -364
  57. package/web/dist/assets/index-Cy8dSTZt.css +0 -1
@@ -0,0 +1,89 @@
1
+ /** parameters(JSON Schema)的体积上限:超过就整丢。 */
2
+ export const TOOL_PARAMETERS_CAP = 64_000;
3
+ /** description 的字数上限(SDK 里的工具描述很少超过几百字,这里防的是扩展写疯)。 */
4
+ export const TOOL_DESCRIPTION_CAP = 8_000;
5
+ /** promptGuidelines 合计字数上限(进系统提示词的要点,正常都很短)。 */
6
+ export const TOOL_GUIDELINES_CAP = 8_000;
7
+ function str(v) {
8
+ if (typeof v !== "string")
9
+ return undefined;
10
+ const s = v.trim();
11
+ return s ? s : undefined;
12
+ }
13
+ /** 超长截断(`…` 结尾,与前端 truncateText 同款标记)。 */
14
+ function cut(s, cap) {
15
+ return s.length > cap ? `${s.slice(0, cap)}…` : s;
16
+ }
17
+ /** 参数 schema 是否可下发(能序列化且不超上限)。 */
18
+ function parametersWithinCap(params) {
19
+ if (params === undefined || params === null)
20
+ return false;
21
+ try {
22
+ const text = JSON.stringify(params);
23
+ return typeof text === "string" && text.length <= TOOL_PARAMETERS_CAP;
24
+ }
25
+ catch {
26
+ // 循环引用 / BigInt 等序列化不了的值:当成「没有 schema」。
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * 归一化一条工具定义 → wire 载荷。
32
+ *
33
+ * @param name 请求里的工具名(**永远以它为准**:定义里的 name 缺失时前端仍要能显示标题)。
34
+ * @param raw 引擎给的定义;undefined/null = 没找到。
35
+ */
36
+ export function normalizeToolInfo(name, raw) {
37
+ const toolName = str(name) ?? "";
38
+ if (!raw || typeof raw !== "object")
39
+ return { name: toolName, found: false };
40
+ const payload = { name: toolName, found: true };
41
+ const label = str(raw.label);
42
+ if (label)
43
+ payload.label = cut(label, 200);
44
+ const description = str(raw.description);
45
+ if (description)
46
+ payload.description = cut(description, TOOL_DESCRIPTION_CAP);
47
+ const snippet = str(raw.promptSnippet);
48
+ if (snippet)
49
+ payload.promptSnippet = cut(snippet, TOOL_DESCRIPTION_CAP);
50
+ if (Array.isArray(raw.promptGuidelines)) {
51
+ const guidelines = [];
52
+ let total = 0;
53
+ for (const g of raw.promptGuidelines) {
54
+ const text = str(g);
55
+ if (!text)
56
+ continue;
57
+ if (total + text.length > TOOL_GUIDELINES_CAP)
58
+ break;
59
+ guidelines.push(text);
60
+ total += text.length;
61
+ }
62
+ if (guidelines.length > 0)
63
+ payload.promptGuidelines = guidelines;
64
+ }
65
+ if (raw.parameters !== undefined && raw.parameters !== null) {
66
+ if (parametersWithinCap(raw.parameters))
67
+ payload.parameters = raw.parameters;
68
+ else
69
+ payload.parametersDropped = true;
70
+ }
71
+ if (raw.active === true)
72
+ payload.active = true;
73
+ else if (raw.active === false)
74
+ payload.active = false;
75
+ const info = raw.sourceInfo;
76
+ if (info && typeof info === "object") {
77
+ const source = str(info.source);
78
+ if (source)
79
+ payload.source = source;
80
+ const scope = str(info.scope);
81
+ if (scope)
82
+ payload.scope = scope;
83
+ }
84
+ return payload;
85
+ }
86
+ /** 当前引擎不支持枚举工具定义时的应答(前端据此显示「当前引擎不支持」而不是「未找到」)。 */
87
+ export function unsupportedToolInfo(name) {
88
+ return { name: str(name) ?? "", found: false, unsupported: true };
89
+ }
@@ -61,9 +61,12 @@ export const SCHEDULE_CANCEL_TOOL_NAME = "schedule_cancel";
61
61
  /** 展示文件工具(定义见 present-files-tool.ts):把图片/视频/文本作为预览卡片
62
62
  * 推到对话里,卡片带预览/本地打开/在文件夹中显示/下载/复制路径。 */
63
63
  export const PRESENT_FILES_TOOL_NAME = "present_files";
64
+ /** 文件认领工具(定义见 claim-files-tool.ts):声明要改哪些文件,让同项目的
65
+ * 并行对话绕行(纯建议,不拦编辑)。 */
66
+ export const CLAIM_FILES_TOOL_NAME = "claim_files";
64
67
  /** 旧工具名(持久化迁移用;新代码一律用 MARKERS_LIST_TOOL_NAME)。 */
65
68
  export const LEGACY_MARKERS_LIST_TOOL_NAME = "markers_list";
66
- /** 可开关的 Agent 工具总目录(共 25 个;bash 本体与 SDK 内置 edit/read
69
+ /** 可开关的 Agent 工具总目录(共 26 个;bash 本体与 SDK 内置 edit/read
67
70
  * 不进目录——关了 agent 就残了,不给关)。 */
68
71
  export const AGENT_TOOL_CATALOG = [
69
72
  ...TERMINAL_TOOL_NAMES.map((name) => ({
@@ -78,26 +81,116 @@ export const AGENT_TOOL_CATALOG = [
78
81
  defaultOn: true,
79
82
  dshVisible: false,
80
83
  })),
81
- { name: EDIT_SOFT_TOOL_NAME, group: "other", defaultOn: false, dshVisible: false },
82
- { name: DELEGATE_TASK_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
83
- { name: ASK_USER_QUESTION_TOOL_NAME, group: "other", defaultOn: true, dshVisible: true },
84
- { name: MARKERS_LIST_TOOL_NAME, group: "other", defaultOn: true, dshVisible: true },
84
+ {
85
+ name: EDIT_SOFT_TOOL_NAME,
86
+ group: "other",
87
+ defaultOn: false,
88
+ dshVisible: false,
89
+ descKey: "editSoftEnabledDesc",
90
+ offHintKey: "editSoftOffHint",
91
+ },
92
+ {
93
+ name: DELEGATE_TASK_TOOL_NAME,
94
+ group: "other",
95
+ defaultOn: true,
96
+ dshVisible: false,
97
+ descKey: "delegateTaskEnabledDesc",
98
+ offHintKey: "delegateTaskOffHint",
99
+ },
100
+ {
101
+ name: ASK_USER_QUESTION_TOOL_NAME,
102
+ group: "other",
103
+ defaultOn: true,
104
+ dshVisible: true,
105
+ descKey: "questionnaireEnabledDesc",
106
+ offHintKey: "questionnaireOffHint",
107
+ },
85
108
  // 默认关(AI 动用户浏览器,opt-in 才开)且 dshVisible=false:DSH 引擎没有页面桥
86
109
  // (page_request 由 pi 引擎的 customTool 发出),列在那里只会让用户关一个不存在的工具。
87
- { name: BROWSER_PAGE_TOOL_NAME, group: "other", defaultOn: false, dshVisible: false },
110
+ {
111
+ name: BROWSER_PAGE_TOOL_NAME,
112
+ group: "other",
113
+ defaultOn: false,
114
+ dshVisible: false,
115
+ descKey: "browserPageEnabledDesc",
116
+ offHintKey: "browserPageOffHint",
117
+ },
88
118
  // 只读别的对话(含子代理实时消息与历史转录),默认开;DSH 引擎没有该 customTool。
89
- { name: CONVERSATION_READ_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
119
+ {
120
+ name: CONVERSATION_READ_TOOL_NAME,
121
+ group: "other",
122
+ defaultOn: true,
123
+ dshVisible: false,
124
+ descKey: "conversationReadEnabledDesc",
125
+ offHintKey: "conversationReadOffHint",
126
+ },
127
+ // 文件认领(事前打招呼,纯 advisory):默认开,不打开 AI 不知道能认领;
128
+ // 关掉只少一路提醒(事后触碰集照常工作);DSH 引擎没有该 customTool
129
+ // (走 goal-rpc,无 customTool 注册面),提醒是服务端算的、DSH 照样能看到。
130
+ {
131
+ name: CLAIM_FILES_TOOL_NAME,
132
+ group: "other",
133
+ defaultOn: true,
134
+ dshVisible: false,
135
+ descKey: "claimFilesEnabledDesc",
136
+ offHintKey: "claimFilesOffHint",
137
+ },
138
+ // 展示文件给用户(图片/视频内联、文本开预览弹窗、本地打开按钮):默认开,
139
+ // 不打开模型根本不知道能“给用户看”;DSH 引擎没有该 customTool(走 shipped preset)。
140
+ {
141
+ name: PRESENT_FILES_TOOL_NAME,
142
+ group: "other",
143
+ defaultOn: true,
144
+ dshVisible: false,
145
+ descKey: "presentFilesEnabledDesc",
146
+ offHintKey: "presentFilesOffHint",
147
+ },
90
148
  // 技能全文按名加载(名录仍在 {{skills}} 段),默认开;DSH 引擎没有该 customTool
91
149
  // (走 goal-rpc,无 customTool 注册面)。
92
- { name: SKILL_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
150
+ {
151
+ name: SKILL_TOOL_NAME,
152
+ group: "other",
153
+ defaultOn: true,
154
+ dshVisible: false,
155
+ descKey: "skillEnabledDesc",
156
+ offHintKey: "skillOffHint",
157
+ },
93
158
  // 定时/延时唤醒:默认开(不打开 AI 根本不知道能定时;60s 间隔底线+面板可随时取消),
94
159
  // DSH 引擎没有该 customTool(走 goal-rpc,无 customTool 注册面)。
95
- { name: SCHEDULE_TASK_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
96
- { name: SCHEDULE_LIST_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
97
- { name: SCHEDULE_CANCEL_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
98
- // 展示文件给用户(图片/视频内联、文本开预览弹窗、本地打开按钮):默认开,
99
- // 不打开模型根本不知道能“给用户看”;DSH 引擎没有该 customTool(走 shipped preset)。
100
- { name: PRESENT_FILES_TOOL_NAME, group: "other", defaultOn: true, dshVisible: false },
160
+ {
161
+ name: SCHEDULE_TASK_TOOL_NAME,
162
+ group: "other",
163
+ defaultOn: true,
164
+ dshVisible: false,
165
+ descKey: "scheduleTaskEnabledDesc",
166
+ offHintKey: "scheduleTaskOffHint",
167
+ },
168
+ {
169
+ name: SCHEDULE_LIST_TOOL_NAME,
170
+ group: "other",
171
+ defaultOn: true,
172
+ dshVisible: false,
173
+ descKey: "scheduleTaskEnabledDesc",
174
+ offHintKey: "scheduleTaskOffHint",
175
+ },
176
+ {
177
+ name: SCHEDULE_CANCEL_TOOL_NAME,
178
+ group: "other",
179
+ defaultOn: true,
180
+ dshVisible: false,
181
+ descKey: "scheduleTaskEnabledDesc",
182
+ offHintKey: "scheduleTaskOffHint",
183
+ },
184
+ // todo_list 唯一例外:行不在「其他」组,固定在上面的 markers 分区(设置页循环
185
+ // 跳过它,见 OTHER_AGENT_TOOLS;文案 key 照给,万一哪天搬家不用补)。
186
+ {
187
+ name: MARKERS_LIST_TOOL_NAME,
188
+ group: "other",
189
+ defaultOn: true,
190
+ dshVisible: true,
191
+ descKey: "todoListEnabledDesc",
192
+ offHintKey: "todoListOffHint",
193
+ },
101
194
  ];
102
195
  const KNOWN_NAMES = new Set(AGENT_TOOL_CATALOG.map((t) => t.name));
103
196
  /** 是否为本表登记的可开关工具(未知名一律 false,不抛错)。 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web-ui",
3
- "version": "0.92.0",
3
+ "version": "0.94.0",
4
4
  "description": "Just open your browser to get all your work done — browser cockpit for AI coding agents (chat, code, files, terminal, Git in one tab)",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -84,7 +84,7 @@
84
84
  "dependencies": {
85
85
  "@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
86
86
  "@deepseek-ai/dsh-sdk-protocol": "^0.1.1-rc.2",
87
- "@earendil-works/pi-coding-agent": "^0.85.1",
87
+ "@earendil-works/pi-coding-agent": ">=0.85.1 <0.87.0",
88
88
  "@xterm/addon-fit": "^0.11.0",
89
89
  "@xterm/xterm": "^6.0.0",
90
90
  "compression": "^1.8.2",
@@ -108,5 +108,15 @@
108
108
  "descriptionEn": "Notes, todos and scheduled reminders in one place: a freely draggable always-on-top panel (position, size and settings all live in it, no separate view tab); reminders fire server-side (survive restarts, delivered on next open), with 5 AI tools and /note /todo /remind quick capture.",
109
109
  "source": "xing-shuyin/pi-web-ui/plugins/notes",
110
110
  "homepage": "https://github.com/xing-shuyin/pi-web-ui/tree/main/plugins/notes"
111
+ },
112
+ {
113
+ "id": "pi-web-multigit",
114
+ "name": "multi-git",
115
+ "icon": "🌿",
116
+ "iconSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"18\" r=\"3\"/><circle cx=\"6\" cy=\"6\" r=\"3\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><path d=\"M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9\"/><path d=\"M12 12v3\"/></svg>",
117
+ "description": "多仓库 Git 总览:工作区内每个仓库的变更、差异、历史、分支、贮藏、跨仓搜索与时间线,另有工作区分支聚合、Fetch/Pull 与内置终端(其余只读)。",
118
+ "descriptionEn": "Multi-repo Git overview: changes, diffs, history, branches, stashes, cross-repo search and a timeline for every repository in the workspace, plus a workspace-wide branch view, Fetch/Pull and an optional terminal.",
119
+ "source": "EinErste/pi-web-multigit",
120
+ "homepage": "https://github.com/EinErste/pi-web-multigit"
111
121
  }
112
122
  ]
@@ -0,0 +1,136 @@
1
+ /* theme-name: 浅阑秋 */
2
+ /* theme-name-en: Ayu Light */
3
+ /* theme-group: classic */
4
+ :root {
5
+ color-scheme: light;
6
+ --bg: #fcfcfc;
7
+ --bg-elev: #f8f9fa;
8
+ --bg-elev2: #f0f1f3;
9
+ --border: #e0e1e3;
10
+ --border-soft: #ecedef;
11
+ --text: #5c6166;
12
+ --text-dim: #66727f;
13
+ --text-faint: #6a7582;
14
+ --accent: #f29718;
15
+ --accent-soft: rgba(242, 151, 24, 0.14);
16
+ --green: #86b300;
17
+ --green-soft: rgba(134, 179, 0, 0.12);
18
+ --red: #f07171;
19
+ --red-soft: rgba(240, 113, 113, 0.1);
20
+ --amber: #e59645;
21
+ --blue: #3b82f6;
22
+ --blue-soft: rgba(59, 130, 246, 0.12);
23
+ --term-bg: #fcfcfc;
24
+ --term-fg: #5c6166;
25
+ --term-cursor: #f29718;
26
+ --term-cursor-accent: #fcfcfc;
27
+ --term-selection: rgba(242, 151, 24, 0.24);
28
+ --term-black: #5c6166;
29
+ --term-red: #f07171;
30
+ --term-green: #86b300;
31
+ --term-yellow: #eba400;
32
+ --term-blue: #22a4e6;
33
+ --term-magenta: #a37acc;
34
+ --term-cyan: #4cbf99;
35
+ --term-white: #f8f9fa;
36
+ --term-bright-black: #828e9f;
37
+ --term-bright-red: #f07171;
38
+ --term-bright-green: #86b300;
39
+ --term-bright-yellow: #eba400;
40
+ --term-bright-blue: #22a4e6;
41
+ --term-bright-magenta: #a37acc;
42
+ --term-bright-cyan: #4cbf99;
43
+ --term-bright-white: #ffffff;
44
+ --mono: "SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
45
+ --mermaid-font-size: 12px;
46
+ --tooltip-bg: #f8f9fa;
47
+ --code-bg: #f0f1f3;
48
+ --code-text: #5c6166;
49
+ --code-border: var(--border-soft);
50
+ --code-pad: 8px 10px;
51
+ --card-body-pad: 4px 14px 12px;
52
+ --err-text: #e55a5a;
53
+ --red-text: #e55a5a;
54
+ --amber-text: #c77e24;
55
+ --info-blue: #22a4e6;
56
+ --link: #22a4e6;
57
+ --link-hover: #1a8fc4;
58
+ --link-soft: #22a4e6;
59
+ --md-strong: #5c6166;
60
+ --skill-blue: #22a4e6;
61
+ --plugin-purple: #b58cff;
62
+ --auth-green: #18a97c;
63
+ --scroll-thumb: #d8dade;
64
+ --scroll-thumb-hover: #b9bcc2;
65
+ --notice-err-bg: #401d23;
66
+ --notice-warn-bg: #38251f;
67
+ --notice-info-bg: #1b2544;
68
+ --notice-err-border: #ef4444;
69
+ --notice-warn-border: #f59e0b;
70
+ --notice-info-border: #3b82f6;
71
+ --send-blue: #f29718;
72
+ --send-blue-hover: #e08a0d;
73
+ --stop-red: #ef4444;
74
+ --stop-red-hover: #dc2626;
75
+ --brand-grad-a: #f29718;
76
+ --brand-grad-b: #f07171;
77
+ --on-amber: #1a1a1a;
78
+ --search-active-fg: #1a1d26;
79
+ --switch-knob: #ffffff;
80
+ --bg-elev3: rgba(255, 255, 255, 0.06);
81
+ --sunken-bg: rgba(0, 0, 0, 0.15);
82
+ --glow-015: rgba(255, 255, 255, 0.015);
83
+ --glow-025: rgba(255, 255, 255, 0.025);
84
+ --glow-03: rgba(255, 255, 255, 0.03);
85
+ --glow-04: rgba(255, 255, 255, 0.04);
86
+ --glow-05: rgba(255, 255, 255, 0.05);
87
+ --glow-12: rgba(255, 255, 255, 0.12);
88
+ --glow-18: rgba(255, 255, 255, 0.18);
89
+ --glow-22: rgba(255, 255, 255, 0.22);
90
+ --glow-38: rgba(255, 255, 255, 0.38);
91
+ --control-fg: #6b7d8f;
92
+ --control-bg: #f0f1f3;
93
+ --control-border: #e0e1e3;
94
+ --bg-image: none;
95
+ --bg-image-dim: 0.78;
96
+ --bg-image-blur: 0px;
97
+ --wallpaper-panel-alpha: 100%;
98
+ --topbar-bg: #f8f9fa;
99
+ --statusbar-bg: #fcfcfc;
100
+ --panel-bg: #f8f9fa;
101
+ --card-bg: #f8f9fa;
102
+ --chip-bg: #f0f1f3;
103
+ --msgs-bg: #fcfcfc;
104
+ --inputbox-bg: #f0f1f3;
105
+ --menu-bg: var(--bg-elev2);
106
+ }
107
+
108
+ /* ---- syntax highlighting (Ayu Light) ---- */
109
+ .hljs {
110
+ color: #5c6166;
111
+ background: #f0f1f3;
112
+ }
113
+ .hljs-keyword,
114
+ .hljs-meta .hljs-keyword {
115
+ color: #fa8532;
116
+ font-weight: 600;
117
+ }
118
+ .hljs-title,
119
+ .hljs-title.function_ {
120
+ color: #eba400;
121
+ }
122
+ .hljs-number,
123
+ .hljs-literal {
124
+ color: #a37acc;
125
+ }
126
+ .hljs-string {
127
+ color: #86b300;
128
+ }
129
+ .hljs-built_in,
130
+ .hljs-type {
131
+ color: #55b4d4;
132
+ }
133
+ .hljs-comment {
134
+ color: #6a7582;
135
+ font-style: italic;
136
+ }
@@ -18,6 +18,8 @@
18
18
  --red: #d20f39;
19
19
  --red-soft: rgba(210, 15, 57, 0.1);
20
20
  --amber: #df8e1d;
21
+ --blue: #3b82f6;
22
+ --blue-soft: rgba(59, 130, 246, 0.12);
21
23
  --term-bg: #eff1f5;
22
24
  --term-fg: #4c4f69;
23
25
  --term-cursor: #dc8a78;
@@ -68,6 +70,8 @@
68
70
  --notice-info-border: #3b82f6;
69
71
  --send-blue: #1e66f5;
70
72
  --send-blue-hover: #7287fd;
73
+ --stop-red: #ef4444;
74
+ --stop-red-hover: #dc2626;
71
75
  --brand-grad-a: #1e66f5;
72
76
  --brand-grad-b: #8839ef;
73
77
  --on-amber: #1a1a1a;
@@ -18,6 +18,8 @@
18
18
  --red: #f38ba8;
19
19
  --red-soft: rgba(243, 139, 168, 0.12);
20
20
  --amber: #f9e2af;
21
+ --blue: #3b82f6;
22
+ --blue-soft: rgba(59, 130, 246, 0.12);
21
23
  --term-bg: #181825;
22
24
  --term-fg: #cdd6f4;
23
25
  --term-cursor: #f5e0dc;
@@ -68,6 +70,8 @@
68
70
  --notice-info-border: #3b82f6;
69
71
  --send-blue: #89b4fa;
70
72
  --send-blue-hover: #b4befe;
73
+ --stop-red: #ef4444;
74
+ --stop-red-hover: #dc2626;
71
75
  --brand-grad-a: #89b4fa;
72
76
  --brand-grad-b: #cba6f7;
73
77
  --on-amber: #1a1a1a;
@@ -0,0 +1,136 @@
1
+ /* theme-name: Codex 清白 */
2
+ /* theme-name-en: Codex Pure */
3
+ /* theme-group: classic */
4
+ :root {
5
+ color-scheme: light;
6
+ --bg: #ffffff;
7
+ --bg-elev: #f7f7f8;
8
+ --bg-elev2: #f0f0f2;
9
+ --border: #e5e5e5;
10
+ --border-soft: #ececf1;
11
+ --text: #0d0d0d;
12
+ --text-dim: #5d5d5d;
13
+ --text-faint: #6b6b7b;
14
+ --accent: #10a37f;
15
+ --accent-soft: rgba(16, 163, 127, 0.12);
16
+ --green: #10a37f;
17
+ --green-soft: rgba(16, 163, 127, 0.12);
18
+ --red: #ef4444;
19
+ --red-soft: rgba(239, 68, 68, 0.1);
20
+ --amber: #f59e0b;
21
+ --blue: #3b82f6;
22
+ --blue-soft: rgba(59, 130, 246, 0.12);
23
+ --term-bg: #f9f9fb;
24
+ --term-fg: #0d0d0d;
25
+ --term-cursor: #10a37f;
26
+ --term-cursor-accent: #ffffff;
27
+ --term-selection: rgba(16, 163, 127, 0.22);
28
+ --term-black: #0d0d0d;
29
+ --term-red: #ef4444;
30
+ --term-green: #10a37f;
31
+ --term-yellow: #f59e0b;
32
+ --term-blue: #2563eb;
33
+ --term-magenta: #8b5cf6;
34
+ --term-cyan: #06b6d4;
35
+ --term-white: #f7f7f8;
36
+ --term-bright-black: #5d5d5d;
37
+ --term-bright-red: #dc2626;
38
+ --term-bright-green: #059669;
39
+ --term-bright-yellow: #d97706;
40
+ --term-bright-blue: #1d4ed8;
41
+ --term-bright-magenta: #7c3aed;
42
+ --term-bright-cyan: #0891b2;
43
+ --term-bright-white: #ffffff;
44
+ --mono: "SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
45
+ --mermaid-font-size: 12px;
46
+ --tooltip-bg: #ffffff;
47
+ --code-bg: #f4f4f5;
48
+ --code-text: #18181b;
49
+ --code-border: var(--border-soft);
50
+ --code-pad: 8px 10px;
51
+ --card-body-pad: 4px 14px 12px;
52
+ --err-text: #ef4444;
53
+ --red-text: #ef4444;
54
+ --amber-text: #d97706;
55
+ --info-blue: #2563eb;
56
+ --link: #10a37f;
57
+ --link-hover: #0e8c6d;
58
+ --link-soft: #10a37f;
59
+ --md-strong: #000000;
60
+ --skill-blue: #10a37f;
61
+ --plugin-purple: #b58cff;
62
+ --auth-green: #10a37f;
63
+ --scroll-thumb: #d4d4d8;
64
+ --scroll-thumb-hover: #a1a1aa;
65
+ --notice-err-bg: #401d23;
66
+ --notice-warn-bg: #38251f;
67
+ --notice-info-bg: #1b2544;
68
+ --notice-err-border: #ef4444;
69
+ --notice-warn-border: #f59e0b;
70
+ --notice-info-border: #3b82f6;
71
+ --send-blue: #10a37f;
72
+ --send-blue-hover: #0e8c6d;
73
+ --stop-red: #ef4444;
74
+ --stop-red-hover: #dc2626;
75
+ --brand-grad-a: #10a37f;
76
+ --brand-grad-b: #1a7f64;
77
+ --on-amber: #1a1a1a;
78
+ --search-active-fg: #1a1d26;
79
+ --switch-knob: #ffffff;
80
+ --bg-elev3: rgba(255, 255, 255, 0.06);
81
+ --sunken-bg: rgba(0, 0, 0, 0.15);
82
+ --glow-015: rgba(255, 255, 255, 0.015);
83
+ --glow-025: rgba(255, 255, 255, 0.025);
84
+ --glow-03: rgba(255, 255, 255, 0.03);
85
+ --glow-04: rgba(255, 255, 255, 0.04);
86
+ --glow-05: rgba(255, 255, 255, 0.05);
87
+ --glow-12: rgba(255, 255, 255, 0.12);
88
+ --glow-18: rgba(255, 255, 255, 0.18);
89
+ --glow-22: rgba(255, 255, 255, 0.22);
90
+ --glow-38: rgba(255, 255, 255, 0.38);
91
+ --control-fg: #52525b;
92
+ --control-bg: #f4f4f5;
93
+ --control-border: #e4e4e7;
94
+ --bg-image: none;
95
+ --bg-image-dim: 0.78;
96
+ --bg-image-blur: 0px;
97
+ --wallpaper-panel-alpha: 100%;
98
+ --topbar-bg: #ffffff;
99
+ --statusbar-bg: #f7f7f8;
100
+ --panel-bg: #ffffff;
101
+ --card-bg: #ffffff;
102
+ --chip-bg: #f4f4f5;
103
+ --msgs-bg: #ffffff;
104
+ --inputbox-bg: #f4f4f5;
105
+ --menu-bg: var(--bg-elev2);
106
+ }
107
+
108
+ /* ---- syntax highlighting (Codex Light) ---- */
109
+ .hljs {
110
+ color: #18181b;
111
+ background: #f4f4f5;
112
+ }
113
+ .hljs-keyword,
114
+ .hljs-meta .hljs-keyword {
115
+ color: #cf222e;
116
+ font-weight: 600;
117
+ }
118
+ .hljs-title,
119
+ .hljs-title.function_ {
120
+ color: #8250df;
121
+ }
122
+ .hljs-number,
123
+ .hljs-literal {
124
+ color: #0550ae;
125
+ }
126
+ .hljs-string {
127
+ color: #0a3069;
128
+ }
129
+ .hljs-built_in,
130
+ .hljs-type {
131
+ color: #953800;
132
+ }
133
+ .hljs-comment {
134
+ color: #6e7781;
135
+ font-style: italic;
136
+ }
@@ -17,6 +17,8 @@
17
17
  --red: #ff006e;
18
18
  --red-soft: rgba(255, 0, 110, 0.12);
19
19
  --amber: #ffd700;
20
+ --blue: #3b82f6;
21
+ --blue-soft: rgba(59, 130, 246, 0.12);
20
22
  --term-bg: #0a0a0f;
21
23
  --term-fg: #e6e6ff;
22
24
  --term-cursor: #00d4ff;
@@ -67,6 +69,8 @@
67
69
  --notice-info-border: #3b82f6;
68
70
  --send-blue: #00d4ff;
69
71
  --send-blue-hover: #00b8d4;
72
+ --stop-red: #ef4444;
73
+ --stop-red-hover: #dc2626;
70
74
  --brand-grad-a: #00d4ff;
71
75
  --brand-grad-b: #ff006e;
72
76
  --on-amber: #1a1a1a;
package/themes/dazzle.css CHANGED
@@ -17,6 +17,8 @@
17
17
  --red: #f43f5e;
18
18
  --red-soft: rgba(244, 63, 94, 0.12);
19
19
  --amber: #f59e0b;
20
+ --blue: #3b82f6;
21
+ --blue-soft: rgba(59, 130, 246, 0.12);
20
22
  --term-bg: #0b0b14;
21
23
  --term-fg: #e8e8f0;
22
24
  --term-cursor: #818cf8;
@@ -67,6 +69,8 @@
67
69
  --notice-info-border: #3b82f6;
68
70
  --send-blue: #818cf8;
69
71
  --send-blue-hover: #6366f1;
72
+ --stop-red: #ef4444;
73
+ --stop-red-hover: #dc2626;
70
74
  --brand-grad-a: #818cf8;
71
75
  --brand-grad-b: #c084fc;
72
76
  --on-amber: #1a1a1a;