pi-cc-extensions 0.8.30 → 0.8.31

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.
@@ -3003,13 +3003,26 @@ export default function (pi: ExtensionAPI, configOverride?: Partial<Config>) {
3003
3003
  // The optional override keeps integration tests independent from the user's global config.
3004
3004
  if (configOverride) config = normalizeConfig({ ...config, ...configOverride });
3005
3005
  const writeExecutionMetadata = installWriteOverride(pi, new WriteExecutionMetadataStore());
3006
- const globalToolRendering = installGlobalToolRendering(writeExecutionMetadata);
3007
- const toolGrouping = installToolGrouping(() => config.mode === "on");
3008
- deactivateLegacyCompactionRendering();
3009
- const compactStyle: CompactStyleHooks = installCompactStyle(pi, {
3010
- getMode: () => config.mode,
3011
- getExcludeRenderers: () => config.excludeRenderers,
3012
- });
3006
+ let installation:
3007
+ | {
3008
+ globalToolRendering: GlobalToolRenderPatch;
3009
+ toolGrouping: ToolGroupingHooks;
3010
+ compactStyle: CompactStyleHooks;
3011
+ }
3012
+ | undefined;
3013
+ const ensureTuiInstallation = (ctx: any) => {
3014
+ if (ctx?.mode !== "tui" || !ctx?.hasUI) return undefined;
3015
+ if (installation) return installation;
3016
+ const globalToolRendering = installGlobalToolRendering(writeExecutionMetadata);
3017
+ const toolGrouping = installToolGrouping(() => config.mode === "on");
3018
+ deactivateLegacyCompactionRendering();
3019
+ const compactStyle = installCompactStyle(pi, {
3020
+ getMode: () => config.mode,
3021
+ getExcludeRenderers: () => config.excludeRenderers,
3022
+ });
3023
+ installation = { globalToolRendering, toolGrouping, compactStyle };
3024
+ return installation;
3025
+ };
3013
3026
 
3014
3027
  pi.registerCommand("ccstyle", {
3015
3028
  description: "Configure Claude Code style, fixed editor, and rich diff options",
@@ -3026,11 +3039,15 @@ export default function (pi: ExtensionAPI, configOverride?: Partial<Config>) {
3026
3039
  handler: async (args, ctx) => {
3027
3040
  const arg = args.trim().toLowerCase();
3028
3041
  if (!arg || arg === "panel") {
3029
- await showCcstylePanel(ctx, compactStyle, toolGrouping);
3042
+ const hooks = ensureTuiInstallation(ctx);
3043
+ if (hooks) await showCcstylePanel(ctx, hooks.compactStyle, hooks.toolGrouping);
3044
+ else ctx.ui?.notify?.("/ccstyle requires TUI mode", "warning");
3030
3045
  return;
3031
3046
  }
3032
3047
  if (arg === "on" || arg === "off" || arg === "compact") {
3033
- applyStyleMode(arg, ctx, compactStyle, toolGrouping);
3048
+ const hooks = ensureTuiInstallation(ctx);
3049
+ if (hooks) applyStyleMode(arg, ctx, hooks.compactStyle, hooks.toolGrouping);
3050
+ else ctx.ui?.notify?.("/ccstyle requires TUI mode", "warning");
3034
3051
  return;
3035
3052
  }
3036
3053
  if (arg === "status") {
@@ -3042,69 +3059,81 @@ export default function (pi: ExtensionAPI, configOverride?: Partial<Config>) {
3042
3059
  });
3043
3060
 
3044
3061
  pi.on("session_start", async (event, ctx) => {
3045
- toolGrouping.setTheme(ctx.ui.theme);
3046
- compactStyle?.onSessionStart(event, ctx);
3062
+ const hooks = ensureTuiInstallation(ctx);
3063
+ if (!hooks) return;
3064
+ hooks.toolGrouping.setTheme(ctx.ui.theme);
3065
+ hooks.compactStyle.onSessionStart(event, ctx);
3047
3066
  pendingScrollMessages = 0;
3048
3067
  assistantMessageActive = false;
3049
3068
  ctx.ui.setStatus("ccstyle", undefined);
3050
3069
  installToolMouseInteraction(ctx);
3051
- scheduleSessionRender(compactStyle.refresh);
3070
+ scheduleSessionRender(hooks.compactStyle.refresh);
3052
3071
  });
3053
3072
 
3054
3073
  pi.on("session_compact", async (event, ctx) => {
3055
- toolGrouping.setTheme(ctx.ui.theme);
3056
- compactStyle?.onSessionCompact(event, ctx);
3074
+ const hooks = ensureTuiInstallation(ctx);
3075
+ if (!hooks) return;
3076
+ hooks.toolGrouping.setTheme(ctx.ui.theme);
3077
+ hooks.compactStyle.onSessionCompact(event, ctx);
3057
3078
  // Compaction rebuilds the transcript without session_start. Rebind after
3058
3079
  // other TUI extensions may have replaced the root input dispatcher.
3059
3080
  installToolMouseInteraction(ctx);
3060
- scheduleSessionRender(compactStyle.refresh);
3081
+ scheduleSessionRender(hooks.compactStyle.refresh);
3061
3082
  });
3062
3083
 
3063
3084
  pi.on("message_start", async (event) => {
3064
- notePendingScrollMessage(event?.message?.role);
3085
+ if (installation) notePendingScrollMessage(event?.message?.role);
3065
3086
  });
3066
3087
 
3067
3088
  pi.on("message_update", async (event, ctx) => {
3068
- compactStyle?.onMessageUpdate(event, ctx);
3069
- if (event?.message?.role === "assistant") notePendingScrollMessage("assistant");
3089
+ installation?.compactStyle.onMessageUpdate(event, ctx);
3090
+ if (installation && event?.message?.role === "assistant") notePendingScrollMessage("assistant");
3070
3091
  });
3071
3092
 
3072
3093
  pi.on("message_end", async (event) => {
3073
- if (event?.message?.role === "assistant") assistantMessageActive = false;
3094
+ if (installation && event?.message?.role === "assistant") assistantMessageActive = false;
3074
3095
  });
3075
3096
 
3076
3097
  pi.on("agent_start", async (event, ctx) => {
3077
- compactStyle?.onAgentStart(event, ctx);
3098
+ installation?.compactStyle.onAgentStart(event, ctx);
3078
3099
  });
3079
3100
 
3080
3101
  pi.on("agent_end", async (event, ctx) => {
3081
- compactStyle?.onAgentEnd(event, ctx);
3102
+ installation?.compactStyle.onAgentEnd(event, ctx);
3082
3103
  });
3083
3104
 
3084
3105
  pi.on("turn_start", async (event, ctx) => {
3085
- compactStyle?.onTurnStart(event, ctx);
3106
+ installation?.compactStyle.onTurnStart(event, ctx);
3086
3107
  });
3087
3108
 
3088
3109
  pi.on("tool_execution_start", async (event, ctx) => {
3089
- toolGrouping.setTheme(ctx.ui.theme);
3090
- compactStyle?.onToolExecutionStart(event, ctx);
3110
+ installation?.toolGrouping.setTheme(ctx.ui.theme);
3111
+ installation?.compactStyle.onToolExecutionStart(event, ctx);
3091
3112
  });
3092
3113
 
3093
3114
  pi.on("tool_execution_update", async (event, ctx) => {
3094
- compactStyle?.onToolExecutionUpdate(event, ctx);
3115
+ installation?.compactStyle.onToolExecutionUpdate(event, ctx);
3095
3116
  });
3096
3117
 
3097
3118
  pi.on("tool_execution_end", async (event, ctx) => {
3098
- compactStyle?.onToolExecutionEnd(event, ctx);
3119
+ installation?.compactStyle.onToolExecutionEnd(event, ctx);
3099
3120
  });
3100
3121
 
3101
3122
  pi.on("session_shutdown", async (event, ctx) => {
3102
- compactStyle?.onSessionShutdown(event, ctx);
3103
3123
  writeExecutionMetadata.clear();
3124
+ const current = installation;
3125
+ if (
3126
+ !current ||
3127
+ (globalThis as any)[GLOBAL_TOOL_RENDER_PATCH] !== current.globalToolRendering ||
3128
+ !current.globalToolRendering.active
3129
+ )
3130
+ return;
3131
+ current.compactStyle.onSessionShutdown(event, ctx);
3104
3132
  teardownToolMouseInteraction();
3105
- deactivateGlobalToolRendering(globalToolRendering);
3106
- toolGrouping.shutdown();
3133
+ deactivateGlobalToolRendering(current.globalToolRendering);
3134
+ current.toolGrouping.shutdown();
3107
3135
  deactivateLegacyCompactionRendering();
3108
3136
  clearAllAnimations();
3137
+ installation = undefined;
3109
3138
  });
3110
3139
  }
@@ -84,31 +84,38 @@ export function formatSubagentNotificationLines(lines: string[], width: number):
84
84
  }
85
85
 
86
86
  export default function subagentNotificationExtension(pi: ExtensionAPI): void {
87
- const prototype = CustomMessageComponent.prototype as any;
88
- const host = globalThis as any;
89
- const previous = host[PATCH_KEY] as Patch | undefined;
90
- if (previous) previous.active = false;
91
- const originalRender =
92
- previous && prototype.render === previous.installedRender
93
- ? previous.originalRender
94
- : prototype.render;
95
- const patch = {
96
- active: true,
97
- prototype,
98
- originalRender,
99
- installedRender: undefined as any,
100
- } satisfies Patch;
101
- patch.installedRender = function (this: any, width: number): string[] {
102
- const lines = originalRender.call(this, width);
103
- if (!patch.active || this?.message?.customType !== "subagent-notification") return lines;
104
- return formatSubagentNotificationLines(lines, width);
105
- };
106
- prototype.render = patch.installedRender;
107
- host[PATCH_KEY] = patch;
87
+ let patch: Patch | undefined;
88
+
89
+ pi.on("session_start", async (_event, ctx) => {
90
+ if (patch || ctx?.mode !== "tui" || !ctx?.hasUI) return;
91
+ const prototype = CustomMessageComponent.prototype as any;
92
+ const host = globalThis as any;
93
+ const previous = host[PATCH_KEY] as Patch | undefined;
94
+ if (previous) previous.active = false;
95
+ const originalRender =
96
+ previous && prototype.render === previous.installedRender
97
+ ? previous.originalRender
98
+ : prototype.render;
99
+ patch = {
100
+ active: true,
101
+ prototype,
102
+ originalRender,
103
+ installedRender: undefined as any,
104
+ };
105
+ const installed = patch;
106
+ installed.installedRender = function (this: any, width: number): string[] {
107
+ const lines = originalRender.call(this, width);
108
+ if (!installed.active || this?.message?.customType !== "subagent-notification") return lines;
109
+ return formatSubagentNotificationLines(lines, width);
110
+ };
111
+ prototype.render = installed.installedRender;
112
+ host[PATCH_KEY] = installed;
113
+ });
108
114
 
109
115
  pi.on("session_shutdown", async () => {
110
- if (!patch.active) return;
116
+ if (!patch?.active) return;
111
117
  patch.active = false;
112
- if (prototype.render === patch.installedRender) prototype.render = originalRender;
118
+ if (patch.prototype.render === patch.installedRender)
119
+ patch.prototype.render = patch.originalRender;
113
120
  });
114
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "0.8.30",
3
+ "version": "0.8.31",
4
4
  "description": "A Pi productivity suite with Claude Code-style UI, structured questionnaires, context inspection, and agent/session references",
5
5
  "type": "module",
6
6
  "keywords": [