pi-cc-extensions 1.0.5 → 1.0.7

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
@@ -28,7 +28,7 @@ Run `/reload` after installation.
28
28
  | Feature | Description | Entry point |
29
29
  | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
30
30
  | Claude Code UI | Tool summaries, expand/collapse, rich edit/write diffs, and `on` / `compact` / `off` modes | `/ccstyle` |
31
- | Markdown enhancements | Mermaid diagrams, admonitions, URL linking, and more | Automatic |
31
+ | Markdown enhancements | Mermaid dialects and circled-number conversion | Automatic; turn off with `enableMarkdownEnhance: false` |
32
32
  | Fullscreen mode | Tool card/group expand and collapse on click, previews, hover highlight, and a back-to-bottom button | `TUIMODE=fullscreen` or `--tui-mode fullscreen` |
33
33
  | Settings panel | `Style / Features / UI / Diff / Thinking / Footer` tabs | `/ccstyle` |
34
34
  | Context inspection | Usage breakdown and previews for the system prompt, memory, skills, tools definition, and messages | `/context` |
@@ -55,6 +55,7 @@ Renderer snapshots for `on` / `compact` modes: [default](./docs/tool-render-exam
55
55
  "enableAgentSummary": true, // per-turn tool summary
56
56
  "enableWorkingMessage": true, // Working... bottom token/elapsed
57
57
  "enableAliases": true, // /clear, /exit aliases
58
+ "enableMarkdownEnhance": true, // markdown pass: Mermaid dialects and circled-number conversion; false hands it to other extensions
58
59
  "enableEditorPrefix": true, // editor ❯ prefix
59
60
 
60
61
  // ui
package/README.md CHANGED
@@ -28,7 +28,7 @@ pi install git:github.com/minuque/pi-cc-extensions
28
28
  | 功能 | 说明 | 入口 |
29
29
  | --------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------- |
30
30
  | Claude Code UI | 工具摘要、折叠展开、rich edit/write diff,以及`on` / `compact` / `off` 三种模式 | `/ccstyle` |
31
- | Markdown 增强 | Mermaid 图、提示框、URL 链接化等 | 自动生效 |
31
+ | Markdown 增强 | Mermaid 方言渲染、圈数字转半角括号 | 自动生效;`enableMarkdownEnhance: false` 关闭 |
32
32
  | Fullscreen mode | 工具卡/group 单击展开与收起、预览、hover 高亮、回到底部按钮 | `TUIMODE=fullscreen` 或 `--tui-mode fullscreen` |
33
33
  | 配置面板 | `Style / Features / UI / Diff / Thinking / Footer` 六页签 | `/ccstyle` |
34
34
  | 上下文检查 | 查看上下文占用,并预览 System prompt、Memory、Skills、Tools definition 和消息内容 | `/context` |
@@ -55,6 +55,7 @@ pi install git:github.com/minuque/pi-cc-extensions
55
55
  "enableAgentSummary": true, // 每回合工具摘要
56
56
  "enableWorkingMessage": true, // Working... 底部 token/耗时
57
57
  "enableAliases": true, // /clear、/exit 别名
58
+ "enableMarkdownEnhance": true, // markdown 转换:Mermaid 方言渲染、圈数字转半角括号;false 让位给其他扩展
58
59
  "enableEditorPrefix": true, // 输入框 ❯ 前缀
59
60
 
60
61
  // ui
@@ -74,6 +74,8 @@ export type Config = {
74
74
  enableAgentSummary: boolean;
75
75
  enableWorkingMessage: boolean;
76
76
  enableAliases: boolean;
77
+ /** markdown 转换:Mermaid 方言渲染、圈数字转半角括号。关掉让位给其他扩展。 */
78
+ enableMarkdownEnhance: boolean;
77
79
  /** 输入框 `❯ ` 前缀(占左侧 2 列,颜色随 thinking/bash mode 联动)。 */
78
80
  enableEditorPrefix: boolean;
79
81
  enableCustomFooter: boolean;
@@ -157,6 +159,7 @@ export const DEFAULT_CONFIG: Config = {
157
159
  enableAgentSummary: true,
158
160
  enableWorkingMessage: true,
159
161
  enableAliases: true,
162
+ enableMarkdownEnhance: true,
160
163
  enableEditorPrefix: true,
161
164
  enableCustomFooter: true,
162
165
  footerTokenRate: true,
@@ -290,6 +293,7 @@ export function normalizeConfig(input: unknown): Config {
290
293
  enableAgentSummary: source.enableAgentSummary !== false,
291
294
  enableWorkingMessage: source.enableWorkingMessage !== false,
292
295
  enableAliases: source.enableAliases !== false,
296
+ enableMarkdownEnhance: source.enableMarkdownEnhance !== false,
293
297
  enableEditorPrefix: (source.enableEditorPrefix ?? source.enableInputPrompt) !== false, // 兼容旧配置键
294
298
  enableCustomFooter: source.enableCustomFooter !== false,
295
299
  footerTokenRate: source.footerTokenRate !== false,
@@ -361,6 +365,7 @@ export function formatConfigStatus(source: Config = config): string {
361
365
  `agentSummary=${source.enableAgentSummary ? "on" : "off"}`,
362
366
  `workingMsg=${source.enableWorkingMessage ? "on" : "off"}`,
363
367
  `aliases=${source.enableAliases ? "on" : "off"}`,
368
+ `markdownEnhance=${source.enableMarkdownEnhance ? "on" : "off"}`,
364
369
  `editorPrefix=${source.enableEditorPrefix ? "on" : "off"}`,
365
370
  `footer=${source.enableCustomFooter ? "on" : "off"}`,
366
371
  `footerTokenRate=${source.footerTokenRate ? "on" : "off"}`,
@@ -656,6 +656,13 @@ export async function showCcstylePanel(
656
656
  "Aliases disabled.",
657
657
  config.enableAliases,
658
658
  );
659
+ const markdownEnhanceToggle = featureToggleSetting(
660
+ "enableMarkdownEnhance",
661
+ "Markdown enhance",
662
+ "Mermaid dialects and circled-number conversion. Next restart applies.",
663
+ "Markdown enhancements off; another extension can own the markdown pass.",
664
+ config.enableMarkdownEnhance,
665
+ );
659
666
  const footerCurrencySetting = {
660
667
  id: "footerCurrency",
661
668
  label: "Cost currency",
@@ -798,6 +805,7 @@ export async function showCcstylePanel(
798
805
  enableAgentSummary: agentSummaryToggle,
799
806
  enableWorkingMessage: workingMessageToggle,
800
807
  enableAliases: aliasesToggle,
808
+ enableMarkdownEnhance: markdownEnhanceToggle,
801
809
  };
802
810
 
803
811
  const onSettingChange = (id: string, value: string) => {
@@ -1049,6 +1057,7 @@ export async function showCcstylePanel(
1049
1057
  agentSummaryToggle.setting,
1050
1058
  workingMessageToggle.setting,
1051
1059
  aliasesToggle.setting,
1060
+ markdownEnhanceToggle.setting,
1052
1061
  ],
1053
1062
  },
1054
1063
  {
@@ -417,9 +417,8 @@ export default function sessionReferenceExtension(pi: ExtensionAPI): void {
417
417
 
418
418
  getAvailableReferences = getReferences;
419
419
  if (ctx.mode === "tui") {
420
- // 预取是 detached 的,必须兜住 rejection,否则 stale 错误会变成
421
- // unhandled rejection 直接终止 Pi。
422
- void getReferences().catch(() => {});
420
+ // 不在这里预取:SessionManager.listAll() 会读完整个会话库,大库要几秒,
421
+ // 而启动并不需要结果。首次 @ 输入由 getSuggestions 触发加载。
423
422
  // Register after other session_start handlers. pi-fff claims every @
424
423
  // prefix, so a provider installed before it would never see session mentions.
425
424
  setTimeout(() => {
@@ -40,10 +40,7 @@ const LEGACY_FIXED_FOOTER_KEYS = [
40
40
  FOOTER_GIT_KEY,
41
41
  ] as const;
42
42
 
43
- const BUILTIN_FOOTER_KEYS = new Set<string>([
44
- ...DEFAULT_FOOTER_LINE1_KEYS,
45
- ...DEFAULT_FOOTER_LINE2_KEYS,
46
- ]);
43
+ const BUILTIN_FOOTER_KEYS = new Set<string>(LEGACY_FIXED_FOOTER_KEYS);
47
44
 
48
45
  export function isBuiltinFooterKey(key: string): boolean {
49
46
  return BUILTIN_FOOTER_KEYS.has(key);
@@ -50,18 +50,37 @@ export class PromptEditor extends CustomEditor {
50
50
  }
51
51
  }
52
52
 
53
- /** 应用/恢复输入框前缀。enableEditorPrefix=false 时不占扩展点。 */
53
+ type EditorFactory = Parameters<ExtensionContext["ui"]["setEditorComponent"]>[0];
54
+
55
+ const promptEditorFactory: EditorFactory = (tui, theme, keybindings) =>
56
+ new PromptEditor(tui, theme, keybindings, { embedWorkingStatus: true });
57
+
58
+ /** 是否正占着插槽;占据前的工厂用于原样还回去。 */
59
+ let active = false;
60
+ let previousEditorFactory: EditorFactory | undefined;
61
+
62
+ /** 撤销本扩展占据的插槽;从未占用就不碰插槽。 */
63
+ function releasePromptEditor(ctx: ExtensionContext): void {
64
+ if (!active) return;
65
+ ctx.ui.setEditorComponent(previousEditorFactory);
66
+ active = false;
67
+ previousEditorFactory = undefined;
68
+ }
69
+
70
+ /** 应用输入框前缀;enableEditorPrefix=false 时只撤自己装的那层。 */
54
71
  export function applyPromptEditor(ctx: ExtensionContext): void {
55
72
  if (!ctx?.hasUI || typeof ctx.ui?.setEditorComponent !== "function") return;
56
73
  try {
57
- if (config.enableEditorPrefix) {
58
- ctx.ui.setEditorComponent(
59
- (tui, theme, keybindings) =>
60
- new PromptEditor(tui, theme, keybindings, { embedWorkingStatus: true }),
61
- );
62
- } else {
63
- ctx.ui.setEditorComponent(undefined);
74
+ if (!config.enableEditorPrefix) {
75
+ releasePromptEditor(ctx);
76
+ return;
77
+ }
78
+ if (!active) {
79
+ // pi 的插槽是硬替换、没有栈,先记住是谁占着,撤销时还回去。
80
+ previousEditorFactory = ctx.ui.getEditorComponent?.();
81
+ active = true;
64
82
  }
83
+ ctx.ui.setEditorComponent(promptEditorFactory);
65
84
  } catch (err) {
66
85
  ctx.ui.notify(
67
86
  `prompt editor error: ${err instanceof Error ? err.message : String(err)}`,
@@ -70,8 +89,8 @@ export function applyPromptEditor(ctx: ExtensionContext): void {
70
89
  }
71
90
  }
72
91
 
73
- /** 恢复 pi 原生编辑器。 */
92
+ /** 恢复本扩展占据前的编辑器;未占用时不动作。 */
74
93
  export function clearPromptEditor(ctx: ExtensionContext): void {
75
94
  if (!ctx?.hasUI || typeof ctx.ui?.setEditorComponent !== "function") return;
76
- ctx.ui.setEditorComponent(undefined);
95
+ releasePromptEditor(ctx);
77
96
  }
@@ -3,8 +3,10 @@
3
3
  *
4
4
  * average:一次用户指令的墙钟平均(工具等待计入分母),显示 `avg`。
5
5
  * live:最近 1 秒的瞬时速率,生成期暂停时钟,显示 `live`;指令结束定格为整段平均。
6
- * token 与 working-message 同源:优先 provider `usage.output`,否则按 delta 增量估算
7
- * (CJK 1 token,其余 chars/4)。provider 值回填到本段消息窗口。
6
+ * token 与 working-message 同源:变大的 provider `usage.output` 覆盖估算,否则按 delta 累加
7
+ * (CJK 1 token,其余 chars/4)。没有变大的 usage 不当作累计值:Anthropic 的 message_start
8
+ * 会给出一个很小的 output_tokens,并在每个 partial 上重复,直到最后的 message_delta。
9
+ * 消息结束时用 message_end 上的 usage 定格本段总量。
8
10
  * Pi 的 turn 是单次 assistant 消息,工具调用结束会开新 turn。token 跨 turn 累加,
9
11
  * 计时与 TTFT 直到下一条用户指令才重置。
10
12
  * TTFT:用户指令开始到第一个内容块(text/thinking/toolcall)开始的毫秒数,
@@ -120,15 +122,29 @@ export function sampleTokenDelta(delta: string, now = Date.now()): void {
120
122
  }
121
123
 
122
124
  /**
123
- * 记录本段 provider `usage.output`。usage 按锚点摊回窗口:
125
+ * 记录本段 provider `usage.output`。变大的 usage 按锚点摊回窗口:
124
126
  * 首次报告从消息起点铺到现在,之后每次把增量摊在上次报告之后。
127
+ * 没有变大的报告直接忽略,避免 message_start 的占位值反复覆盖 delta 累计。
128
+ * `final` 用于消息结束:以本次 output 为本段总量,估算偏高偏低都按它修正。
129
+ * 结束值含未逐字流出的思考 token,它们不属于最近一秒,所以窗口只整体平移,不回填。
125
130
  */
126
- export function recordProviderUsage(output: number, now = Date.now()): void {
131
+ export function recordProviderUsage(output: number, now = Date.now(), final = false): void {
127
132
  if (!runStartTime || output <= 0) return;
133
+ if (final) {
134
+ const shift = output - currentTokens;
135
+ for (const sample of samples) sample.cum += shift;
136
+ countedUsage = output;
137
+ currentTokens = output;
138
+ usageAnchorTime = now;
139
+ usageAnchorTokens = output;
140
+ updateRates(now);
141
+ return;
142
+ }
143
+ if (output <= countedUsage) return;
128
144
  const firstReport = countedUsage === 0;
129
145
  const jump = output - countedUsage;
130
146
  countedUsage = output;
131
- // provider 是权威计数;首次报告以它为准,之后增量接管。
147
+ // 变大的 provider 计数是权威值,覆盖本段估算。
132
148
  currentTokens = output;
133
149
  if (firstReport) {
134
150
  samples = samples.filter((sample) => sample.t < usageAnchorTime);
@@ -49,9 +49,9 @@ export default function (pi: ExtensionAPI): void {
49
49
  return totalTokens();
50
50
  }
51
51
 
52
- function updateProviderUsage(message: StreamMessage): void {
52
+ function updateProviderUsage(message: StreamMessage, final = false): void {
53
53
  const output = outputUsage(message);
54
- if (output > 0) recordProviderUsage(output);
54
+ if (output > 0) recordProviderUsage(output, Date.now(), final);
55
55
  }
56
56
 
57
57
  function buildWorkingMessage(): string {
@@ -171,13 +171,20 @@ export default function (pi: ExtensionAPI): void {
171
171
  // 分段锚点只在 turn_start 重置。这里再重置会把累计 usage.output 当成新的首报。
172
172
  markFirstToken();
173
173
  updateProviderUsage(evt.partial);
174
- } else if (evt.type === "thinking_delta" || evt.type === "text_delta") {
174
+ } else if (
175
+ evt.type === "thinking_delta" ||
176
+ evt.type === "text_delta" ||
177
+ evt.type === "toolcall_delta"
178
+ ) {
179
+ // 工具参数走 toolcall_delta;不计入的话,写长文件这类调用期间 token 一直不涨。
175
180
  if (typeof evt.delta === "string") sampleTokenDelta(evt.delta);
176
181
  updateProviderUsage(evt.partial);
177
182
  } else if (evt.type === "text_end" || evt.type === "thinking_end") {
178
183
  updateProviderUsage(evt.partial);
179
184
  } else if (evt.type === "done") {
180
- updateProviderUsage(evt.message);
185
+ // Pi 目前不会把 done/error 转成 message_update,定格在下面的 message_end 里做。
186
+ // 这两个分支只在宿主直接转发 done/error 时生效;同一个值重复定格不改变结果。
187
+ updateProviderUsage(evt.message, true);
181
188
  } else if (evt.type === "error") {
182
189
  updateProviderUsage(evt.error);
183
190
  } else {
@@ -188,6 +195,18 @@ export default function (pi: ExtensionAPI): void {
188
195
  scheduleRefreshTick();
189
196
  });
190
197
 
198
+ // message_delta 的累计 usage 只出现在 message_end 上,含未逐字流出的思考 token。
199
+ // message_end 在工具执行和 turn_end 之前,先于 carryTokenRate 结转。
200
+ pi.on("message_end", async (event, ctx) => {
201
+ const message = event?.message;
202
+ if (message?.role !== "assistant") return;
203
+ activeCtx = ctx;
204
+ // 出错/中断时 usage 可能还是 message_start 的占位值,只接受变大的值。
205
+ const failed = message.stopReason === "error" || message.stopReason === "aborted";
206
+ updateProviderUsage(message, !failed);
207
+ syncWorkingMessage();
208
+ });
209
+
191
210
  pi.on("tool_execution_start", async () => {
192
211
  pauseTokenRate();
193
212
  });
@@ -35,7 +35,8 @@ export default function (pi: ExtensionAPI): void {
35
35
  });
36
36
 
37
37
  // render stack:thinking controller 直接交给 style 作 query
38
- markdownEnhance(pi);
38
+ // markdownEnhance 单独开关:其他扩展也注册 transformer 时会互相改写输出。
39
+ if (config.enableMarkdownEnhance) markdownEnhance(pi);
39
40
  claudeCodeStyle(pi, undefined, installCompactThinking(pi, getCompactThinkingConfig()));
40
41
 
41
42
  // features
@@ -41,99 +41,6 @@ function collectFence(lines: string[], i: number): { diagram: string; next: numb
41
41
  return null; // 未闭合:放弃转换,保持原文
42
42
  }
43
43
 
44
- // ============================================================================
45
- // GitHub 风格提示框(admonition)
46
- // ============================================================================
47
-
48
- const ADMONITION = /^>\s*\[\s*!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\s*\]\s*(.*)$/i;
49
- const ADMONITION_STYLE: Record<string, { icon: string; label: string }> = {
50
- NOTE: { icon: "💡", label: "NOTE" },
51
- TIP: { icon: "✅", label: "TIP" },
52
- IMPORTANT: { icon: "❗", label: "IMPORTANT" },
53
- WARNING: { icon: "⚠️", label: "WARNING" },
54
- CAUTION: { icon: "⚠️", label: "CAUTION" },
55
- };
56
-
57
- /**
58
- * 把 > [!TYPE] 及其后续 > 行转成带加粗标签的引用块,视觉上成提示框。
59
- * 多行内容用空格合并为一行。返回 null 表示该行不是提示框。
60
- */
61
- function renderAdmonition(lines: string[], i: number): { output: string[]; next: number } | null {
62
- const m = lines[i].match(ADMONITION);
63
- if (!m) return null;
64
- const style = ADMONITION_STYLE[m[1].toUpperCase()];
65
- const body: string[] = [m[2]];
66
- let j = i + 1;
67
- while (j < lines.length && /^>\s?/.test(lines[j]) && !ADMONITION.test(lines[j])) {
68
- body.push(lines[j].replace(/^>\s?/, ""));
69
- j++;
70
- }
71
- while (body.length > 0 && body[body.length - 1].trim() === "") body.pop();
72
- // 内容合并为一行,作为引用块正文
73
- const content = body.join(" ").trim();
74
- // 保留引用块形态(pi 渲染为左侧竖线),标签加粗
75
- return {
76
- output: [`> **${style.icon} ${style.label}**${content ? ` ${content}` : ""}`, ""],
77
- next: j,
78
- };
79
- }
80
-
81
- // ============================================================================
82
- // 裸 URL 转可点击超链接
83
- // ============================================================================
84
-
85
- const URL_RE = /(?<!<)(?<!\]\()https?:\/\/[^\s<>'"|,。;:!?、」』】()【】《》『』「」]+/g;
86
- const TRIM_URL_RE = /[.,;:!?】」』"'》)}]+$/;
87
-
88
- /**
89
- * 去掉 URL 尾部标点;括号按平衡保留(如 Wikipedia 链接含括号、
90
- * IPv6 地址含 [::1]),尾部不成对的 ] 与 ) 会截掉。
91
- */
92
- function trimUrl(url: string): string {
93
- let t = url.replace(TRIM_URL_RE, "");
94
- for (;;) {
95
- if (t.endsWith(")") && (t.match(/\(/g)?.length ?? 0) < (t.match(/\)/g)?.length ?? 0)) {
96
- t = t.slice(0, -1);
97
- } else if (t.endsWith("]") && (t.match(/\[/g)?.length ?? 0) < (t.match(/\]/g)?.length ?? 0)) {
98
- t = t.slice(0, -1);
99
- } else {
100
- break;
101
- }
102
- }
103
- return t;
104
- }
105
-
106
- /**
107
- * 把代码块和行内代码外的裸 URL 转成 markdown 链接。
108
- * 已有的 [text](url) / ![alt](url) / <url> 自动链接用 lookbehind 排除。
109
- */
110
- function linkifyUrls(markdown: string): string {
111
- const lines = markdown.split("\n");
112
- const out: string[] = [];
113
- let fence: MarkdownFence | undefined;
114
- for (const line of lines) {
115
- const scanned = scanMarkdownFence(line, fence);
116
- fence = scanned.fence;
117
- if (scanned.protected) {
118
- out.push(line);
119
- continue;
120
- }
121
- // 行内代码(`...`)按反引号分片,只处理偶数片(代码外)
122
- const parts = line.split("`");
123
- for (let p = 0; p < parts.length; p++) {
124
- if (p % 2 === 0) {
125
- parts[p] = parts[p].replace(URL_RE, (url) => {
126
- const trimmed = trimUrl(url);
127
- if (trimmed.length === 0) return url;
128
- return `[${trimmed}](${trimmed})`;
129
- });
130
- }
131
- }
132
- out.push(parts.join("`"));
133
- }
134
- return out.join("\n");
135
- }
136
-
137
44
  // ============================================================================
138
45
  // 圈数字 → 半角括号
139
46
  // ============================================================================
@@ -231,7 +138,9 @@ function normalizeMultilineLinks(markdown: string): string {
231
138
 
232
139
  export default function (pi: ExtensionAPI): void {
233
140
  // 注意:pi 每个扩展只有一个 markdownTransformer 槽位,多次注册会互相覆盖,
234
- // 所以三个转换合并为一次注册,内部按序链式执行。
141
+ // 所以剩下的转换合并为一次注册,内部按序链式执行。
142
+ // 提示框和裸 URL 不接管:pi 的 marked 已自带裸 URL 链接化(带尾标点回退,
143
+ // 且在链接文本内不再嵌套),提示框交给默认引用块风格。
235
144
  pi.registerMarkdownTransformer((markdown, context) => {
236
145
  const { messageType, isStreaming = false } = context ?? {};
237
146
  // thinking 保持原文;普通回复即使流式中也先关闭跨行链接的空白点击区。
@@ -241,11 +150,7 @@ export default function (pi: ExtensionAPI): void {
241
150
  // 0. 圈数字转半角括号(Nerd Font 补丁字形缺陷规避)
242
151
  markdown = deCircled(markdown);
243
152
  // 1. Mermaid 方言渲染
244
- markdown = renderDiagrams(markdown, context);
245
- // 2. GitHub 风格提示框
246
- markdown = renderAdmonitions(markdown);
247
- // 3. 裸 URL 转超链接
248
- return linkifyUrls(markdown);
153
+ return renderDiagrams(markdown, context);
249
154
  });
250
155
  }
251
156
 
@@ -307,32 +212,3 @@ function renderDiagrams(
307
212
  }
308
213
  return out.join("\n");
309
214
  }
310
-
311
- /** GitHub 风格提示框 → 加粗标签引用块(跳过代码块)。 */
312
- function renderAdmonitions(markdown: string): string {
313
- const lines = markdown.split("\n");
314
- const out: string[] = [];
315
- let fence: MarkdownFence | undefined;
316
- let i = 0;
317
- while (i < lines.length) {
318
- const line = lines[i];
319
- const scanned = scanMarkdownFence(line, fence);
320
- fence = scanned.fence;
321
- if (scanned.protected) {
322
- out.push(line);
323
- i++;
324
- continue;
325
- }
326
- if (/^>\s*\[\s*!/i.test(line)) {
327
- const result = renderAdmonition(lines, i);
328
- if (result) {
329
- out.push(...result.output);
330
- i = result.next;
331
- continue;
332
- }
333
- }
334
- out.push(line);
335
- i++;
336
- }
337
- return out.join("\n");
338
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cc-extensions",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "license": "MIT",
5
5
  "description": "Claude Code-style TUI output with some personal touches and handy utilities.",
6
6
  "type": "module",