pi-cc-extensions 1.0.3 → 1.0.5

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.
@@ -14,7 +14,7 @@ function clip(value: unknown): string {
14
14
  return oneLine(value, clipLimit());
15
15
  }
16
16
 
17
- /** 载荷(入参 JSON / 脚本代码)至少留出这么多宽度才显示,否则整段省略(避免只剩一个孤零零的 " {…")。 */
17
+ /** 载荷(入参 JSON / 脚本代码 / 路径值)至少留出这么多宽度才显示,否则整段省略(避免只剩一个孤零零的 " {…")。 */
18
18
  const MIN_PAYLOAD_WIDTH = 10;
19
19
 
20
20
  /** 品牌大小写固定写法;humanize 推导不出来的工具名写在这里。 */
@@ -62,7 +62,7 @@ export type ToolCallSummary = {
62
62
  detail: string;
63
63
  /** 路径摘要保留结构,供最终渲染按实际宽度优先保留文件名。 */
64
64
  path?: { prefix: string; value: string };
65
- /** 标题之外的原始载荷(完整入参 JSON、脚本代码…),已压成单行,渲染时用 dim 接在标题后。 */
65
+ /** 标题之外的原始载荷(入参 JSON、脚本代码、命令、路径、查询…),已压成单行,渲染时用 muted 接在标题后。 */
66
66
  payload?: string;
67
67
  };
68
68
 
@@ -149,11 +149,8 @@ function pathSummary(
149
149
  detail = "",
150
150
  ): ToolCallSummary {
151
151
  const path = displayPath(value, cwd);
152
- return {
153
- main: `${prefix} ${truncatePathToWidth(path, clipLimit())}`,
154
- detail,
155
- path: { prefix, value: path },
156
- };
152
+ // main 只留标题:渲染时 prefix 用标题色、路径值用次级色,截断按 path 结构走中间省略。
153
+ return { main: prefix, detail, path: { prefix, value: path } };
157
154
  }
158
155
 
159
156
  /** 入参是 shell 命令的工具。 */
@@ -192,7 +189,7 @@ const GENERIC_SUMMARY_FIELDS = [
192
189
  ] as const;
193
190
 
194
191
  /** 通用字段链取值:字符串直接用;数组取首个可展示项并标注剩余条数。 */
195
- type SummaryValue = { text: string; more: number };
192
+ type SummaryValue = { text: string; more: number; input: boolean };
196
193
 
197
194
  function arrayItemText(item: unknown): string | undefined {
198
195
  if (typeof item === "string" && item) return item;
@@ -205,7 +202,7 @@ function arrayItemText(item: unknown): string | undefined {
205
202
  }
206
203
 
207
204
  function summaryFieldValue(value: unknown): SummaryValue | undefined {
208
- if (typeof value === "string" && value) return { text: value, more: 0 };
205
+ if (typeof value === "string" && value) return { text: value, more: 0, input: true };
209
206
  if (!Array.isArray(value)) return undefined;
210
207
  let first: string | undefined;
211
208
  let count = 0;
@@ -215,7 +212,7 @@ function summaryFieldValue(value: unknown): SummaryValue | undefined {
215
212
  count += 1;
216
213
  first ??= text;
217
214
  }
218
- return first === undefined ? undefined : { text: first, more: count - 1 };
215
+ return first === undefined ? undefined : { text: first, more: count - 1, input: true };
219
216
  }
220
217
 
221
218
  /** 通用字段链取值;无可用字段时返回 undefined,交给调用方继续降级。 */
@@ -225,7 +222,7 @@ function genericSummary(title: string, args: any): ToolCallSummary | undefined {
225
222
  if (!found) continue;
226
223
  // (+N) 追加在截断之后,避免首个元素过长时把条数挤没
227
224
  const more = found.more > 0 ? ` (+${found.more})` : "";
228
- return { main: `${title} ${clip(found.text)}${more}`, detail: "" };
225
+ return { main: title, detail: "", payload: `${clip(found.text)}${more}` };
229
226
  }
230
227
  return undefined;
231
228
  }
@@ -261,45 +258,39 @@ export function toolCallSummary(
261
258
 
262
259
  const value = (fallback: string, ...keys: string[]) => {
263
260
  const found = keys.map((key) => args[key]).find((item) => typeof item === "string" && item);
264
- return `${title} ${clip(found || fallback)}`;
261
+ return { main: title, detail: "", payload: clip(found || fallback) };
265
262
  };
266
263
 
267
264
  if (variant === "default" && AGENT_FAMILY_TOOL_NAMES.has(toolName) && args.agent_id) {
268
- return { main: `${title} ${clip(args.agent_id)}`, detail: "" };
265
+ return { main: title, detail: "", payload: clip(args.agent_id) };
269
266
  }
270
267
  if (variant === "grouping" && (name === "agent" || name === "agents")) {
271
268
  const displayName = args.subagent_type ?? args.agent_type ?? args.agent;
272
269
  if (typeof displayName === "string" && displayName) {
273
- return { main: `${title} ${displayName}`, detail: "" };
270
+ return { main: title, detail: "", payload: displayName };
274
271
  }
275
- return {
276
- main: value(name === "agent" ? "launch agent" : "launch agents", "description", "prompt"),
277
- detail: "",
278
- };
272
+ return value(name === "agent" ? "launch agent" : "launch agents", "description", "prompt");
279
273
  }
280
274
  if (variant === "grouping" && (name === "get_subagent_result" || name === "steer_subagent")) {
281
- return {
282
- main: value(name === "get_subagent_result" ? "agent result" : "steer agent", "agent_id"),
283
- detail: "",
284
- };
275
+ return value(name === "get_subagent_result" ? "agent result" : "steer agent", "agent_id");
285
276
  }
286
277
  if (variant === "default" && name === "agents") {
287
- return { main: value("launch agents", "description", "prompt"), detail: "" };
278
+ return value("launch agents", "description", "prompt");
288
279
  }
289
- if (name === "skill") return { main: value("run skill", "name"), detail: "" };
280
+ if (name === "skill") return value("run skill", "name");
290
281
  if (name === "enterplanmode" || name === "enter_plan_mode") {
291
- return { main: `${title} enable read-only planning`, detail: "" };
282
+ return { main: title, detail: "", payload: "enable read-only planning" };
292
283
  }
293
284
  if (name === "exitplanmode" || name === "exit_plan_mode") {
294
- return { main: `${title} present plan`, detail: "" };
285
+ return { main: title, detail: "", payload: "present plan" };
295
286
  }
296
- if (name === "taskcreate") return { main: value("create task", "subject"), detail: "" };
297
- if (name === "tasklist") return { main: `${title} task list`, detail: "" };
287
+ if (name === "taskcreate") return value("create task", "subject");
288
+ if (name === "tasklist") return { main: title, detail: "", payload: "task list" };
298
289
  if (name === "taskget" || name === "taskupdate") {
299
- return { main: value("task", "taskId", "task_id"), detail: "" };
290
+ return value("task", "taskId", "task_id");
300
291
  }
301
292
  if (name === "taskoutput" || name === "taskstop") {
302
- return { main: value("background task", "task_id", "taskId"), detail: "" };
293
+ return value("background task", "task_id", "taskId");
303
294
  }
304
295
  if (name === "taskexecute") {
305
296
  const ids = Array.isArray(args.task_ids)
@@ -310,7 +301,7 @@ export function toolCallSummary(
310
301
  const summary = ids.length
311
302
  ? `${ids[0]}${ids.length > 1 ? ` (+${ids.length - 1} tasks)` : ""}`
312
303
  : "start tasks";
313
- return { main: `${title} ${summary}`, detail: "" };
304
+ return { main: title, detail: "", payload: summary };
314
305
  }
315
306
  if (toolName === "read") {
316
307
  const details = [
@@ -322,20 +313,21 @@ export function toolCallSummary(
322
313
  return pathSummary(variant === "grouping" ? "Read" : title, args.path, opts.cwd, detail);
323
314
  }
324
315
  return {
325
- main: variant === "grouping" ? "Read ..." : title,
316
+ main: variant === "grouping" ? "Read" : title,
326
317
  detail,
318
+ payload: variant === "grouping" ? "..." : undefined,
327
319
  };
328
320
  }
329
321
  if (variant === "grouping" && SHELL_TOOL_NAMES.has(name)) {
330
322
  // 分组行缺 command 时保留占位,避免与单工具卡一样只剩标题
331
- return { main: value("...", "command"), detail: "" };
323
+ return value("...", "command");
332
324
  }
333
325
 
334
326
  // 检索类:pattern 是正文,path 只是范围;两个变体同格式
335
327
  if (typeof args.pattern === "string" || SEARCH_TOOL_NAMES.has(name)) {
336
328
  const pattern = clip(args.pattern || "...");
337
329
  const scope = typeof args.path === "string" && args.path ? ` in ${clip(args.path)}` : "";
338
- return { main: `${title} ${JSON.stringify(pattern)}${scope}`, detail: "" };
330
+ return { main: title, detail: "", payload: `${JSON.stringify(pattern)}${scope}` };
339
331
  }
340
332
 
341
333
  const generic = genericSummary(title, args);
@@ -368,28 +360,29 @@ function mcpGatewaySummary(title: string, args: any): ToolCallSummary | undefine
368
360
  const action = text(args.action);
369
361
  const scoped = (target: string) => (server ? `${target} @ ${server}` : target);
370
362
 
371
- if (action === "ui-messages") return { main: `${title} ${action}`, detail: "" };
363
+ if (action === "ui-messages") return { main: title, detail: "", payload: action };
372
364
  if (tool) {
373
- const main = `${title} call ${scoped(tool)}`;
374
- const payload = innerArgsPayload(args.args);
375
- return payload ? { main, detail: "", payload } : { main, detail: "" };
365
+ const argsPayload = innerArgsPayload(args.args);
366
+ const payload = argsPayload ? `call ${scoped(tool)} ${argsPayload}` : `call ${scoped(tool)}`;
367
+ return { main: title, detail: "", payload };
376
368
  }
377
- if (connect) return { main: `${title} connect ${connect}`, detail: "" };
378
- if (describe) return { main: `${title} describe ${scoped(describe)}`, detail: "" };
379
- if (instructions) return { main: `${title} instructions ${instructions}`, detail: "" };
369
+ if (connect) return { main: title, detail: "", payload: `connect ${connect}` };
370
+ if (describe) return { main: title, detail: "", payload: `describe ${scoped(describe)}` };
371
+ if (instructions) return { main: title, detail: "", payload: `instructions ${instructions}` };
380
372
  if (search) {
381
373
  const flags = [
382
374
  args.regex === true ? "regex" : "",
383
375
  args.includeSchemas === false ? "schemas hidden" : "",
384
376
  ].filter(Boolean);
385
377
  return {
386
- main: `${title} search ${scoped(search)}`,
378
+ main: title,
387
379
  detail: flags.length ? ` (${flags.join(", ")})` : "",
380
+ payload: `search ${scoped(search)}`,
388
381
  };
389
382
  }
390
- if (server) return { main: `${title} list ${server}`, detail: "" };
391
- if (action) return { main: `${title} ${action}`, detail: "" };
392
- if (Object.keys(args).length === 0) return { main: `${title} status`, detail: "" };
383
+ if (server) return { main: title, detail: "", payload: `list ${server}` };
384
+ if (action) return { main: title, detail: "", payload: action };
385
+ if (Object.keys(args).length === 0) return { main: title, detail: "", payload: "status" };
393
386
  return undefined;
394
387
  }
395
388
 
@@ -411,20 +404,27 @@ function jsonArgs(args: any): string {
411
404
  }
412
405
 
413
406
  /**
414
- * 标题行内容:标题用调用方的 toolTitle 色,原始载荷(入参 JSON / 脚本代码)单独用 dim。
415
- * 标题优先占宽(它是身份),剩下的宽度给载荷;载荷超宽时尾部省略,连
416
- * MIN_PAYLOAD_WIDTH 都放不下时整段省略。
407
+ * 标题行内容:main 是身份(工具名),用 toolTitle 色;路径值与载荷(入参 JSON、
408
+ * 脚本代码、命令、查询…)是输入,单独用 muted。标题优先占宽,剩下的宽度给载荷;
409
+ * 载荷超宽时尾部省略,连 MIN_PAYLOAD_WIDTH 都放不下时整段省略。
417
410
  */
418
411
  export function renderToolSummary(
419
412
  summary: ToolCallSummary,
420
413
  width: number,
421
414
  fg: (color: ThemeColor, text: string) => string,
422
415
  ): string {
416
+ // 路径摘要:前缀用标题色,值用次级色并按可用宽度中间截断(文件名优先保留)。
417
+ if (summary.path) {
418
+ const prefix = headToWidth(summary.path.prefix, width, "…");
419
+ const pathWidth = width - visibleWidth(prefix) - 1;
420
+ if (pathWidth < MIN_PAYLOAD_WIDTH) return fg("toolTitle", prefix);
421
+ return `${fg("toolTitle", prefix)} ${fg("muted", truncatePathToWidth(summary.path.value, Math.min(pathWidth, clipLimit())))}`;
422
+ }
423
423
  const title = fitToolCallSummary(summary, width);
424
424
  if (!summary.payload) return fg("toolTitle", title);
425
425
  const room = width - visibleWidth(title);
426
426
  return room >= MIN_PAYLOAD_WIDTH
427
- ? `${fg("toolTitle", title)}${fg("dim", headTruncateToWidth(` ${summary.payload}`, room))}`
427
+ ? `${fg("toolTitle", title)}${fg("muted", headTruncateToWidth(` ${summary.payload}`, room))}`
428
428
  : fg("toolTitle", title);
429
429
  }
430
430
 
@@ -33,6 +33,30 @@ export function insetComponent(component: any): any {
33
33
  return wrapped;
34
34
  }
35
35
 
36
+ /**
37
+ * 展开卡内嵌组件:`↳` 行右移 2 格(Box pad 1 + 2 = 标题文字列),其余行贴左。
38
+ * 与折叠态 insetComponent 的 ` ↳` 同一视觉列。
39
+ */
40
+ export function expandedBodyComponent(component: any): any {
41
+ const wrapped: Record<string, unknown> = {
42
+ render: (width: number) =>
43
+ component
44
+ .render(width)
45
+ .map((line: string) =>
46
+ truncateToWidth(
47
+ line.replace(/^((?:\x1b\[[0-?]*[ -/]*[@-~])*)↳/, "$1 ↳"),
48
+ Math.max(0, width),
49
+ "",
50
+ ),
51
+ ),
52
+ invalidate: () => component.invalidate?.(),
53
+ };
54
+ if (typeof component.isCollapsedHintLine === "function") {
55
+ wrapped.isCollapsedHintLine = (line: string) => component.isCollapsedHintLine(line);
56
+ }
57
+ return wrapped;
58
+ }
59
+
36
60
  function rawTextFromResult(result: any): string {
37
61
  return Array.isArray(result?.content)
38
62
  ? result.content
@@ -1,3 +1,4 @@
1
+ import type { ThemeBg } from "@earendil-works/pi-coding-agent";
1
2
  import { getToolMouseTui } from "../mouse/scroll.ts";
2
3
  import { TOOL_LOADING_INTERVAL_MS, toolLoadingIcon } from "../../utils/tool-loading-icon.ts";
3
4
 
@@ -93,6 +94,54 @@ export function pendingIcon(_name: string): string {
93
94
 
94
95
  type ToolVisualState = "pending" | "success" | "error";
95
96
 
97
+ /** 展开卡底色槽位:与工具状态一一对应,不再读配置。 */
98
+ export const TOOL_CARD_BG_SLOT: Record<ToolVisualState, ThemeBg> = {
99
+ pending: "toolPendingBg",
100
+ success: "toolSuccessBg",
101
+ error: "toolErrorBg",
102
+ };
103
+
104
+ /** 单张工具卡的状态。有失败取失败,没有结果或仍在输出取进行中,其余取成功。 */
105
+ export function toolCardStatus(tool: any): ToolVisualState {
106
+ if (tool?.result?.isError === true || tool?.isError === true) return "error";
107
+ if (tool?.isPartial === true || (tool?.executionStarted && !tool?.result) || !tool?.result) {
108
+ return "pending";
109
+ }
110
+ return "success";
111
+ }
112
+
113
+ /**
114
+ * 一张卡里多个工具的汇总状态。
115
+ * 有一个失败取失败;没有失败但还有进行中取进行中;全部成功取成功。
116
+ */
117
+ export function aggregateToolCardStatus(tools: readonly any[]): ToolVisualState {
118
+ let pending = false;
119
+ for (const tool of tools) {
120
+ const value = toolCardStatus(tool);
121
+ if (value === "error") return "error";
122
+ if (value === "pending") pending = true;
123
+ }
124
+ return pending ? "pending" : "success";
125
+ }
126
+
127
+ /**
128
+ * 单张工具卡的底色。
129
+ * edit/write 的新增行底色由 toolSuccessBg 混出,成功卡不能再用同一块绿,否则两层叠在一起。
130
+ * 成功的 edit/write 改用中性的 toolPendingBg;失败卡仍用 toolErrorBg。
131
+ */
132
+ export function toolCardBgSlot(tool: any): ThemeBg {
133
+ const status = toolCardStatus(tool);
134
+ const name = String(tool?.toolName ?? "");
135
+ if ((name === "edit" || name === "write") && status !== "error") {
136
+ return TOOL_CARD_BG_SLOT.pending;
137
+ }
138
+ return TOOL_CARD_BG_SLOT[status];
139
+ }
140
+
141
+ export function aggregateToolCardBgSlot(tools: readonly any[]): string {
142
+ return TOOL_CARD_BG_SLOT[aggregateToolCardStatus(tools)];
143
+ }
144
+
96
145
  export function settledIcon(name: string, state: ToolVisualState | undefined): string {
97
146
  if (state === "success") return "✓";
98
147
  if (state === "error") return "✗";
@@ -124,11 +173,11 @@ export function resolveToolVisualState(context: any): ToolVisualState | undefine
124
173
  return settledState;
125
174
  }
126
175
 
127
- export function toolIconColor(context: any): "accent" | "error" | "success" | "muted" {
176
+ export function toolIconColor(context: any): "dim" | "error" | "success" | "muted" {
128
177
  const visualState = getToolVisualState(context);
129
178
  if (context?.isError || visualState === "error") return "error";
130
179
  if (visualState === "success") return "success";
131
- if (context?.isPartial || context?.executionStarted || visualState === "pending") return "accent";
180
+ if (context?.isPartial || context?.executionStarted || visualState === "pending") return "dim";
132
181
  return "muted";
133
182
  }
134
183
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "license": "MIT",
5
5
  "description": "Claude Code-style TUI output with some personal touches and handy utilities.",
6
6
  "type": "module",
@@ -1,91 +1,92 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://pi.dev/schemas/theme.schema.json",
3
3
  "name": "cc-dark",
4
+ "appearance": "dark",
4
5
  "vars": {
5
- "bg": "#131217",
6
- "panel": "#1b1922",
7
- "surface": "#211e2b",
8
- "surfaceRaised": "#292533",
9
- "border": "#36313f",
10
- "borderMuted": "#292631",
11
- "accent": "#5e9cff",
12
- "accentBright": "#8ab4ff",
13
- "purple": "#c084fc",
14
- "pink": "#f472b6",
15
- "cyan": "#67e8f9",
16
- "blue": "#60a5fa",
17
- "green": "#4ade80",
18
- "red": "#fb7185",
19
- "yellow": "#facc15",
20
- "orange": "#fb923c",
21
- "text": "#e4e4e7",
22
- "muted": "#a1a1aa",
23
- "dim": "#71717a",
24
- "selectedBg": "#252035",
25
- "userMessageBg": "#1e1e2e",
26
- "toolPendingBg": "#1b1924",
27
- "toolSuccessBg": "#1e1e2e",
28
- "toolErrorBg": "#2a1b22",
29
- "customMessageBg": "#211c30"
6
+ "fg": "#d6dde3",
7
+ "fgMuted": "#929eab",
8
+ "fgSubtle": "#768494",
9
+ "canvas": "#0d1117",
10
+ "canvasSubtle": "#1c2033",
11
+ "canvasInset": "#161a2b",
12
+ "border": "#1c2d44",
13
+ "borderMuted": "#16233a",
14
+ "blue": "#4f9eff",
15
+ "blueBright": "#79c0ff",
16
+ "green": "#37b34a",
17
+ "red": "#ff6e62",
18
+ "redSoft": "#ff7b72",
19
+ "yellow": "#cb9214",
20
+ "orange": "#f0883e",
21
+ "orangeSoft": "#ffa657",
22
+ "purple": "#be8fff",
23
+ "pink": "#f778ba",
24
+ "cyan": "#39c5cf",
25
+ "selection": "#1a4480",
26
+ "diffAddBg": "#0f2a24",
27
+ "diffDelBg": "#261418"
30
28
  },
31
29
  "colors": {
32
- "accent": "accent",
30
+ "accent": "blue",
33
31
  "border": "border",
34
- "borderAccent": "accent",
32
+ "borderAccent": "blue",
35
33
  "borderMuted": "borderMuted",
36
34
  "success": "green",
37
35
  "error": "red",
38
36
  "warning": "yellow",
39
- "muted": "muted",
40
- "dim": "dim",
41
- "text": "text",
42
- "thinkingText": "muted",
43
- "selectedBg": "selectedBg",
44
- "scrollbarThumb": "selectedBg",
45
- "userMessageBg": "userMessageBg",
46
- "userMessageText": "text",
47
- "customMessageBg": "customMessageBg",
48
- "customMessageText": "text",
49
- "customMessageLabel": "purple",
50
- "toolPendingBg": "toolPendingBg",
51
- "toolSuccessBg": "toolSuccessBg",
52
- "toolErrorBg": "toolErrorBg",
53
- "toolTitle": "accentBright",
54
- "toolOutput": "muted",
55
- "mdHeading": "accentBright",
56
- "mdLink": "cyan",
57
- "mdLinkUrl": "muted",
58
- "mdCode": "accentBright",
59
- "mdCodeBlock": "text",
37
+ "muted": "fgMuted",
38
+ "dim": "#71717a",
39
+ "text": "fg",
40
+ "thinkingText": "fgMuted",
41
+ "selectedBg": "selection",
42
+ "scrollbarTrack": "borderMuted",
43
+ "scrollbarThumb": "#3a5274",
44
+ "searchMatchBg": "#1e1800",
45
+ "searchMatchText": "fg",
46
+ "userMessageBg": "canvasSubtle",
47
+ "userMessageText": "fg",
48
+ "customMessageBg": "borderMuted",
49
+ "customMessageText": "fgMuted",
50
+ "customMessageLabel": "blue",
51
+ "toolPendingBg": "canvasSubtle",
52
+ "toolSuccessBg": "diffAddBg",
53
+ "toolErrorBg": "diffDelBg",
54
+ "toolTitle": "fg",
55
+ "toolOutput": "fgMuted",
56
+ "mdHeading": "blueBright",
57
+ "mdLink": "blue",
58
+ "mdLinkUrl": "fgMuted",
59
+ "mdCode": "#a5d6ff",
60
+ "mdCodeBlock": "fg",
60
61
  "mdCodeBlockBorder": "border",
61
- "mdQuote": "muted",
62
- "mdQuoteBorder": "accent",
63
- "mdHr": "borderMuted",
64
- "mdListBullet": "accent",
62
+ "mdQuote": "fgMuted",
63
+ "mdQuoteBorder": "#2a4060",
64
+ "mdHr": "border",
65
+ "mdListBullet": "blueBright",
65
66
  "toolDiffAdded": "green",
66
67
  "toolDiffRemoved": "red",
67
- "toolDiffContext": "muted",
68
- "syntaxComment": "#6b7280",
69
- "syntaxKeyword": "pink",
70
- "syntaxFunction": "accentBright",
71
- "syntaxVariable": "blue",
72
- "syntaxString": "green",
73
- "syntaxNumber": "orange",
74
- "syntaxType": "cyan",
75
- "syntaxOperator": "text",
76
- "syntaxPunctuation": "muted",
77
- "thinkingOff": "muted",
78
- "thinkingMinimal": "dim",
68
+ "toolDiffContext": "fgMuted",
69
+ "syntaxComment": "fgMuted",
70
+ "syntaxKeyword": "redSoft",
71
+ "syntaxFunction": "purple",
72
+ "syntaxVariable": "orangeSoft",
73
+ "syntaxString": "#a5d6ff",
74
+ "syntaxNumber": "blueBright",
75
+ "syntaxType": "orange",
76
+ "syntaxOperator": "redSoft",
77
+ "syntaxPunctuation": "fg",
78
+ "thinkingOff": "fgMuted",
79
+ "thinkingMinimal": "fgSubtle",
79
80
  "thinkingLow": "blue",
80
- "thinkingMedium": "accent",
81
- "thinkingHigh": "accentBright",
82
- "thinkingXhigh": "#4db9cd",
81
+ "thinkingMedium": "blue",
82
+ "thinkingHigh": "blueBright",
83
+ "thinkingXhigh": "cyan",
83
84
  "thinkingMax": "cyan",
84
85
  "bashMode": "green"
85
86
  },
86
87
  "export": {
87
- "pageBg": "bg",
88
- "cardBg": "panel",
89
- "infoBg": "surface"
88
+ "pageBg": "#0a1424",
89
+ "cardBg": "canvasSubtle",
90
+ "infoBg": "#122544"
90
91
  }
91
92
  }