pi-cc-extensions 0.8.61 → 0.8.62

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
@@ -56,7 +56,7 @@ Run `/reload` after installation.
56
56
  "diffViewMode": "auto", // diff layout: auto / split / unified
57
57
  "diffIndicatorMode": "bars", // diff change indicators: bars / classic / none
58
58
  "diffSplitMinWidth": 120, // min terminal width before auto layout uses side-by-side columns
59
- "diffCollapsedLines": 24, // edit/diff body lines shown when collapsed; beyond that shows the expand hint (Ctrl+O / click)
59
+ "editDiffCollapsedLines": 24, // Edit collapsed lines; beyond that shows the expand hint (Ctrl+O / click)
60
60
  "writeDiffCollapsedLines": 0, // write collapsed body lines; 0 = ↳ created • expand hint (stats stay on the title)
61
61
  "diffWordWrap": true, // whether long diff lines wrap (otherwise truncated)
62
62
  "expandedPreviewMaxLines": 40, // max body lines for expanded output/diff
package/README.md CHANGED
@@ -56,7 +56,7 @@ pi install git:github.com/minuque/pi-cc-extensions
56
56
  "diffViewMode": "auto", // diff 布局:auto / split / unified
57
57
  "diffIndicatorMode": "bars", // diff 变更指示:bars / classic / none
58
58
  "diffSplitMinWidth": 120, // 自动布局下使用左右分栏的最小终端宽度
59
- "diffCollapsedLines": 24, // 折叠时展示的 edit/diff 行数,超出显示展开提示(Ctrl+O / 点击)
59
+ "editDiffCollapsedLines": 24, // Edit 折叠行数;超出显示展开提示(Ctrl+O / 点击)
60
60
  "writeDiffCollapsedLines": 0, // write 折叠行数;0 = ↳ created • 展开提示(统计在标题)
61
61
  "diffWordWrap": true, // 长 diff 行是否换行(否则截断)
62
62
  "expandedPreviewMaxLines": 40, // 展开后输出/diff 正文的最大行数
@@ -15,7 +15,7 @@ export interface ToolDisplayConfig {
15
15
  diffViewMode: DiffViewMode;
16
16
  diffIndicatorMode: DiffIndicatorMode;
17
17
  diffSplitMinWidth: number;
18
- diffCollapsedLines: number;
18
+ editDiffCollapsedLines: number;
19
19
  /** Write-only collapsed body lines. 0 = `↳ created • click to show more`. */
20
20
  writeDiffCollapsedLines: number;
21
21
  diffWordWrap: boolean;
@@ -26,8 +26,8 @@ export const DEFAULT_TOOL_DISPLAY_CONFIG: ToolDisplayConfig = {
26
26
  diffViewMode: "auto",
27
27
  diffIndicatorMode: "bars",
28
28
  diffSplitMinWidth: 120,
29
- /** Collapsed tool/diff body: ~half a typical terminal after chrome. */
30
- diffCollapsedLines: 24,
29
+ /** Collapsed edit/diff body: ~half a typical terminal after chrome. */
30
+ editDiffCollapsedLines: 24,
31
31
  /**
32
32
  * Write create/overwrite collapsed body.
33
33
  * 0 = `↳ created • click to show more` (stats stay on the title).
@@ -48,7 +48,7 @@ export type Config = {
48
48
  diffViewMode: DiffViewMode;
49
49
  diffIndicatorMode: DiffIndicatorMode;
50
50
  diffSplitMinWidth: number;
51
- diffCollapsedLines: number;
51
+ editDiffCollapsedLines: number;
52
52
  writeDiffCollapsedLines: number;
53
53
  diffWordWrap: boolean;
54
54
  expandedPreviewMaxLines: number;
@@ -99,7 +99,7 @@ export const DEFAULT_CONFIG: Config = {
99
99
  diffViewMode: DEFAULT_TOOL_DISPLAY_CONFIG.diffViewMode,
100
100
  diffIndicatorMode: DEFAULT_TOOL_DISPLAY_CONFIG.diffIndicatorMode,
101
101
  diffSplitMinWidth: DEFAULT_TOOL_DISPLAY_CONFIG.diffSplitMinWidth,
102
- diffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.diffCollapsedLines,
102
+ editDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.editDiffCollapsedLines,
103
103
  writeDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines,
104
104
  diffWordWrap: DEFAULT_TOOL_DISPLAY_CONFIG.diffWordWrap,
105
105
  expandedPreviewMaxLines: DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
@@ -169,9 +169,9 @@ export function normalizeConfig(input: unknown): Config {
169
169
  40,
170
170
  300,
171
171
  ),
172
- diffCollapsedLines: pickPositiveInt(
173
- source.diffCollapsedLines,
174
- DEFAULT_CONFIG.diffCollapsedLines,
172
+ editDiffCollapsedLines: pickPositiveInt(
173
+ source.editDiffCollapsedLines ?? source.diffCollapsedLines,
174
+ DEFAULT_CONFIG.editDiffCollapsedLines,
175
175
  1,
176
176
  500,
177
177
  ),
@@ -223,7 +223,7 @@ export function getToolDisplayConfig(source: Config = config): ToolDisplayConfig
223
223
  diffViewMode: source.diffViewMode,
224
224
  diffIndicatorMode: source.diffIndicatorMode,
225
225
  diffSplitMinWidth: source.diffSplitMinWidth,
226
- diffCollapsedLines: source.diffCollapsedLines,
226
+ editDiffCollapsedLines: source.editDiffCollapsedLines,
227
227
  writeDiffCollapsedLines: source.writeDiffCollapsedLines,
228
228
  diffWordWrap: source.diffWordWrap,
229
229
  expandedPreviewMaxLines: source.expandedPreviewMaxLines,
@@ -241,7 +241,7 @@ export function formatConfigStatus(source: Config = config): string {
241
241
  `diffView=${source.diffViewMode}`,
242
242
  `diffIndicator=${source.diffIndicatorMode}`,
243
243
  `diffSplitMin=${source.diffSplitMinWidth}`,
244
- `diffCollapsed=${source.diffCollapsedLines}`,
244
+ `editCollapsed=${source.editDiffCollapsedLines}`,
245
245
  `writeCollapsed=${source.writeDiffCollapsedLines}`,
246
246
  `diffWordWrap=${source.diffWordWrap ? "on" : "off"}`,
247
247
  `expandedMax=${source.expandedPreviewMaxLines}`,
@@ -288,11 +288,11 @@ export async function showCcstylePanel(
288
288
  buildNumberInputSubmenu(theme, diffSplitSetting, closeSubmenu),
289
289
  };
290
290
  const diffCollapsedSetting = {
291
- id: "diffCollapsedLines",
291
+ id: "editDiffCollapsedLines",
292
292
  label: "Edit collapsed lines",
293
293
  description:
294
294
  "How many edit/diff body lines to show before the expand hint (Ctrl+O / click). Write uses its own setting below.",
295
- currentValue: String(config.diffCollapsedLines),
295
+ currentValue: String(config.editDiffCollapsedLines),
296
296
  values: [...DIFF_COLLAPSED_LINES_VALUES],
297
297
  submenu: (_current: string, closeSubmenu: (selected?: string) => void) =>
298
298
  buildNumberInputSubmenu(theme, diffCollapsedSetting, closeSubmenu),
@@ -458,11 +458,16 @@ export async function showCcstylePanel(
458
458
  });
459
459
  diffSplitSetting.currentValue = String(config.diffSplitMinWidth);
460
460
  break;
461
- case "diffCollapsedLines":
461
+ case "editDiffCollapsedLines":
462
462
  updateConfig({
463
- diffCollapsedLines: pickPositiveInt(value, DEFAULT_CONFIG.diffCollapsedLines, 1, 500),
463
+ editDiffCollapsedLines: pickPositiveInt(
464
+ value,
465
+ DEFAULT_CONFIG.editDiffCollapsedLines,
466
+ 1,
467
+ 500,
468
+ ),
464
469
  });
465
- diffCollapsedSetting.currentValue = String(config.diffCollapsedLines);
470
+ diffCollapsedSetting.currentValue = String(config.editDiffCollapsedLines);
466
471
  break;
467
472
  case "writeDiffCollapsedLines":
468
473
  updateConfig({
@@ -174,11 +174,38 @@ function thinkingExpandAction(): string | undefined {
174
174
  }
175
175
 
176
176
  // 只 wrap 尾部窗口;缓存未着色折行,着色放到取出时做,避免主题切换命中旧 ANSI。
177
- const previewCache = new Map<string, { lines: string[]; hiddenBefore: number }>();
178
- const PREVIEW_CACHE_MAX = 500;
177
+ type PreviewCacheEntry = { lines: string[]; hiddenBefore: number };
178
+ const previewCache = new Map<string, PreviewCacheEntry>();
179
+ export const THINKING_PREVIEW_CACHE_MAX = 2_048;
179
180
  const PREVIEW_BUDGET_MIN_CHARS = 2_000;
180
181
  const PREVIEW_BUDGET_SLACK_LINES = 2;
181
182
 
183
+ function getCachedPreview(key: string): PreviewCacheEntry | undefined {
184
+ const entry = previewCache.get(key);
185
+ if (!entry) return undefined;
186
+ previewCache.delete(key);
187
+ previewCache.set(key, entry);
188
+ return entry;
189
+ }
190
+
191
+ function cachePreview(key: string, entry: PreviewCacheEntry): void {
192
+ previewCache.delete(key);
193
+ while (previewCache.size >= THINKING_PREVIEW_CACHE_MAX) {
194
+ const oldest = previewCache.keys().next().value;
195
+ if (oldest === undefined) break;
196
+ previewCache.delete(oldest);
197
+ }
198
+ previewCache.set(key, entry);
199
+ }
200
+
201
+ export function clearThinkingPreviewCache(): void {
202
+ previewCache.clear();
203
+ }
204
+
205
+ export function thinkingPreviewCacheSize(): number {
206
+ return previewCache.size;
207
+ }
208
+
182
209
  /** 按可见宽度估算折行数,不走 Text 全量 wrap。无换行长段也能计到隐藏行。 */
183
210
  function countWrappedLines(text: string, contentWidth: number): number {
184
211
  if (!text) return 0;
@@ -219,14 +246,13 @@ function layoutThinkingPreview(
219
246
  else cut = 0;
220
247
  }
221
248
  const cacheKey = `${width}:${padding}:${cut}:${source}`;
222
- let entry = previewCache.get(cacheKey);
249
+ let entry = getCachedPreview(cacheKey);
223
250
  if (!entry) {
224
251
  entry = {
225
252
  lines: wrapTextWithAnsi(source.replace(/\t/g, " "), contentWidth),
226
253
  hiddenBefore: cut > 0 ? countWrappedLines(text.slice(0, cut), contentWidth) : 0,
227
254
  };
228
- if (previewCache.size >= PREVIEW_CACHE_MAX) previewCache.clear();
229
- previewCache.set(cacheKey, entry);
255
+ cachePreview(cacheKey, entry);
230
256
  }
231
257
  const hiddenLines = entry.hiddenBefore + Math.max(0, entry.lines.length - config.previewLines);
232
258
  const visible = hiddenLines > 0 ? entry.lines.slice(-config.previewLines) : entry.lines;
@@ -265,6 +291,15 @@ export class ThinkingPreviewBlock implements Component {
265
291
  private _expanded: boolean;
266
292
  private hintHovered = false;
267
293
  private expandedBody: { width: number; lines: string[] } | undefined;
294
+ private collapsedMemo:
295
+ | {
296
+ width: number;
297
+ previewLines: number;
298
+ hintHovered: boolean;
299
+ expandAction: string | undefined;
300
+ lines: string[];
301
+ }
302
+ | undefined;
268
303
 
269
304
  constructor(
270
305
  heading: string,
@@ -294,6 +329,7 @@ export class ThinkingPreviewBlock implements Component {
294
329
  }
295
330
 
296
331
  setExpanded(expanded: boolean): void {
332
+ if (this._expanded !== expanded) this.collapsedMemo = undefined;
297
333
  this._expanded = expanded;
298
334
  if (expanded) expandedThinking.add(this.messageTimestamp);
299
335
  else {
@@ -303,6 +339,7 @@ export class ThinkingPreviewBlock implements Component {
303
339
  }
304
340
 
305
341
  setHintHovered(hovered: boolean): void {
342
+ if (this.hintHovered !== hovered) this.collapsedMemo = undefined;
306
343
  this.hintHovered = hovered;
307
344
  }
308
345
 
@@ -362,16 +399,39 @@ export class ThinkingPreviewBlock implements Component {
362
399
  });
363
400
  return box.render(width);
364
401
  }
402
+
403
+ const expandAction = thinkingExpandAction();
404
+ if (
405
+ this.collapsedMemo?.width === width &&
406
+ this.collapsedMemo.previewLines === config.previewLines &&
407
+ this.collapsedMemo.hintHovered === this.hintHovered &&
408
+ this.collapsedMemo.expandAction === expandAction
409
+ ) {
410
+ return this.collapsedMemo.lines;
411
+ }
412
+
365
413
  const body = this.bodyLines(width, this.padding);
366
414
  const heading = this.headingLines(width, body.hiddenLines, this.padding);
367
- if (!body.lines.length) return heading;
368
- return [
369
- ...heading,
370
- ...body.lines.map((line) => padPreviewLine(this.style(line), width, this.padding)),
371
- ];
415
+ const lines = body.lines.length
416
+ ? [
417
+ ...heading,
418
+ ...body.lines.map((line) => padPreviewLine(this.style(line), width, this.padding)),
419
+ ]
420
+ : heading;
421
+ this.collapsedMemo = {
422
+ width,
423
+ previewLines: config.previewLines,
424
+ hintHovered: this.hintHovered,
425
+ expandAction,
426
+ lines,
427
+ };
428
+ return lines;
372
429
  }
373
430
 
374
- invalidate() {}
431
+ invalidate() {
432
+ this.collapsedMemo = undefined;
433
+ this.expandedBody = undefined;
434
+ }
375
435
  }
376
436
 
377
437
  function parseSummaryPart(text: string): SummaryPart | undefined {
@@ -922,6 +982,7 @@ function compactThinking(pi: ExtensionAPI) {
922
982
  completedDurations.clear();
923
983
  streamingComponents.clear();
924
984
  expandedThinking.clear();
985
+ clearThinkingPreviewCache();
925
986
  if (ctx.mode === "tui") ctx.ui.setWidget(WIDGET_ID, undefined);
926
987
 
927
988
  if (patchInstalled) {
@@ -0,0 +1,19 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+
3
+ function modelLabel(model: any): string | undefined {
4
+ if (!model) return undefined;
5
+ const name = model.name || model.id;
6
+ if (!name) return undefined;
7
+ return model.provider ? `${model.provider} · ${name}` : name;
8
+ }
9
+
10
+ function apply(ctx: any): void {
11
+ if (!ctx?.hasUI) return;
12
+ ctx.ui?.setStatus?.("model", modelLabel(ctx.model));
13
+ }
14
+
15
+ /** 用 setStatus 挂模型名,不 setFooter,不接管原生 footer。 */
16
+ export default function (pi: ExtensionAPI): void {
17
+ pi.on("session_start", async (_event, ctx) => apply(ctx));
18
+ pi.on("model_select", async (_event, ctx) => apply(ctx));
19
+ }
@@ -5,6 +5,7 @@ import { config } from "./config/config.ts";
5
5
  import piAliases from "./feature/shell/aliases.ts";
6
6
  import piStartupHeader from "./feature/shell/startup-header.ts";
7
7
  import workingMessage from "./feature/shell/working-message.ts";
8
+ import modelStatus from "./feature/shell/model-status.ts";
8
9
 
9
10
  // feature
10
11
  import agentAutocomplete from "./feature/reference/subagent.ts";
@@ -22,6 +23,7 @@ export default function (pi: ExtensionAPI): void {
22
23
  if (config.enableAliases) piAliases(pi);
23
24
  piStartupHeader(pi);
24
25
  if (config.enableWorkingMessage) workingMessage(pi);
26
+ modelStatus(pi);
25
27
 
26
28
  // render stack:thinking controller 直接交给 style 作 query
27
29
  markdownEnhance(pi);
@@ -3,7 +3,7 @@
3
3
  * (`Ran for 8s, bash×2, read×2`),edit/write 独立标题行(`✓ write <path> (+25 -0)`),
4
4
  * 普通工具折叠时不显示独立行;展开(Ctrl+O / fullscreen 点击)在单个工具卡中恢复
5
5
  * compact-thinking/Pi 原生或专用 renderer。edit/write 复用 mode=on 的 rich diff
6
- * 与 `diffCollapsedLines` / `writeDiffCollapsedLines` / `expandedPreviewMaxLines`。
6
+ * 与 `editDiffCollapsedLines` / `writeDiffCollapsedLines` / `expandedPreviewMaxLines`。
7
7
  * Agent/Task 族:调用只进摘要计数,tool 卡始终折叠(避免 pending→完成高度闪动)。
8
8
  * 底部 Agents/Tasks 面板由 pi-subagents/pi-tasks 独立 widget 负责,不经 tool 卡外置。
9
9
  *
@@ -526,6 +526,12 @@ function compactEditWriteLine(
526
526
  return ["", truncateToWidth(line, width, "")];
527
527
  }
528
528
 
529
+ /** expanded 写进 rich diff 闭包,折叠/展开分槽缓存,避免每帧 parseDiff。 */
530
+ const compactRichDiffCache = new WeakMap<
531
+ object,
532
+ { result: unknown; collapsed?: unknown; expanded?: unknown }
533
+ >();
534
+
529
535
  /**
530
536
  * compact edit/write:标题行 + mode=on 同一套 rich diff。
531
537
  * 折叠/展开都走 `renderRichToolResult`,limits 不另开一套。
@@ -540,23 +546,33 @@ function compactEditWriteLines(
540
546
  const expanded = component.expanded === true;
541
547
  const isError = result?.isError === true;
542
548
  const isPending = !result || component.isPartial === true;
543
- const candidate =
544
- !isPending && writeMetadata
545
- ? renderRichToolResult(
546
- String(component.toolName ?? ""),
547
- result,
548
- {
549
- expanded,
550
- isPartial: component.isPartial === true,
551
- isError,
552
- isHovered: () => isToolCallHovered(component.toolCallId),
553
- },
554
- theme,
555
- component,
556
- writeMetadata,
557
- getToolDisplayConfig,
558
- )
559
- : undefined;
549
+ let candidate: unknown;
550
+ if (!isPending && writeMetadata) {
551
+ let entry = compactRichDiffCache.get(component);
552
+ if (!entry || entry.result !== result) {
553
+ entry = { result };
554
+ compactRichDiffCache.set(component, entry);
555
+ }
556
+ const slot = expanded ? "expanded" : "collapsed";
557
+ candidate = entry[slot];
558
+ if (!isRichDiffComponent(candidate)) {
559
+ candidate = renderRichToolResult(
560
+ String(component.toolName ?? ""),
561
+ result,
562
+ {
563
+ expanded,
564
+ isPartial: component.isPartial === true,
565
+ isError,
566
+ isHovered: () => isToolCallHovered(component.toolCallId),
567
+ },
568
+ theme,
569
+ component,
570
+ writeMetadata,
571
+ getToolDisplayConfig,
572
+ );
573
+ if (isRichDiffComponent(candidate)) entry[slot] = candidate;
574
+ }
575
+ }
560
576
  const hasRich = isRichDiffComponent(candidate);
561
577
  if (hasRich) {
562
578
  component.resultRendererComponent = candidate;
@@ -39,7 +39,7 @@ export function displayConfigCacheKey(config: ToolDisplayConfig): string {
39
39
  config.diffViewMode,
40
40
  config.diffIndicatorMode,
41
41
  String(config.diffSplitMinWidth),
42
- String(config.diffCollapsedLines),
42
+ String(config.editDiffCollapsedLines),
43
43
  String(config.writeDiffCollapsedLines),
44
44
  config.diffWordWrap ? "1" : "0",
45
45
  String(config.expandedPreviewMaxLines),
@@ -143,7 +143,7 @@ export function renderEditDiffResult(
143
143
  const headerRows = renderHeaderRows(parsed.stats, mode, safeWidth, theme);
144
144
  const displayLimit = resolveDiffDisplayLimit(
145
145
  options.expanded,
146
- live.diffCollapsedLines,
146
+ live.editDiffCollapsedLines,
147
147
  live.expandedPreviewMaxLines,
148
148
  );
149
149
  const processBudget = resolveDiffProcessBudget(displayLimit, wordWrap);
@@ -177,7 +177,7 @@ export function renderEditDiffResult(
177
177
  bodyRows,
178
178
  safeWidth,
179
179
  options.expanded,
180
- live.diffCollapsedLines,
180
+ live.editDiffCollapsedLines,
181
181
  live.expandedPreviewMaxLines,
182
182
  parsed.stats.hunks,
183
183
  theme,
@@ -41,20 +41,20 @@ export function resolveDiffDisplayLimit(
41
41
  : DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines;
42
42
  const collapsedLimit = Number.isFinite(maxCollapsedLines)
43
43
  ? maxCollapsedLines
44
- : DEFAULT_TOOL_DISPLAY_CONFIG.diffCollapsedLines;
44
+ : DEFAULT_TOOL_DISPLAY_CONFIG.editDiffCollapsedLines;
45
45
  return expanded ? Math.max(0, expandedLimit) : Math.max(1, collapsedLimit);
46
46
  }
47
47
 
48
- /** Write collapsed body limit. Missing/NaN falls back to edit's `diffCollapsedLines`. */
48
+ /** Write collapsed body limit. Missing/NaN falls back to edit's `editDiffCollapsedLines`. */
49
49
  export function resolveWriteCollapsedLimit(
50
- config: Pick<ToolDisplayConfig, "writeDiffCollapsedLines" | "diffCollapsedLines">,
50
+ config: Pick<ToolDisplayConfig, "writeDiffCollapsedLines" | "editDiffCollapsedLines">,
51
51
  ): number {
52
52
  const value = config.writeDiffCollapsedLines;
53
53
  if (Number.isFinite(value)) {
54
54
  return Math.max(0, value);
55
55
  }
56
- const fallback = Number.isFinite(config.diffCollapsedLines)
57
- ? config.diffCollapsedLines
56
+ const fallback = Number.isFinite(config.editDiffCollapsedLines)
57
+ ? config.editDiffCollapsedLines
58
58
  : DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines;
59
59
  return Math.max(0, fallback);
60
60
  }
@@ -180,11 +180,13 @@ export class ToolGroupComponent extends Container {
180
180
  }
181
181
 
182
182
  addTool(tool: any): void {
183
+ this.settledCache = undefined;
183
184
  this.children.push(tool);
184
185
  tool[PARENT_KEY] = this;
185
186
  }
186
187
 
187
188
  releaseTools(): any[] {
189
+ this.settledCache = undefined;
188
190
  const tools = [...this.children];
189
191
  this.children.length = 0;
190
192
  this.patch.groups.delete(this);
@@ -192,18 +194,21 @@ export class ToolGroupComponent extends Container {
192
194
  }
193
195
 
194
196
  removeTool(tool: any): void {
197
+ this.settledCache = undefined;
195
198
  const index = this.children.indexOf(tool);
196
199
  if (index >= 0) this.children.splice(index, 1);
197
200
  if (tool?.[PARENT_KEY] === this) delete tool[PARENT_KEY];
198
201
  }
199
202
 
200
203
  setExpanded(expanded: boolean): void {
204
+ if (this._expanded !== expanded) this.settledCache = undefined;
201
205
  this._expanded = expanded;
202
206
  for (const tool of this.children)
203
207
  (tool as Component & { setExpanded?: (expanded: boolean) => void }).setExpanded?.(expanded);
204
208
  }
205
209
 
206
210
  setHintHovered(hovered: boolean): void {
211
+ if (this.hintHovered !== hovered) this.settledCache = undefined;
207
212
  this.hintHovered = hovered;
208
213
  }
209
214
 
@@ -232,6 +237,7 @@ export class ToolGroupComponent extends Container {
232
237
  }
233
238
 
234
239
  invalidate(): void {
240
+ this.settledCache = undefined;
235
241
  for (const tool of this.children) tool.invalidate?.();
236
242
  }
237
243
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "0.8.61",
3
+ "version": "0.8.62",
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",