@herbertgao/pi-extensions 2026.9.4 → 2026.9.6
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 +3 -15
- package/node_modules/@dietrichgebert/ponytail/.qoder-plugin/plugin.json +1 -1
- package/node_modules/@dietrichgebert/ponytail/README.es.md +33 -2
- package/node_modules/@dietrichgebert/ponytail/README.ko.md +33 -2
- package/node_modules/@dietrichgebert/ponytail/README.md +49 -5
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-icon.png +0 -0
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-dark.svg +4 -0
- package/node_modules/@dietrichgebert/ponytail/assets/retriever-logo-light.svg +4 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/claude-codex-hooks.json +0 -3
- package/node_modules/@dietrichgebert/ponytail/hooks/cursor-hooks.json +17 -0
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-activate.js +22 -3
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-mode-tracker.js +27 -2
- package/node_modules/@dietrichgebert/ponytail/hooks/ponytail-runtime.js +61 -2
- package/node_modules/@dietrichgebert/ponytail/package.json +2 -1
- package/node_modules/@dietrichgebert/ponytail/scripts/cursor-hooks.js +135 -0
- package/node_modules/@dietrichgebert/ponytail/scripts/uninstall.js +21 -4
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +33 -15
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +6 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +23 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +69 -14
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +1 -1
- package/node_modules/@herbertgao/sol-pi/package.json +1 -1
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +0 -5
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +4 -4
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +41 -1
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +5 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/events.ts +5 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/tool/normalize-params.ts +56 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/option-list-view.ts +1 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/tab-bar.ts +1 -2
- package/node_modules/@pi-plugins/fast-mode/README.md +31 -44
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20914 -30
- package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
- package/node_modules/@pi-plugins/fast-mode/package.json +5 -7
- package/node_modules/@tifan/pi-copy-response/README.md +2 -2
- package/node_modules/@tifan/pi-copy-response/package.json +3 -2
- package/node_modules/@tifan/pi-inline-skills/README.md +2 -2
- package/node_modules/@tifan/pi-inline-skills/package.json +3 -2
- package/node_modules/@tifan/pi-mermaid-open/README.md +1 -1
- package/node_modules/@tifan/pi-mermaid-open/package.json +3 -2
- package/node_modules/@tifan/pi-preferred-thinking/package.json +3 -2
- package/node_modules/@tifan/pi-recap/package.json +3 -2
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +78 -0
- package/node_modules/pi-mcp-adapter/README.md +125 -19
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +69 -30
- package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +36 -0
- package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +365 -0
- package/node_modules/pi-mcp-adapter/commands.ts +13 -15
- package/node_modules/pi-mcp-adapter/config.ts +198 -30
- package/node_modules/pi-mcp-adapter/consent-manager.ts +40 -9
- package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +250 -0
- package/node_modules/pi-mcp-adapter/direct-tools.ts +9 -228
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +74 -32
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +1 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +31 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +9 -0
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +362 -0
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +3 -1
- package/node_modules/pi-mcp-adapter/dist/config.js +189 -27
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +7 -16
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +5 -17
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +30 -4
- package/node_modules/pi-mcp-adapter/dist/types.js +26 -0
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +65 -6
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -1
- package/node_modules/pi-mcp-adapter/host-html-template.ts +20 -19
- package/node_modules/pi-mcp-adapter/http-ca.ts +84 -0
- package/node_modules/pi-mcp-adapter/index.ts +827 -164
- package/node_modules/pi-mcp-adapter/init.ts +48 -10
- package/node_modules/pi-mcp-adapter/lazy-loader.ts +7 -0
- package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +113 -0
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +256 -77
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +316 -54
- package/node_modules/pi-mcp-adapter/mcp-code.ts +45 -18
- package/node_modules/pi-mcp-adapter/mcp-install.ts +60 -0
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +70 -6
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +53 -42
- package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +104 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +366 -332
- package/node_modules/pi-mcp-adapter/mcp-references.ts +9 -14
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +3 -1
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +383 -341
- package/node_modules/pi-mcp-adapter/mcp-status.ts +5 -0
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +7 -16
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +61 -3
- package/node_modules/pi-mcp-adapter/oauth.ts +6 -2
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +5 -17
- package/node_modules/pi-mcp-adapter/package.json +13 -3
- package/node_modules/pi-mcp-adapter/prompts.ts +35 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -7
- package/node_modules/pi-mcp-adapter/runtime-owner.ts +16 -1
- package/node_modules/pi-mcp-adapter/sampling-handler.ts +9 -32
- package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +20 -93
- package/node_modules/pi-mcp-adapter/server-manager.ts +227 -40
- package/node_modules/pi-mcp-adapter/session-approvals.ts +187 -0
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +9 -1
- package/node_modules/pi-mcp-adapter/state.ts +10 -1
- package/node_modules/pi-mcp-adapter/tool-approval.ts +10 -22
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +14 -0
- package/node_modules/pi-mcp-adapter/types.ts +57 -4
- package/node_modules/pi-mcp-adapter/ui-server.ts +36 -28
- package/node_modules/pi-mcp-adapter/utils.ts +64 -6
- package/package.json +13 -21
- package/examples/pi-footer.json +0 -275
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +0 -70
- package/node_modules/@czottmann/pi-automode/LICENSE.md +0 -21
- package/node_modules/@czottmann/pi-automode/README.md +0 -215
- package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +0 -39
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +0 -46
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +0 -60
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +0 -6
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +0 -428
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +0 -171
- package/node_modules/@czottmann/pi-automode/docs/defaults.md +0 -178
- package/node_modules/@czottmann/pi-automode/docs/diagnostics.md +0 -90
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +0 -160
- package/node_modules/@czottmann/pi-automode/examples/automode.local.json +0 -44
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +0 -692
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +0 -852
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +0 -904
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +0 -228
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +0 -954
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +0 -429
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/log.ts +0 -173
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model-selector.ts +0 -113
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/model.ts +0 -13
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +0 -297
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +0 -623
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/state.ts +0 -102
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/transcript.ts +0 -236
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/types.ts +0 -205
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/utils.ts +0 -54
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +0 -26
- package/node_modules/@czottmann/pi-automode/package.json +0 -61
- package/node_modules/@czottmann/pi-automode/skills/automode-diagnostics/SKILL.md +0 -63
package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts
CHANGED
|
@@ -50,7 +50,7 @@ interface DiffTheme {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
type DiffLineKind = "add" | "remove" | "context";
|
|
53
|
-
type DiffEntryKind = "line" | "meta" | "hunk" | "file";
|
|
53
|
+
type DiffEntryKind = "line" | "omission" | "meta" | "hunk" | "file";
|
|
54
54
|
|
|
55
55
|
export interface DiffLineEntry {
|
|
56
56
|
kind: "line";
|
|
@@ -64,13 +64,19 @@ export interface DiffLineEntry {
|
|
|
64
64
|
hunkIndex: number;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
export interface DiffOmissionEntry {
|
|
68
|
+
kind: "omission";
|
|
69
|
+
raw: string;
|
|
70
|
+
hunkIndex: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
67
73
|
interface DiffMetaEntry {
|
|
68
|
-
kind: Exclude<DiffEntryKind, "line">;
|
|
74
|
+
kind: Exclude<DiffEntryKind, "line" | "omission">;
|
|
69
75
|
raw: string;
|
|
70
76
|
hunkIndex: number;
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
type ParsedDiffEntry = DiffLineEntry | DiffMetaEntry;
|
|
79
|
+
type ParsedDiffEntry = DiffLineEntry | DiffOmissionEntry | DiffMetaEntry;
|
|
74
80
|
|
|
75
81
|
export interface ParsedDiff {
|
|
76
82
|
entries: ParsedDiffEntry[];
|
|
@@ -94,6 +100,7 @@ interface RenderedRow {
|
|
|
94
100
|
interface SplitDiffRow {
|
|
95
101
|
left?: DiffLineEntry;
|
|
96
102
|
right?: DiffLineEntry;
|
|
103
|
+
omission?: DiffOmissionEntry;
|
|
97
104
|
meta?: DiffMetaEntry;
|
|
98
105
|
hunkIndex: number | null;
|
|
99
106
|
}
|
|
@@ -544,7 +551,7 @@ export function parseDiff(diffText: string): ParsedDiff {
|
|
|
544
551
|
|
|
545
552
|
// Pi 用空白行号填充省略上下文;它不是源码行,也不推进行号游标。
|
|
546
553
|
if (!hasHunkHeader && PI_OMISSION_LINE_PATTERN.test(rawLine)) {
|
|
547
|
-
entries.push(
|
|
554
|
+
entries.push({ kind: "omission", raw: rawLine, hunkIndex });
|
|
548
555
|
continue;
|
|
549
556
|
}
|
|
550
557
|
|
|
@@ -816,6 +823,12 @@ function buildSplitRows(entries: ParsedDiffEntry[]): SplitDiffRow[] {
|
|
|
816
823
|
break;
|
|
817
824
|
}
|
|
818
825
|
|
|
826
|
+
if (entry.kind === "omission") {
|
|
827
|
+
rows.push({ omission: entry, hunkIndex: entry.hunkIndex || null });
|
|
828
|
+
index++;
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
|
|
819
832
|
if (entry.kind !== "line") {
|
|
820
833
|
rows.push({ meta: entry, hunkIndex: entry.hunkIndex || null });
|
|
821
834
|
index++;
|
|
@@ -1799,8 +1812,44 @@ interface DiffRenderContext {
|
|
|
1799
1812
|
showHashlineAnchors: boolean;
|
|
1800
1813
|
}
|
|
1801
1814
|
|
|
1802
|
-
|
|
1815
|
+
const OMISSION_GLYPH = "⋮";
|
|
1816
|
+
|
|
1817
|
+
function createOmissionRenderLine(entry: DiffOmissionEntry, compact = false): DiffLineEntry {
|
|
1818
|
+
return {
|
|
1819
|
+
kind: "line",
|
|
1820
|
+
lineKind: "context",
|
|
1821
|
+
oldLineNumber: null,
|
|
1822
|
+
newLineNumber: null,
|
|
1823
|
+
fallbackLineNumber: compact ? "" : OMISSION_GLYPH,
|
|
1824
|
+
content: compact ? OMISSION_GLYPH : "",
|
|
1825
|
+
raw: entry.raw,
|
|
1826
|
+
hunkIndex: entry.hunkIndex,
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
function materializeOmissionEntries(
|
|
1803
1831
|
entries: ParsedDiffEntry[],
|
|
1832
|
+
compact = false,
|
|
1833
|
+
): (DiffLineEntry | DiffMetaEntry)[] {
|
|
1834
|
+
return entries.map((entry) =>
|
|
1835
|
+
entry.kind === "omission" ? createOmissionRenderLine(entry, compact) : entry,
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
function omitTerminalOmissions(entries: ParsedDiffEntry[]): ParsedDiffEntry[] {
|
|
1840
|
+
let lastLineIndex = -1;
|
|
1841
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
1842
|
+
if (entries[index]?.kind === "line") {
|
|
1843
|
+
lastLineIndex = index;
|
|
1844
|
+
break;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
return entries.filter((entry, index) => entry.kind !== "omission" || index < lastLineIndex);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
function processDiffEntries(
|
|
1852
|
+
entries: (DiffLineEntry | DiffMetaEntry)[],
|
|
1804
1853
|
ctx: DiffRenderContext,
|
|
1805
1854
|
processLine: (entry: DiffLineEntry) => string[],
|
|
1806
1855
|
): RenderedRow[] {
|
|
@@ -1821,7 +1870,7 @@ function renderUnified(
|
|
|
1821
1870
|
ctx: DiffRenderContext,
|
|
1822
1871
|
lineNumberWidth: number,
|
|
1823
1872
|
): RenderedRow[] {
|
|
1824
|
-
return processDiffEntries(entries, ctx, (entry) => {
|
|
1873
|
+
return processDiffEntries(materializeOmissionEntries(entries), ctx, (entry) => {
|
|
1825
1874
|
const lineNumber =
|
|
1826
1875
|
entry.lineKind === "add"
|
|
1827
1876
|
? formatLineNumberLabel(
|
|
@@ -1871,6 +1920,10 @@ function toUnifiedFallbackRows(
|
|
|
1871
1920
|
): RenderedRow[] {
|
|
1872
1921
|
const flattened: ParsedDiffEntry[] = [];
|
|
1873
1922
|
for (const row of rows) {
|
|
1923
|
+
if (row.omission) {
|
|
1924
|
+
flattened.push(row.omission);
|
|
1925
|
+
continue;
|
|
1926
|
+
}
|
|
1874
1927
|
if (row.meta) {
|
|
1875
1928
|
flattened.push(row.meta);
|
|
1876
1929
|
continue;
|
|
@@ -1886,7 +1939,7 @@ function toUnifiedFallbackRows(
|
|
|
1886
1939
|
}
|
|
1887
1940
|
|
|
1888
1941
|
function renderCompact(entries: ParsedDiffEntry[], ctx: DiffRenderContext): RenderedRow[] {
|
|
1889
|
-
return processDiffEntries(entries, ctx, (entry) => {
|
|
1942
|
+
return processDiffEntries(materializeOmissionEntries(entries, true), ctx, (entry) => {
|
|
1890
1943
|
const codeText = normalizeCodeWhitespace(
|
|
1891
1944
|
getCompactLineRenderContent(entry, ctx.showHashlineAnchors),
|
|
1892
1945
|
);
|
|
@@ -2105,8 +2158,9 @@ function renderSplit(
|
|
|
2105
2158
|
continue;
|
|
2106
2159
|
}
|
|
2107
2160
|
|
|
2161
|
+
const omissionLine = row.omission ? createOmissionRenderLine(row.omission) : undefined;
|
|
2108
2162
|
const leftCells = renderSplitCell(
|
|
2109
|
-
row.left,
|
|
2163
|
+
omissionLine ?? row.left,
|
|
2110
2164
|
"left",
|
|
2111
2165
|
leftWidth,
|
|
2112
2166
|
splitLineNumberWidth,
|
|
@@ -2120,7 +2174,7 @@ function renderSplit(
|
|
|
2120
2174
|
showHashlineAnchors,
|
|
2121
2175
|
);
|
|
2122
2176
|
const rightCells = renderSplitCell(
|
|
2123
|
-
row.right,
|
|
2177
|
+
omissionLine ?? row.right,
|
|
2124
2178
|
"right",
|
|
2125
2179
|
rightWidth,
|
|
2126
2180
|
splitLineNumberWidth,
|
|
@@ -2575,18 +2629,19 @@ export function renderEditDiffResult(
|
|
|
2575
2629
|
return new Text(theme.fg("muted", "↳ no diff data"), 0, 0);
|
|
2576
2630
|
}
|
|
2577
2631
|
|
|
2578
|
-
const
|
|
2632
|
+
const renderEntries = omitTerminalOmissions(parsed.entries);
|
|
2633
|
+
const splitRows = buildSplitRows(renderEntries);
|
|
2579
2634
|
const showHashlineAnchors =
|
|
2580
2635
|
options.expanded === true &&
|
|
2581
|
-
|
|
2582
|
-
const lineNumberWidth = getLineNumberWidth(
|
|
2636
|
+
renderEntries.some((entry) => entry.kind === "line" && !!entry.hashlineAnchorContent);
|
|
2637
|
+
const lineNumberWidth = getLineNumberWidth(renderEntries, showHashlineAnchors);
|
|
2583
2638
|
const palette = resolveDiffPalette(theme);
|
|
2584
2639
|
// Rich diffs use ccstyle's self shell. Keep the panel transparent so the
|
|
2585
2640
|
// separator cannot leak toolSuccessBg across the entire new column.
|
|
2586
2641
|
const containerBgAnsi = undefined;
|
|
2587
2642
|
const language = resolveLanguageFromPath(options.filePath);
|
|
2588
2643
|
const cache = createDiffRenderCache();
|
|
2589
|
-
const highlightLine = createCodeLineHighlighter(language, theme,
|
|
2644
|
+
const highlightLine = createCodeLineHighlighter(language, theme, renderEntries, () => {
|
|
2590
2645
|
cache.invalidate();
|
|
2591
2646
|
options.invalidate?.();
|
|
2592
2647
|
});
|
|
@@ -2635,7 +2690,7 @@ export function renderEditDiffResult(
|
|
|
2635
2690
|
const processBudget = resolveDiffProcessBudget(displayLimit, wordWrap);
|
|
2636
2691
|
// Only highlight/render a prefix that can fill the display limit; full-diff
|
|
2637
2692
|
// LCS + syntax highlight on thousands of hidden lines is pure waste when collapsed.
|
|
2638
|
-
const entryBudget = takeEntriesForLineBudget(
|
|
2693
|
+
const entryBudget = takeEntriesForLineBudget(renderEntries, processBudget);
|
|
2639
2694
|
const splitBudget = takeSplitRowsForBudget(splitRows, processBudget);
|
|
2640
2695
|
const inlineHighlights = buildInlineHighlightMap(splitBudget.rows);
|
|
2641
2696
|
const renderCtx: DiffRenderContext = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-cc-extensions",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
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",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
},
|
|
70
70
|
"x-upstream": {
|
|
71
71
|
"package": "pi-cc-extensions",
|
|
72
|
-
"version": "0.8.
|
|
72
|
+
"version": "0.8.71",
|
|
73
73
|
"repository": "https://github.com/minuque/pi-cc-extensions",
|
|
74
|
-
"commit": "
|
|
74
|
+
"commit": "e43e0041b59f5d7f03be9b9d103a5f9e954e4c11"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -21,7 +21,7 @@ Action Fusion decodes `file://` targets with Node's `fileURLToPath()` before res
|
|
|
21
21
|
|
|
22
22
|
The queue covers only fused operations registered by this SoL-Pi instance. External processes, direct built-in-tool calls outside the replacement, and unrelated extensions are not globally locked. SoL-Pi hashes the target immediately before launching `then_run` and skips the command if it observes an intervening content change.
|
|
23
23
|
|
|
24
|
-
When another extension already owns `write`, Action Fusion leaves that tool in place and only registers its `edit` replacement.
|
|
24
|
+
When another extension already owns `write`, Action Fusion leaves that tool in place and only registers its `edit` replacement.
|
|
25
25
|
|
|
26
26
|
## ObservationPack
|
|
27
27
|
|
|
@@ -80,11 +80,6 @@ export function createActionFusionExtension(options: ActionFusionOptions = {}):
|
|
|
80
80
|
const baseWrite = memoizeByCwd((cwd: string) => createWriteToolDefinition(cwd, options.writeOptions));
|
|
81
81
|
|
|
82
82
|
return (pi: ExtensionAPI) => {
|
|
83
|
-
// then_run executes Bash inside the mutation tool, so it cannot pass through
|
|
84
|
-
// Pi's public tool_call permission handlers. Leave it to automode instead of
|
|
85
|
-
// creating a nested shell escape hatch.
|
|
86
|
-
if (hasExternalToolOwner(pi, "automode_inspect")) return;
|
|
87
|
-
|
|
88
83
|
const editTemplate = baseEdit(process.cwd());
|
|
89
84
|
const writeTemplate = baseWrite(process.cwd());
|
|
90
85
|
|
package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts
CHANGED
|
@@ -218,9 +218,8 @@ export function decideCompaction(input: {
|
|
|
218
218
|
carriedDebtTokens: input.carriedDebtTokens,
|
|
219
219
|
cacheDebtRepaymentTokens: input.cacheDebtRepaymentTokens,
|
|
220
220
|
compact,
|
|
221
|
-
reason:
|
|
222
|
-
?
|
|
223
|
-
: windowProtection
|
|
221
|
+
reason: compressible
|
|
222
|
+
? windowProtection
|
|
224
223
|
? "window_protection"
|
|
225
224
|
: economic
|
|
226
225
|
? "economic"
|
|
@@ -232,6 +231,7 @@ export function decideCompaction(input: {
|
|
|
232
231
|
? "deferred_subsequent_margin"
|
|
233
232
|
: !firstCompaction && baseEconomic && !carriedDebtGateOpen
|
|
234
233
|
? "deferred_carried_debt"
|
|
235
|
-
: "deferred_economic"
|
|
234
|
+
: "deferred_economic"
|
|
235
|
+
: "non_positive_saving",
|
|
236
236
|
};
|
|
237
237
|
}
|
package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
|
-
import type { AgentMessage, AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
5
|
+
import type { AgentMessage, AgentToolResult, ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
6
6
|
import {
|
|
7
7
|
buildSessionContext,
|
|
8
8
|
estimateTokens,
|
|
9
9
|
findCutPoint,
|
|
10
10
|
sessionEntryToContextMessages,
|
|
11
|
+
type ExtensionAPI,
|
|
11
12
|
type ExtensionContext,
|
|
12
13
|
type ExtensionFactory,
|
|
13
14
|
type SessionEntry,
|
|
@@ -165,6 +166,37 @@ function validPositiveInteger(value: unknown): value is number {
|
|
|
165
166
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
166
167
|
}
|
|
167
168
|
|
|
169
|
+
type CompactionThinkingOverride = {
|
|
170
|
+
readonly previous: ThinkingLevel;
|
|
171
|
+
readonly applied: ThinkingLevel;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Native summaries share their output cap with reasoning; reserve the cap for summary text.
|
|
175
|
+
function lowerCompactionThinking(
|
|
176
|
+
pi: ExtensionAPI,
|
|
177
|
+
reasoning: boolean,
|
|
178
|
+
): CompactionThinkingOverride | undefined {
|
|
179
|
+
if (!reasoning) return;
|
|
180
|
+
try {
|
|
181
|
+
const previous = pi.getThinkingLevel();
|
|
182
|
+
if (previous !== "high" && previous !== "xhigh" && previous !== "max") return;
|
|
183
|
+
pi.setThinkingLevel("medium");
|
|
184
|
+
const applied = pi.getThinkingLevel();
|
|
185
|
+
return applied === previous ? undefined : { previous, applied };
|
|
186
|
+
} catch {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function restoreCompactionThinking(pi: ExtensionAPI, override: CompactionThinkingOverride | undefined): void {
|
|
192
|
+
if (!override) return;
|
|
193
|
+
try {
|
|
194
|
+
if (pi.getThinkingLevel() === override.applied) pi.setThinkingLevel(override.previous);
|
|
195
|
+
} catch {
|
|
196
|
+
// A compaction result must not be masked by a best-effort state restore.
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
168
200
|
function releaseParentContinuation(continuation: PendingContinuation | undefined): void {
|
|
169
201
|
if (continuation) setTimeout(continuation.resolve, 0);
|
|
170
202
|
}
|
|
@@ -182,6 +214,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
|
|
|
182
214
|
let activeDebt: CacheDebt | undefined;
|
|
183
215
|
let nextContinuation: PendingContinuation | undefined;
|
|
184
216
|
let compactionInFlight = false;
|
|
217
|
+
let compactionThinkingOverride: CompactionThinkingOverride | undefined;
|
|
185
218
|
|
|
186
219
|
const releaseContinuation = (): void => {
|
|
187
220
|
const continuation = nextContinuation;
|
|
@@ -349,6 +382,7 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
|
|
|
349
382
|
let compactionError: Error | undefined;
|
|
350
383
|
try {
|
|
351
384
|
compactionInFlight = true;
|
|
385
|
+
compactionThinkingOverride = lowerCompactionThinking(pi, context.model?.reasoning === true);
|
|
352
386
|
await new Promise<void>((resolve) => {
|
|
353
387
|
let finished = false;
|
|
354
388
|
const finish = (): void => {
|
|
@@ -382,6 +416,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
|
|
|
382
416
|
},
|
|
383
417
|
});
|
|
384
418
|
});
|
|
419
|
+
restoreCompactionThinking(pi, compactionThinkingOverride);
|
|
420
|
+
compactionThinkingOverride = undefined;
|
|
385
421
|
compactionInFlight = false;
|
|
386
422
|
if (
|
|
387
423
|
compactionError &&
|
|
@@ -422,6 +458,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
|
|
|
422
458
|
await continuation.promise;
|
|
423
459
|
}
|
|
424
460
|
} finally {
|
|
461
|
+
restoreCompactionThinking(pi, compactionThinkingOverride);
|
|
462
|
+
compactionThinkingOverride = undefined;
|
|
425
463
|
compactionInFlight = false;
|
|
426
464
|
activeDebt = undefined;
|
|
427
465
|
releaseParentContinuation(parentContinuation);
|
|
@@ -445,6 +483,8 @@ export function createOnlineContextCompactExtension(options: OnlineContextCompac
|
|
|
445
483
|
});
|
|
446
484
|
|
|
447
485
|
pi.on("session_shutdown", () => {
|
|
486
|
+
restoreCompactionThinking(pi, compactionThinkingOverride);
|
|
487
|
+
compactionThinkingOverride = undefined;
|
|
448
488
|
releaseContinuation();
|
|
449
489
|
pendingBoundary = undefined;
|
|
450
490
|
selected = undefined;
|
package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts
CHANGED
|
@@ -180,7 +180,9 @@ export function recordCompaction(
|
|
|
180
180
|
return {
|
|
181
181
|
...state,
|
|
182
182
|
epoch: state.epoch + 1,
|
|
183
|
-
plan
|
|
183
|
+
// Keep the plan so the post-compaction rebuild does not reclassify
|
|
184
|
+
// already-completed steps as a new boundary.
|
|
185
|
+
plan: [...state.plan],
|
|
184
186
|
pendingProgress: [],
|
|
185
187
|
lastContextTokens: null,
|
|
186
188
|
positiveContextDeltaTotal: 0,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { type DialogUI, hasDialogUI, runRpcQuestionnaire } from "./rpc-fallback.js";
|
|
19
19
|
import { displayLabel, t } from "./state/i18n-bridge.js";
|
|
20
20
|
import { sentinelsToAppend } from "./state/row-intent.js";
|
|
21
|
+
import { normalizeQuestionParams } from "./tool/normalize-params.js";
|
|
21
22
|
import { buildQuestionnaireResponse, buildToolResult } from "./tool/response-envelope.js";
|
|
22
23
|
import {
|
|
23
24
|
MAX_OPTIONS,
|
|
@@ -310,7 +311,10 @@ export function registerAskUserQuestionTool(pi: ExtensionAPI): void {
|
|
|
310
311
|
parameters: QuestionParamsSchema,
|
|
311
312
|
|
|
312
313
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
313
|
-
|
|
314
|
+
// Line-terminator normalization runs once here, ahead of validation, so
|
|
315
|
+
// every downstream consumer — validator, TUI, RPC walker, envelope, prompt
|
|
316
|
+
// event — sees the same clean text (#192).
|
|
317
|
+
const typed = normalizeQuestionParams(params as unknown as QuestionParams);
|
|
314
318
|
if (!ctx.hasUI) return rejectWithoutUi();
|
|
315
319
|
|
|
316
320
|
const validation = validateQuestionnaire(typed);
|
|
@@ -38,7 +38,11 @@ export interface AskUserBlockedEventPayload {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface AskUserPromptQuestion {
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* The full question text as the agent authored it, with line terminators
|
|
43
|
+
* normalized at tool entry (`\r\n` → `\n`, lone `\r` removed — #192). The
|
|
44
|
+
* same normalization applies to `header` and every option field below.
|
|
45
|
+
*/
|
|
42
46
|
question: string;
|
|
43
47
|
/** The short chip/tag shown next to the question. */
|
|
44
48
|
header: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juicesharp/rpiv-ask-user-question",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.1",
|
|
4
4
|
"description": "Pi extension. A structured questionnaire the model can put to you when it would otherwise guess, with typed options instead of free-form replies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"state/state-reducer.ts",
|
|
57
57
|
"state/state.ts",
|
|
58
58
|
"tool/format-answer.ts",
|
|
59
|
+
"tool/normalize-params.ts",
|
|
59
60
|
"tool/response-envelope.ts",
|
|
60
61
|
"tool/types.ts",
|
|
61
62
|
"tool/validate-questionnaire.ts",
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
}
|
|
95
96
|
},
|
|
96
97
|
"dependencies": {
|
|
97
|
-
"@juicesharp/rpiv-config": "^2.
|
|
98
|
+
"@juicesharp/rpiv-config": "^2.10.1",
|
|
98
99
|
"typebox": "^1.1.24"
|
|
99
100
|
}
|
|
100
101
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { QuestionParams } from "./types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalize line terminators in one model-supplied text field (#192).
|
|
5
|
+
*
|
|
6
|
+
* Some models serialize a bare carriage return inside tool-call string
|
|
7
|
+
* arguments at token boundaries where the text was meant to be contiguous
|
|
8
|
+
* (`GEMBA\r_LOG\r_FILE` for `GEMBA_LOG_FILE`). A raw CR is a cursor-control
|
|
9
|
+
* byte, not text: pi-tui ≤0.80 writes it straight into the row, so the
|
|
10
|
+
* terminal returns to column 0 and later text overwrites the pointer and
|
|
11
|
+
* number; pi-tui ≥0.84 splits `wrapTextWithAnsi` on `\r`, so one option
|
|
12
|
+
* fragments into stacked rows. Both symptoms have the same fix at our
|
|
13
|
+
* boundary:
|
|
14
|
+
*
|
|
15
|
+
* - `\r\n` → `\n` keeps genuine multi-line content (preview markdown) intact.
|
|
16
|
+
* - a lone `\r` is deleted — never a space (phantom gaps inside words) and
|
|
17
|
+
* never `\n` (reintroduces the vertical fragmentation). This matches
|
|
18
|
+
* pi-coding-agent's own display normalization (`normalizeDisplayText`).
|
|
19
|
+
*/
|
|
20
|
+
export function normalizeLineTerminators(text: string): string {
|
|
21
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Copy `obj`, normalizing the listed keys that hold strings. Keys absent from
|
|
26
|
+
* `obj` (e.g. an omitted `preview`) stay absent so `"preview" in option`
|
|
27
|
+
* checks and `hasPreview` derivations are unchanged.
|
|
28
|
+
*/
|
|
29
|
+
function normalizeStringFields<T extends object>(obj: T, keys: readonly (keyof T)[]): T {
|
|
30
|
+
const out = { ...obj };
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
const value = obj[key];
|
|
33
|
+
if (typeof value === "string") out[key] = normalizeLineTerminators(value) as T[typeof key];
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Return a copy of the tool params with every user-facing string field
|
|
40
|
+
* (`question`, `header`, `options[].label`, `options[].description`,
|
|
41
|
+
* `options[].preview`) line-terminator-normalized. Runs once at tool entry,
|
|
42
|
+
* BEFORE `validateQuestionnaire`, so the reserved-label and duplicate-label
|
|
43
|
+
* guards compare the text the user will actually see (`"Other\r"` must not
|
|
44
|
+
* slip past `reserved_label`), and so the TUI, the RPC dialog walker, the
|
|
45
|
+
* envelope echo, and the `rpiv:ask-user:prompt` payload all carry the same
|
|
46
|
+
* clean text. Pure: the input object is never mutated.
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeQuestionParams(params: QuestionParams): QuestionParams {
|
|
49
|
+
return {
|
|
50
|
+
...params,
|
|
51
|
+
questions: params.questions.map((q) => ({
|
|
52
|
+
...normalizeStringFields(q, ["question", "header"]),
|
|
53
|
+
options: q.options.map((o) => normalizeStringFields(o, ["label", "description", "preview"])),
|
|
54
|
+
})),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -13,7 +13,7 @@ export interface OptionListViewConfig {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Per-tick projection of OptionListView state.
|
|
16
|
+
* Per-tick projection of OptionListView state. `inputBuffer`
|
|
17
17
|
* is part of the props bag — the session-owned `inlineInput` (a headless
|
|
18
18
|
* `pi-tui` Editor instance) supplies its current `getText()` here per tick.
|
|
19
19
|
* `OptionListView` is purely props-driven; the imperative buffer surface and
|
|
@@ -6,8 +6,7 @@ import type { StatefulView } from "../stateful-view.js";
|
|
|
6
6
|
* Per-tick projection of TabBar state. The selector
|
|
7
7
|
* (`selectTabBarProps`) hoists every render-time derivation
|
|
8
8
|
* (`allAnswered`, `answered`, `isActive`, `submitActive`) into props so
|
|
9
|
-
* `render()` is pure styling.
|
|
10
|
-
* snowflake and the inline `+ 1` magic at `props-adapter.ts:127`.
|
|
9
|
+
* `render()` is pure styling.
|
|
11
10
|
*/
|
|
12
11
|
export interface TabBarProps {
|
|
13
12
|
/** One per author-defined question, in order. */
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
# `@pi-plugins/fast-mode`
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
higher token cost.
|
|
6
|
-
|
|
7
|
-
Fast mode is a per-model opt-in: you decide which `provider/model-id` pairs it
|
|
8
|
-
applies to, and a single session toggle turns it on and off. Requests for any other
|
|
9
|
-
model are left untouched.
|
|
3
|
+
Request priority inference for selected models in
|
|
4
|
+
[pi](https://github.com/earendil-works/pi) with a session toggle.
|
|
10
5
|
|
|
11
6
|
## Install
|
|
12
7
|
|
|
@@ -14,49 +9,45 @@ model are left untouched.
|
|
|
14
9
|
pi install npm:@pi-plugins/fast-mode
|
|
15
10
|
```
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
To try it for one session without changing your settings:
|
|
18
13
|
|
|
19
14
|
```bash
|
|
20
15
|
pi -e npm:@pi-plugins/fast-mode
|
|
21
16
|
```
|
|
22
17
|
|
|
23
|
-
For local development, load it straight from this directory:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
pi -e ./plugins/fast-mode
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Supported providers
|
|
30
|
-
|
|
31
|
-
| Provider | Mechanism |
|
|
32
|
-
| -------------- | ---------------------------------- |
|
|
33
|
-
| `openai` | `service_tier: "priority"` payload |
|
|
34
|
-
| `openai-codex` | `service_tier: "priority"` payload |
|
|
35
|
-
|
|
36
18
|
## Usage
|
|
37
19
|
|
|
38
|
-
|
|
39
|
-
/fast # toggle fast mode for this session
|
|
40
|
-
/fast on # enable
|
|
41
|
-
/fast off # disable
|
|
42
|
-
/fast status # show the current state and why it is (in)active
|
|
43
|
-
```
|
|
20
|
+
Use `/fast` to control fast mode for the current session:
|
|
44
21
|
|
|
45
|
-
|
|
22
|
+
| Command | Action |
|
|
23
|
+
| -------------- | ---------------------------------------------------------------------------- |
|
|
24
|
+
| `/fast` | Toggle fast mode. |
|
|
25
|
+
| `/fast on` | Enable fast mode. |
|
|
26
|
+
| `/fast off` | Disable fast mode. |
|
|
27
|
+
| `/fast status` | Show the current state and explain whether it applies to the selected model. |
|
|
28
|
+
|
|
29
|
+
To start a session with fast mode enabled:
|
|
46
30
|
|
|
47
31
|
```bash
|
|
48
32
|
pi --fast
|
|
49
33
|
```
|
|
50
34
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
35
|
+
Fast mode applies only to models listed in the configuration. Other models are left
|
|
36
|
+
unchanged. A `[fast mode]` indicator appears above the editor while active.
|
|
37
|
+
|
|
38
|
+
## Supported providers
|
|
39
|
+
|
|
40
|
+
| Provider | Pi provider |
|
|
41
|
+
| ------------ | -------------- |
|
|
42
|
+
| OpenAI | `openai` |
|
|
43
|
+
| OpenAI Codex | `openai-codex` |
|
|
44
|
+
|
|
45
|
+
Priority availability depends on the provider and model.
|
|
55
46
|
|
|
56
47
|
## Configuration
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
`~/.pi/agent/extensions/fast-mode.json
|
|
49
|
+
Optionally create `<agent-dir>/extensions/fast-mode.json`, typically
|
|
50
|
+
`~/.pi/agent/extensions/fast-mode.json`. The defaults are:
|
|
60
51
|
|
|
61
52
|
```json
|
|
62
53
|
{
|
|
@@ -79,16 +70,12 @@ Optional config file at `<agent-dir>/extensions/fast-mode.json` (typically
|
|
|
79
70
|
}
|
|
80
71
|
```
|
|
81
72
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- `showStatus`: show the `[fast mode]` indicator above the editor while active.
|
|
73
|
+
| Setting | Description |
|
|
74
|
+
| ------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `enabled` | Enable fast mode at session start. `/fast` changes only the current session and does not write to the file. |
|
|
76
|
+
| `models` | The exact `provider/model-id` pairs fast mode applies to. |
|
|
77
|
+
| `showStatus` | Show the status indicator while fast mode is active. |
|
|
88
78
|
|
|
89
79
|
## Notes
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
provider's pricing before leaving it enabled.
|
|
93
|
-
- If another extension already set a `service_tier` on the payload, this extension
|
|
94
|
-
leaves it alone.
|
|
81
|
+
Priority inference can cost more. Check your provider's pricing before enabling it.
|