pi-cc-extensions 0.8.65 → 0.8.67

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/README.en.md CHANGED
@@ -40,8 +40,8 @@ Run `/reload` after installation.
40
40
  | Claude Code Output | Tool summaries, expand/collapse, rich edit/write diffs, and`on` / `compact` / `off` modes | `/ccstyle` |
41
41
  | Markdown enhancements | Mermaid art, admonitions, URL linking, and more | Automatic |
42
42
  | Fullscreen mode | Tool card/group click to expand, double-click to collapse, previews, hover highlight, and a back-to-bottom button | `TUIMODE=fullscreen` or `--tui-mode fullscreen` |
43
- | Settings panel | `Style / Diff / Thinking / Feature` tabs: startup header toggle and wheel step | `/ccstyle` |
44
- | Context inspection | Usage breakdown and previews for the system prompt, tools, skills, and messages | `/context` |
43
+ | Settings panel | `Style / Diff / Thinking / UI / Feature` tabs | `/ccstyle` |
44
+ | Context inspection | Usage breakdown and previews for the system prompt, memory, skills, tools definition, and messages | `/context` |
45
45
  | Session/Subagent references | Search and inject effective context from previous Sessions or existing SubAgents | `@` |
46
46
  | Theme | Bundled CC Dark and CC Light themes | `/theme` |
47
47
 
@@ -62,11 +62,13 @@ Run `/reload` after installation.
62
62
  "writeDiffCollapsedLines": 0, // write collapse lines; 0 = creation summary only
63
63
  "diffWordWrap": true, // wrap long diff lines
64
64
  "expandedPreviewMaxLines": 40, // max lines for expanded bodies
65
+ "toolInputNameLength": 100, // tool summary path/command clip length
65
66
 
66
67
  // thinking
67
68
  "useSummaryTitlesAsThinkingTitle": true, // use latest summary as thinking title
68
69
  "previewLines": 3, // preview lines; 0 hides
69
70
  "animationIntervalMs": 90, // title animation interval (ms)
71
+ "dimThinkingText": false, // dim thinking body text
70
72
 
71
73
  // ui
72
74
  "showStartupHeader": true, // startup header (logo + tips) toggle
package/README.md CHANGED
@@ -40,8 +40,8 @@ pi install git:github.com/minuque/pi-cc-extensions
40
40
  | Claude Code UI | 工具摘要、折叠展开、rich edit/write diff,以及`on` / `compact` / `off` 三种模式 | `/ccstyle` |
41
41
  | Markdown 增强 | Mermaid 图、提示框、URL 链接化等 | 自动生效 |
42
42
  | Fullscreen mode | 工具卡/group 单击展开、双击收起、预览、hover 高亮、回到底部按钮 | `TUIMODE=fullscreen` 或 `--tui-mode fullscreen` |
43
- | 配置面板 | `Style / Diff / Thinking / Feature` 四页签,含启动头开关与滚轮步进 | `/ccstyle` |
44
- | 上下文检查 | 查看上下文占用,并预览 System prompt、Tools、Skills 和消息内容 | `/context` |
43
+ | 配置面板 | `Style / Diff / Thinking / UI / Feature` 五页签 | `/ccstyle` |
44
+ | 上下文检查 | 查看上下文占用,并预览 System prompt、Memory、Skills、Tools definition 和消息内容 | `/context` |
45
45
  | Session/Subagent 引用 | 搜索并注入历史 Session 或现有 SubAgent 的有效上下文 | `@` |
46
46
  | 主题 | 随包提供内置 CC Dark、CC Light 主题 | `/theme` |
47
47
 
@@ -62,11 +62,13 @@ pi install git:github.com/minuque/pi-cc-extensions
62
62
  "writeDiffCollapsedLines": 0, // write 折叠行数,0 仅显示创建摘要
63
63
  "diffWordWrap": true, // 长 diff 行换行
64
64
  "expandedPreviewMaxLines": 40, // 展开正文最大行数
65
+ "toolInputNameLength": 100, // 工具摘要 path/command 折叠字符数
65
66
 
66
67
  // thinking
67
68
  "useSummaryTitlesAsThinkingTitle": true, // 用最新摘要作思考标题
68
69
  "previewLines": 3, // 预览行数,0 隐藏
69
70
  "animationIntervalMs": 90, // 标题动画间隔(毫秒)
71
+ "dimThinkingText": false, // thinking 正文用 dim 色
70
72
 
71
73
  // ui
72
74
  "showStartupHeader": true, // 启动头(logo + tips)开关
Binary file
@@ -52,9 +52,11 @@ export type Config = {
52
52
  writeDiffCollapsedLines: number;
53
53
  diffWordWrap: boolean;
54
54
  expandedPreviewMaxLines: number;
55
+ toolInputNameLength: number;
55
56
  useSummaryTitlesAsThinkingTitle: boolean;
56
57
  previewLines: number;
57
58
  animationIntervalMs: number;
59
+ dimThinkingText: boolean;
58
60
  showStartupHeader: boolean;
59
61
  scrollStepLines: number;
60
62
  enableSessionReference: boolean;
@@ -76,6 +78,8 @@ export const DIFF_COLLAPSED_LINES_VALUES = ["12", "24", "36", "48", "80", "120"]
76
78
  export const WRITE_DIFF_COLLAPSED_LINES_VALUES = ["0", "4", "8", "12", "24", "36"];
77
79
  /** Presets for expanded body height — keep low options first so cycling stays TUI-friendly. */
78
80
  export const EXPANDED_PREVIEW_MAX_LINES_VALUES = ["40", "60", "80", "120", "200", "500", "2000"];
81
+ /** 工具摘要里 path/command 等输入的折叠字符数。 */
82
+ export const TOOL_INPUT_NAME_LENGTH_VALUES = ["40", "60", "80", "100", "120", "160"];
79
83
  export const THINKING_PREVIEW_LINES_VALUES = ["0", "1", "3", "5", "10"];
80
84
  export const THINKING_ANIMATION_INTERVAL_VALUES = ["40", "60", "90", "120", "180"];
81
85
  /** fullscreen 滚轮步进行数预设。 */
@@ -103,9 +107,11 @@ export const DEFAULT_CONFIG: Config = {
103
107
  writeDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines,
104
108
  diffWordWrap: DEFAULT_TOOL_DISPLAY_CONFIG.diffWordWrap,
105
109
  expandedPreviewMaxLines: DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
110
+ toolInputNameLength: 100,
106
111
  useSummaryTitlesAsThinkingTitle: true,
107
112
  previewLines: 3,
108
113
  animationIntervalMs: 90,
114
+ dimThinkingText: false,
109
115
  showStartupHeader: true,
110
116
  scrollStepLines: 3,
111
117
  enableSessionReference: true,
@@ -188,6 +194,12 @@ export function normalizeConfig(input: unknown): Config {
188
194
  10,
189
195
  50_000,
190
196
  ),
197
+ toolInputNameLength: pickPositiveInt(
198
+ source.toolInputNameLength,
199
+ DEFAULT_CONFIG.toolInputNameLength,
200
+ 8,
201
+ 500,
202
+ ),
191
203
  useSummaryTitlesAsThinkingTitle: source.useSummaryTitlesAsThinkingTitle !== false,
192
204
  previewLines: pickPositiveInt(
193
205
  source.previewLines,
@@ -199,6 +211,7 @@ export function normalizeConfig(input: unknown): Config {
199
211
  source.animationIntervalMs,
200
212
  DEFAULT_CONFIG.animationIntervalMs,
201
213
  ),
214
+ dimThinkingText: source.dimThinkingText === true,
202
215
  showStartupHeader: source.showStartupHeader !== false,
203
216
  scrollStepLines: pickPositiveInt(source.scrollStepLines, DEFAULT_CONFIG.scrollStepLines, 1, 50),
204
217
  enableSessionReference: source.enableSessionReference !== false,
@@ -245,9 +258,11 @@ export function formatConfigStatus(source: Config = config): string {
245
258
  `writeCollapsed=${source.writeDiffCollapsedLines}`,
246
259
  `diffWordWrap=${source.diffWordWrap ? "on" : "off"}`,
247
260
  `expandedMax=${source.expandedPreviewMaxLines}`,
261
+ `toolInputName=${source.toolInputNameLength}`,
248
262
  `thinkingTitle=${source.useSummaryTitlesAsThinkingTitle ? "summary" : "default"}`,
249
263
  `thinkingPreview=${source.previewLines}`,
250
264
  `thinkingAnimation=${source.animationIntervalMs}ms`,
265
+ `thinkingDim=${source.dimThinkingText ? "on" : "off"}`,
251
266
  `startupHeader=${source.showStartupHeader ? "on" : "off"}`,
252
267
  `scrollStep=${source.scrollStepLines}`,
253
268
  `sessionRef=${source.enableSessionReference ? "on" : "off"}`,
@@ -25,6 +25,7 @@ import {
25
25
  SCROLL_STEP_LINES_VALUES,
26
26
  THINKING_ANIMATION_INTERVAL_VALUES,
27
27
  THINKING_PREVIEW_LINES_VALUES,
28
+ TOOL_INPUT_NAME_LENGTH_VALUES,
28
29
  WRITE_DIFF_COLLAPSED_LINES_VALUES,
29
30
  updateConfig,
30
31
  type CompactStyleMode,
@@ -182,7 +183,7 @@ function buildNumberInputSubmenu(
182
183
 
183
184
  /** Section tabs for /ccstyle — matches Zentui-style "A / B / C" headers. */
184
185
  type CcstyleSection = {
185
- id: "style" | "editor" | "diff" | "thinking" | "feature";
186
+ id: "style" | "diff" | "thinking" | "ui" | "feature";
186
187
  label: string;
187
188
  items: any[];
188
189
  };
@@ -263,6 +264,16 @@ export async function showCcstylePanel(
263
264
  );
264
265
  },
265
266
  };
267
+ const toolInputNameSetting = {
268
+ id: "toolInputNameLength",
269
+ label: "Input clip",
270
+ description:
271
+ "Max characters for path/command/name in single and grouped tool summaries. Enter to type a custom value.",
272
+ currentValue: String(config.toolInputNameLength),
273
+ values: [...TOOL_INPUT_NAME_LENGTH_VALUES],
274
+ submenu: (_current: string, closeSubmenu: (selected?: string) => void) =>
275
+ buildNumberInputSubmenu(theme, toolInputNameSetting, closeSubmenu),
276
+ };
266
277
  const diffViewSetting = {
267
278
  id: "diffViewMode",
268
279
  label: "Diff layout",
@@ -351,6 +362,15 @@ export async function showCcstylePanel(
351
362
  submenu: (_current: string, closeSubmenu: (selected?: string) => void) =>
352
363
  buildNumberInputSubmenu(theme, thinkingAnimationSetting, closeSubmenu),
353
364
  };
365
+ const thinkingDimSetting = {
366
+ id: "dimThinkingText",
367
+ label: "Dim thinking text",
368
+ description: config.dimThinkingText
369
+ ? "Thinking text uses the theme's dim color."
370
+ : "Keep the default thinking text color.",
371
+ currentValue: config.dimThinkingText ? "on" : "off",
372
+ values: ["on", "off"],
373
+ };
354
374
  const startupHeaderSetting = {
355
375
  id: "showStartupHeader",
356
376
  label: "Startup header",
@@ -432,6 +452,12 @@ export async function showCcstylePanel(
432
452
  return;
433
453
  }
434
454
  switch (id) {
455
+ case "toolInputNameLength":
456
+ updateConfig({
457
+ toolInputNameLength: pickPositiveInt(value, DEFAULT_CONFIG.toolInputNameLength, 8, 500),
458
+ });
459
+ toolInputNameSetting.currentValue = String(config.toolInputNameLength);
460
+ break;
435
461
  case "mode": {
436
462
  // 选项值带 Experimental 标记,选择后还原为真实 mode 值。
437
463
  const mode: CompactStyleMode =
@@ -510,6 +536,12 @@ export async function showCcstylePanel(
510
536
  });
511
537
  thinkingAnimationSetting.currentValue = String(config.animationIntervalMs);
512
538
  break;
539
+ case "dimThinkingText":
540
+ updateConfig({ dimThinkingText: value === "on" });
541
+ thinkingDimSetting.description = config.dimThinkingText
542
+ ? "Thinking text uses the theme's dim color."
543
+ : "Keep the default thinking text color.";
544
+ break;
513
545
  case "showStartupHeader":
514
546
  updateConfig({ showStartupHeader: value === "on" });
515
547
  startupHeaderSetting.description = config.showStartupHeader
@@ -549,19 +581,28 @@ export async function showCcstylePanel(
549
581
  writeDiffCollapsedSetting,
550
582
  diffWordWrapSetting,
551
583
  expandedMaxSetting,
584
+ toolInputNameSetting,
552
585
  ],
553
586
  },
554
587
  {
555
588
  id: "thinking",
556
589
  label: "Thinking",
557
- items: [thinkingTitleSetting, thinkingPreviewSetting, thinkingAnimationSetting],
590
+ items: [
591
+ thinkingTitleSetting,
592
+ thinkingPreviewSetting,
593
+ thinkingAnimationSetting,
594
+ thinkingDimSetting,
595
+ ],
596
+ },
597
+ {
598
+ id: "ui",
599
+ label: "UI",
600
+ items: [startupHeaderSetting, scrollStepSetting],
558
601
  },
559
602
  {
560
603
  id: "feature",
561
604
  label: "Feature",
562
605
  items: [
563
- startupHeaderSetting,
564
- scrollStepSetting,
565
606
  sessionReferenceToggle.setting,
566
607
  subagentAutocompleteToggle.setting,
567
608
  contextCommandToggle.setting,
@@ -4,6 +4,7 @@ import {
4
4
  type ExtensionCommandContext,
5
5
  type ToolInfo,
6
6
  estimateTokens,
7
+ formatSkillsForPrompt,
7
8
  getMarkdownTheme,
8
9
  } from "@earendil-works/pi-coding-agent";
9
10
  import { Key, Markdown, matchesKey, visibleWidth } from "@earendil-works/pi-tui";
@@ -16,7 +17,13 @@ export type ContextPart = {
16
17
  color: "accent" | "success" | "warning" | "customMessageLabel" | "muted" | "dim" | "error";
17
18
  };
18
19
 
19
- type PreviewKey = "systemPrompt" | "memoryFiles" | "tools" | "toolResults" | "contextFiles";
20
+ type PreviewKey =
21
+ | "systemPrompt"
22
+ | "memoryFiles"
23
+ | "skills"
24
+ | "tools"
25
+ | "toolResults"
26
+ | "contextFiles";
20
27
 
21
28
  type ContextPreview = {
22
29
  key: PreviewKey;
@@ -265,6 +272,12 @@ const tokenEstimate = (value: unknown): number => {
265
272
  return Math.max(0, Math.ceil(text.length / 4));
266
273
  };
267
274
 
275
+ /** 只统计确实嵌进 system prompt 的片段,避免源文件预览把占用加两遍。 */
276
+ function embeddedTokens(prompt: string, chunk: string): number {
277
+ if (!chunk || !prompt.includes(chunk)) return 0;
278
+ return tokenEstimate(chunk);
279
+ }
280
+
268
281
  export function capParts(parts: ContextPart[], target: number, fixedPrefix = 0): ContextPart[] {
269
282
  const fixed = parts.slice(0, fixedPrefix);
270
283
  const variable = parts.slice(fixedPrefix);
@@ -346,10 +359,13 @@ export function collectContextBreakdown(
346
359
  const memoryPreview: string[] = [];
347
360
  let memoryTokens = 0;
348
361
  for (const file of options.contextFiles ?? []) {
349
- memoryTokens += tokenEstimate(file.content);
362
+ memoryTokens += embeddedTokens(systemPrompt, file.content);
350
363
  memoryPreview.push(`## ${file.path}\n\n${previewValue(file.content)}`);
351
364
  }
352
365
 
366
+ const skillsText = formatSkillsForPrompt(options.skills ?? []).trim();
367
+ const skillsTokens = embeddedTokens(systemPrompt, skillsText);
368
+
353
369
  for (const tool of allTools) {
354
370
  if (!selectedTools.has(tool.name)) continue;
355
371
  const definition = {
@@ -407,17 +423,20 @@ export function collectContextBreakdown(
407
423
  }
408
424
  }
409
425
 
426
+ const systemTokens = Math.max(0, tokenEstimate(systemPrompt) - memoryTokens - skillsTokens);
410
427
  return {
411
428
  parts: [
412
- { label: "System prompt", tokens: tokenEstimate(systemPrompt), color: "accent" },
429
+ { label: "System prompt", tokens: systemTokens, color: "accent" },
413
430
  { label: "Memory", tokens: memoryTokens, color: "error" },
414
- { label: "Tools", tokens: toolDefinitionTokens, color: "success" },
431
+ { label: "Skills", tokens: skillsTokens, color: "warning" },
432
+ { label: "Tools definition", tokens: toolDefinitionTokens, color: "success" },
415
433
  { label: "Tool results", tokens: toolResultTokens, color: "customMessageLabel" },
416
434
  { label: "Context", tokens: contextTokens, color: "warning" },
417
435
  ] satisfies ContextPart[],
418
436
  previews: {
419
437
  systemPrompt: systemPrompt || "No system prompt.",
420
438
  memoryFiles: memoryPreview.join("\n\n") || "No memory files in context.",
439
+ skills: skillsText || "No skills in context.",
421
440
  tools: toolDefinitionPreview.join("\n\n") || "No active tool definitions.",
422
441
  toolResults: toolResultPreview.join("\n\n") || "No tool results in the current context.",
423
442
  contextFiles: contextPreview.join("\n\n") || "No conversation context.",
@@ -434,10 +453,10 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
434
453
  const tools = pi.getAllTools();
435
454
  const breakdown = collectContextBreakdown(ctx, tools);
436
455
  const estimated = breakdown.parts.reduce((sum, part) => sum + part.tokens, 0);
437
- // System prompt、Memory、Tools 为固定项,capParts 时保持原值不压缩。
438
- const fixedTokens = breakdown.parts.slice(0, 3).reduce((sum, part) => sum + part.tokens, 0);
456
+ // System / Memory / Skills / Tools definition 为固定项,capParts 时保持原值不压缩。
457
+ const fixedTokens = breakdown.parts.slice(0, 4).reduce((sum, part) => sum + part.tokens, 0);
439
458
  const used = Math.max(resolveUsedTokens(usage, estimated, contextWindow), fixedTokens);
440
- const parts = capParts(breakdown.parts, used, 3);
459
+ const parts = capParts(breakdown.parts, used, 4);
441
460
  const attributed = parts.reduce((sum, part) => sum + part.tokens, 0);
442
461
  const other = Math.max(0, used - attributed);
443
462
  const free = Math.max(0, contextWindow - used);
@@ -466,10 +485,16 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
466
485
  title: "Memory Files",
467
486
  content: breakdown.previews.memoryFiles,
468
487
  },
488
+ {
489
+ key: "skills",
490
+ label: "Skills",
491
+ title: "Skills",
492
+ content: breakdown.previews.skills,
493
+ },
469
494
  {
470
495
  key: "tools",
471
- label: "Tools",
472
- title: "Tools",
496
+ label: "Tools definition",
497
+ title: "Tools definition",
473
498
  content: breakdown.previews.tools,
474
499
  },
475
500
  {
@@ -72,7 +72,8 @@ export function styleCompactThinkingText(
72
72
  bold = false,
73
73
  ): string {
74
74
  if (!theme) return text;
75
- const colored = typeof theme.fg === "function" ? theme.fg("thinkingText", text) : text;
75
+ const color = config.dimThinkingText ? "dim" : "thinkingText";
76
+ const colored = typeof theme.fg === "function" ? theme.fg(color, text) : text;
76
77
  const weighted = bold && typeof theme.bold === "function" ? theme.bold(colored) : colored;
77
78
  return typeof theme.italic === "function" ? theme.italic(weighted) : weighted;
78
79
  }
@@ -1177,7 +1178,8 @@ export function installCompactMode(deps: CompactModeInstallDeps): CompactModeHoo
1177
1178
  }
1178
1179
  const name = String(this.toolName ?? "");
1179
1180
  if (EDIT_WRITE_TOOLS.has(name)) {
1180
- if (!this.result || this.isPartial === true) scheduleAnimation(this);
1181
+ if (this.executionStarted && (!this.result || this.isPartial === true))
1182
+ scheduleAnimation(this);
1181
1183
  return compactEditWriteLines(this, width, deps.writeMetadata);
1182
1184
  }
1183
1185
  // Agent/Task 等同普通工具:折叠不外置(live 面板走独立 widget)。
@@ -233,7 +233,7 @@ function createCcstyleTool(
233
233
  const isPending =
234
234
  visualState === "pending" ||
235
235
  (!visualState && (context?.isPartial || context?.executionStarted));
236
- if (isPending) scheduleAnimation(context);
236
+ if (isPending && context?.executionStarted) scheduleAnimation(context);
237
237
  const rawIcon = isPending ? pendingIcon(toolName) : settledIcon(toolName, visualState);
238
238
  const icon =
239
239
  visualState === "success"
@@ -85,7 +85,12 @@ function scheduleGroupAnimation(patch: Patch): void {
85
85
  patch.animationTimer = null;
86
86
  if (!patch.active) return;
87
87
  for (const group of patch.groups) {
88
- if (group.children.some((tool) => status(tool) === "pending")) group.invalidate();
88
+ if (
89
+ (group.children as any[]).some(
90
+ (tool) => tool?.executionStarted && status(tool) === "pending",
91
+ )
92
+ )
93
+ group.invalidate();
89
94
  }
90
95
  }, TOOL_LOADING_INTERVAL_MS);
91
96
  patch.animationTimer.unref?.();
@@ -300,7 +305,10 @@ export class ToolGroupComponent extends Container {
300
305
  const label =
301
306
  names.size === 1 ? humanizeToolLabel(toolName(this.children[0])) : "Multiple Tools";
302
307
  const overall: ToolStatus = counts.error ? "error" : counts.pending ? "pending" : "success";
303
- if (overall === "pending") scheduleGroupAnimation(this.patch);
308
+ if (
309
+ (this.children as any[]).some((tool) => tool?.executionStarted && status(tool) === "pending")
310
+ )
311
+ scheduleGroupAnimation(this.patch);
304
312
  const overallColor = overall === "pending" ? "accent" : overall;
305
313
  const nameList = names.size > 1 ? ` ${fg("dim", `• ${toolNameList(this.children)}`)}` : "";
306
314
  // 圆点保持 dim;hover 只高亮可点击文字。
@@ -1,5 +1,10 @@
1
+ import { config } from "../../config/config.ts";
1
2
  import { oneLine } from "../../utils/format.ts";
2
3
 
4
+ function clip(value: unknown): string {
5
+ return oneLine(value, config.toolInputNameLength);
6
+ }
7
+
3
8
  /**
4
9
  * 工具名/标签人性化:与 default-mode 的 humanizeToolLabel、grouping 的 humanizeToolName
5
10
  * 逐字相同,收敛为一个共享实现。
@@ -45,12 +50,11 @@ export function toolCallSummary(
45
50
  const name = toolName.toLowerCase();
46
51
  const value = (fallback: string, ...keys: string[]) => {
47
52
  const found = keys.map((key) => args[key]).find((item) => typeof item === "string" && item);
48
- // 两处对齐:从头截断,上限 96 字符(oneLine 默认值)。
49
- return `${title} ${oneLine(found || fallback, 96)}`;
53
+ return `${title} ${clip(found || fallback)}`;
50
54
  };
51
55
 
52
56
  if (variant === "default" && AGENT_FAMILY_TOOL_NAMES.has(toolName) && args.agent_id) {
53
- return { main: `${title} ${oneLine(args.agent_id, 96)}`, detail: "" };
57
+ return { main: `${title} ${clip(args.agent_id)}`, detail: "" };
54
58
  }
55
59
  if (variant === "grouping" && (name === "agent" || name === "agents")) {
56
60
  const displayName = args.subagent_type ?? args.agent_type ?? args.agent;
@@ -104,28 +108,28 @@ export function toolCallSummary(
104
108
  ].filter(Boolean);
105
109
  if (variant === "grouping") {
106
110
  return {
107
- main: `Read ${oneLine(args.path || "...")}`,
111
+ main: `Read ${clip(args.path || "...")}`,
108
112
  detail: details.length ? ` (${details.join(", ")})` : "",
109
113
  };
110
114
  }
111
115
  return {
112
- main: `${title}${args.path ? ` ${oneLine(args.path, 96)}` : ""}`,
116
+ main: `${title}${args.path ? ` ${clip(args.path)}` : ""}`,
113
117
  detail: details.length ? ` (${details.join(", ")})` : "",
114
118
  };
115
119
  }
116
120
  if (variant === "grouping") {
117
- if (toolName === "bash") return { main: `Bash ${oneLine(args.command || "...")}`, detail: "" };
121
+ if (toolName === "bash") return { main: `Bash ${clip(args.command || "...")}`, detail: "" };
118
122
  if (toolName === "grep") {
119
- const pattern = oneLine(args.pattern || "...");
123
+ const pattern = clip(args.pattern || "...");
120
124
  return {
121
- main: `Grep ${JSON.stringify(pattern)}${args.path ? ` in ${oneLine(args.path)}` : ""}`,
125
+ main: `Grep ${JSON.stringify(pattern)}${args.path ? ` in ${clip(args.path)}` : ""}`,
122
126
  detail: "",
123
127
  };
124
128
  }
125
129
  if (toolName === "find") {
126
- const pattern = oneLine(args.pattern || "...");
130
+ const pattern = clip(args.pattern || "...");
127
131
  return {
128
- main: `Find ${JSON.stringify(pattern)}${args.path ? ` in ${oneLine(args.path)}` : ""}`,
132
+ main: `Find ${JSON.stringify(pattern)}${args.path ? ` in ${clip(args.path)}` : ""}`,
129
133
  detail: "",
130
134
  };
131
135
  }
@@ -147,7 +151,7 @@ export function toolCallSummary(
147
151
  return {
148
152
  main:
149
153
  preferred !== undefined && preferred !== null && typeof preferred !== "object"
150
- ? `${title} ${oneLine(preferred, 96)}`
154
+ ? `${title} ${clip(preferred)}`
151
155
  : title,
152
156
  detail: "",
153
157
  };
@@ -162,7 +166,7 @@ export function toolCallSummary(
162
166
  args.name ??
163
167
  args.prompt;
164
168
  return {
165
- main: `${title}${preferred === undefined ? "" : ` ${oneLine(preferred)}`}`,
169
+ main: `${title}${preferred === undefined ? "" : ` ${clip(preferred)}`}`,
166
170
  detail: "",
167
171
  };
168
172
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "0.8.65",
3
+ "version": "0.8.67",
4
4
  "license": "MIT",
5
5
  "description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
6
6
  "type": "module",
@@ -34,7 +34,7 @@
34
34
  "./themes/cc-dark.json",
35
35
  "./themes/cc-light.json"
36
36
  ],
37
- "image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/welcome.webp",
37
+ "image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/preview.png",
38
38
  "video": "https://github.com/user-attachments/assets/6c858000-fdad-43f9-957f-4d0278648498"
39
39
  },
40
40
  "scripts": {