pi-cc-extensions 0.8.3 → 0.8.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.
package/README.md CHANGED
@@ -86,7 +86,6 @@
86
86
 
87
87
  `mode` 可取 `on`、`off` 或 `compact`。旧版 `enabled: true/false` 会自动迁移为 `on/off`。排除名单使用精确工具名;手动修改配置后执行 `/reload`。`Agent` 的专用 renderer 始终保留。
88
88
 
89
- `compact` 不会自动修改 Pi 的 `hideThinkingBlock` 或 `outputPad` 设置。运行总结会持久化到 Session,但只在 `compact` 模式显示。
90
89
 
91
90
  Compact transcript 行为改编自 [avhagedorn/pi-compact-transcript](https://github.com/avhagedorn/pi-compact-transcript) v0.6.2(MIT,Alan Hagedorn)。
92
91
 
@@ -253,8 +253,8 @@ export class ExpandedToolResultText {
253
253
  }
254
254
  }
255
255
 
256
- function renderCollapsedToolResult(body: string, collapsedHint = ""): string {
257
- return `\n ⎿ ${body}${collapsedHint}`;
256
+ export function renderCollapsedToolResult(body: string, collapsedHint = ""): string {
257
+ return ` ↳ ${body}${collapsedHint}`;
258
258
  }
259
259
 
260
260
  function renderExpandedToolResult(
@@ -1172,7 +1172,7 @@ function shouldUseSelfShell(component: any, patch: GlobalToolRenderPatch): boole
1172
1172
  const definition = component.toolDefinition ?? component.builtInToolDefinition;
1173
1173
  const toolName = String(component.toolName || definition?.name || "");
1174
1174
  const useSelfShell =
1175
- patch.mode() !== "off" &&
1175
+ patch.enabled() &&
1176
1176
  SUBAGENT_TOOL_NAMES.has(toolName) &&
1177
1177
  definition != null &&
1178
1178
  definition.renderShell === undefined;
@@ -32,6 +32,7 @@ type AssistantPrototypePatch = {
32
32
  prototype: any;
33
33
  active: boolean;
34
34
  originalUpdateContent: (...args: any[]) => any;
35
+ nativeUpdateContent: (...args: any[]) => any;
35
36
  patchedUpdateContent: (...args: any[]) => any;
36
37
  };
37
38
 
@@ -131,6 +132,7 @@ const MARKER_WIDTH = 2;
131
132
  const STATE_KEY = Symbol.for("pi.ccstyle.compact-style.state");
132
133
  const TOOL_PATCH_KEY = Symbol.for("pi.ccstyle.compact-style.tool-patch");
133
134
  const ASSISTANT_PATCH_KEY = Symbol.for("pi.ccstyle.compact-style.assistant-patch");
135
+ const ASSISTANT_REENTRY_KEY = Symbol.for("pi.ccstyle.compact-style.assistant-reentry");
134
136
  const TOOL_NATIVE_CHILD_KEY = Symbol.for("pi.ccstyle.compact-style.native-tool-child");
135
137
 
136
138
  function newRunStats(): RunStats {
@@ -499,7 +501,7 @@ function anchorCurrentThoughtTo(info: ToolInfo) {
499
501
 
500
502
  function currentThoughtLine(toolCallId: string, theme: Theme): string {
501
503
  if (!thoughtTickerEnabled() || state.thoughtAnchorId !== toolCallId || !state.currentThoughtHeading) return "";
502
- const prefix = " ↳ ";
504
+ const prefix = "↳ ";
503
505
  const budget = previewWidth((process.stdout.columns || 100) - prefix.length);
504
506
  return theme.fg("dim", prefix) + theme.fg("thinkingText", limitPlain(state.currentThoughtHeading, budget));
505
507
  }
@@ -786,8 +788,11 @@ function patchToolExecutionComponent(installation: CompactInstallation): ToolPro
786
788
  return;
787
789
  }
788
790
 
789
- this.selfRenderContainer.addChild(new Text(line, 0, 0));
790
791
  const thoughtLine = currentThoughtLine(this.toolCallId, theme);
792
+ // Keep a compact tool group visually separate from its thinking ticker,
793
+ // without adding vertical space to ordinary compact tool rows.
794
+ if (thoughtLine) this.selfRenderContainer.addChild(new Spacer(1));
795
+ this.selfRenderContainer.addChild(new Text(line, 0, 0));
791
796
  if (thoughtLine) this.selfRenderContainer.addChild(new Text(thoughtLine, 0, 0));
792
797
  };
793
798
 
@@ -839,20 +844,34 @@ function patchAssistantMessageComponent(installation: CompactInstallation): Assi
839
844
  prototype,
840
845
  active: true,
841
846
  originalUpdateContent: prototype.updateContent,
847
+ nativeUpdateContent: prototype.updateContent,
842
848
  patchedUpdateContent: undefined as any,
843
849
  };
844
850
 
845
851
  patch.patchedUpdateContent = function patchedUpdateContent(this: any, message: any) {
852
+ // A renderer loaded after ccstyle may call the previous ccstyle wrapper.
853
+ // Bypass the newly linked downstream wrapper on that re-entry to avoid a
854
+ // recursion loop while preserving the original native renderer.
855
+ if (this[ASSISTANT_REENTRY_KEY] === patch) {
856
+ return patch.nativeUpdateContent.call(this, message);
857
+ }
846
858
  if (!patch.active || !installation.active || state.activeInstallation !== installation) {
847
859
  return patch.originalUpdateContent.call(this, message);
848
860
  }
849
861
 
850
862
  state.assistantComponents.add(this);
851
- state.thinkingHidden = !!this.hideThinkingBlock;
852
863
  const mode = currentMode();
853
- if (mode !== "compact" || !this.hideThinkingBlock || !Array.isArray(message?.content)) {
864
+ // Compact owns thinking presentation: always suppress the full native block
865
+ // and surface only the short ticker, without changing Pi's persisted setting.
866
+ state.thinkingHidden = mode === "compact" || !!this.hideThinkingBlock;
867
+ if (mode !== "compact" || !Array.isArray(message?.content)) {
854
868
  if (mode !== "compact") clearCurrentThought();
855
- return patch.originalUpdateContent.call(this, message);
869
+ this[ASSISTANT_REENTRY_KEY] = patch;
870
+ try {
871
+ return patch.originalUpdateContent.call(this, message);
872
+ } finally {
873
+ delete this[ASSISTANT_REENTRY_KEY];
874
+ }
856
875
  }
857
876
  const theme = state.currentTheme;
858
877
  if (!theme || !this.contentContainer || typeof this.contentContainer.clear !== "function") {
@@ -886,6 +905,17 @@ function patchAssistantMessageComponent(installation: CompactInstallation): Assi
886
905
  return patch;
887
906
  }
888
907
 
908
+ /** Reclaim the outermost assistant renderer after another extension patches it. */
909
+ function ensureAssistantPatchOwnership(installation: CompactInstallation): void {
910
+ const patch = installation.assistantPatch;
911
+ if (!installation.active || !patch) return;
912
+ const prototype = patch.prototype;
913
+ if (prototype.updateContent === patch.patchedUpdateContent) return;
914
+ patch.originalUpdateContent = prototype.updateContent;
915
+ prototype.updateContent = patch.patchedUpdateContent;
916
+ prototype[ASSISTANT_PATCH_KEY] = patch;
917
+ }
918
+
889
919
  function patchRenderers(installation: CompactInstallation): void {
890
920
  installation.toolPatch = patchToolExecutionComponent(installation);
891
921
  installation.assistantPatch = patchAssistantMessageComponent(installation);
@@ -987,7 +1017,7 @@ export class DynamicSummaryComponent {
987
1017
  invalidate(): void {}
988
1018
 
989
1019
  render(width: number): string[] {
990
- const line = isCompact() ? summaryLine(this.data) : "";
1020
+ const line = currentMode() !== "off" ? summaryLine(this.data) : "";
991
1021
  if (!line) return [];
992
1022
  return new Text(this.theme.fg("muted", line), 0, 0).render(width);
993
1023
  }
@@ -996,7 +1026,7 @@ export class DynamicSummaryComponent {
996
1026
  function appendRunSummary() {
997
1027
  const stats = state.runStats;
998
1028
  // A single tool row is already the summary.
999
- if (!isCompact() || stats.toolCount < 2 || !state.pi?.appendEntry) return;
1029
+ if (currentMode() === "off" || stats.toolCount < 2 || !state.pi?.appendEntry) return;
1000
1030
  const data: CompactSummaryData = {
1001
1031
  reads: stats.readFiles.size,
1002
1032
  edits: stats.editFiles.size,
@@ -1077,6 +1107,7 @@ export function installCompactStyle(pi: ExtensionAPI, host: CompactStyleHost): C
1077
1107
  return {
1078
1108
  onSessionStart: (_event, ctx) => {
1079
1109
  if (!isOwner()) return;
1110
+ ensureAssistantPatchOwnership(installation);
1080
1111
  captureTheme(ctx);
1081
1112
  state.agentActive = false;
1082
1113
  state.runStats = newRunStats();
@@ -1111,6 +1142,7 @@ export function installCompactStyle(pi: ExtensionAPI, host: CompactStyleHost): C
1111
1142
  },
1112
1143
  onMessageUpdate: (event, ctx) => {
1113
1144
  if (!isOwner()) return;
1145
+ ensureAssistantPatchOwnership(installation);
1114
1146
  captureTheme(ctx);
1115
1147
  const type = event?.assistantMessageEvent?.type;
1116
1148
  if (typeof type === "string" && type.startsWith("thinking_")) updateCurrentThoughtFromMessage(event.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -27,8 +27,7 @@
27
27
  "./extensions/claude-code-style.ts",
28
28
  "./extensions/context.ts",
29
29
  "./extensions/session-reference.ts",
30
- "./extensions/agent-autocomplete.ts",
31
- "./extensions/compact-style.ts"
30
+ "./extensions/agent-autocomplete.ts"
32
31
  ],
33
32
  "image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/welcome.webp"
34
33
  },