pi-repoprompt-mcp 0.2.5 → 0.2.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.md
CHANGED
|
@@ -4,7 +4,7 @@ A token-efficient RepoPrompt MCP integration for Pi.
|
|
|
4
4
|
|
|
5
5
|
Exposes a single `rp` tool (RepoPrompt MCP proxy) plus `/rp …` commands, with:
|
|
6
6
|
- window/tab binding (auto-detect by `cwd`, optional persistence)
|
|
7
|
-
- output rendering (syntax + diff highlighting)
|
|
7
|
+
- output rendering (syntax + diff highlighting; uses `delta` when installed, honoring the user's global git/delta color config, with graceful fallback)
|
|
8
8
|
- safety guardrails (deletes blocked unless explicitly allowed; optional edit confirmation)
|
|
9
9
|
- optional [Gurpartap/pi-readcache](https://github.com/Gurpartap/pi-readcache)-like caching for RepoPrompt `read_file` results (unchanged markers + diffs) to save on tokens
|
|
10
10
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// First-class RepoPrompt integration with:
|
|
4
4
|
// - Auto-detection of matching windows based on cwd
|
|
5
5
|
// - Syntax highlighting for code blocks
|
|
6
|
-
// -
|
|
6
|
+
// - Delta-powered diff highlighting (with graceful fallback)
|
|
7
7
|
// - Safety guards for destructive operations
|
|
8
8
|
// - Persistent window binding across sessions
|
|
9
9
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// render.ts - Syntax highlighting and diff rendering for RepoPrompt output
|
|
2
2
|
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
|
|
3
5
|
import { highlightCode, type Theme } from "@mariozechner/pi-coding-agent";
|
|
4
6
|
import * as Diff from "diff";
|
|
5
7
|
|
|
@@ -73,6 +75,92 @@ export function parseFencedBlocks(text: string): FencedBlock[] {
|
|
|
73
75
|
return blocks;
|
|
74
76
|
}
|
|
75
77
|
|
|
78
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
// Delta Diff Rendering
|
|
80
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
const ANSI_ESCAPE_RE = /\x1b\[[0-9;]*m/g;
|
|
83
|
+
const DELTA_TIMEOUT_MS = 5000;
|
|
84
|
+
const DELTA_MAX_BUFFER = 8 * 1024 * 1024;
|
|
85
|
+
const DELTA_CACHE_MAX_ENTRIES = 200;
|
|
86
|
+
|
|
87
|
+
let deltaAvailable: boolean | null = null;
|
|
88
|
+
const deltaDiffCache = new Map<string, string | null>();
|
|
89
|
+
|
|
90
|
+
function isDeltaInstalled(): boolean {
|
|
91
|
+
if (deltaAvailable !== null) {
|
|
92
|
+
return deltaAvailable;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const check = spawnSync("delta", ["--version"], {
|
|
96
|
+
stdio: "ignore",
|
|
97
|
+
timeout: 1000,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
deltaAvailable = !check.error && check.status === 0;
|
|
101
|
+
return deltaAvailable;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function runDelta(diffText: string): string | null {
|
|
105
|
+
const result = spawnSync("delta", ["--color-only", "--paging=never"], {
|
|
106
|
+
encoding: "utf-8",
|
|
107
|
+
input: diffText,
|
|
108
|
+
timeout: DELTA_TIMEOUT_MS,
|
|
109
|
+
maxBuffer: DELTA_MAX_BUFFER,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (result.error || result.status !== 0) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return typeof result.stdout === "string" ? result.stdout : null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function stripSyntheticHeader(deltaOutput: string): string {
|
|
120
|
+
const outputLines = deltaOutput.split("\n");
|
|
121
|
+
const bodyStart = outputLines.findIndex((line) => line.replace(ANSI_ESCAPE_RE, "").startsWith("@@"));
|
|
122
|
+
|
|
123
|
+
if (bodyStart >= 0) {
|
|
124
|
+
return outputLines.slice(bodyStart + 1).join("\n");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return deltaOutput;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function renderDiffBlockWithDelta(code: string): string | null {
|
|
131
|
+
if (!isDeltaInstalled()) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const cached = deltaDiffCache.get(code);
|
|
136
|
+
if (cached !== undefined) {
|
|
137
|
+
return cached;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let rendered = runDelta(code);
|
|
141
|
+
|
|
142
|
+
if (!rendered) {
|
|
143
|
+
const syntheticDiff = [
|
|
144
|
+
"--- a/file",
|
|
145
|
+
"+++ b/file",
|
|
146
|
+
"@@ -1,1 +1,1 @@",
|
|
147
|
+
code,
|
|
148
|
+
].join("\n");
|
|
149
|
+
|
|
150
|
+
const syntheticRendered = runDelta(syntheticDiff);
|
|
151
|
+
if (syntheticRendered) {
|
|
152
|
+
rendered = stripSyntheticHeader(syntheticRendered);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (deltaDiffCache.size >= DELTA_CACHE_MAX_ENTRIES) {
|
|
157
|
+
deltaDiffCache.clear();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
deltaDiffCache.set(code, rendered);
|
|
161
|
+
return rendered;
|
|
162
|
+
}
|
|
163
|
+
|
|
76
164
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
77
165
|
// Word-Level Diff Highlighting
|
|
78
166
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -128,6 +216,11 @@ function renderIntraLineDiff(
|
|
|
128
216
|
* Render diff lines with syntax highlighting (red/green, word-level inverse)
|
|
129
217
|
*/
|
|
130
218
|
export function renderDiffBlock(code: string, theme: Theme): string {
|
|
219
|
+
const deltaRendered = renderDiffBlockWithDelta(code);
|
|
220
|
+
if (deltaRendered !== null) {
|
|
221
|
+
return deltaRendered;
|
|
222
|
+
}
|
|
223
|
+
|
|
131
224
|
const lines = code.split("\n");
|
|
132
225
|
const result: string[] = [];
|
|
133
226
|
|
|
@@ -378,7 +471,7 @@ export interface RenderOptions {
|
|
|
378
471
|
|
|
379
472
|
/**
|
|
380
473
|
* Render RepoPrompt output with syntax highlighting for fenced code blocks.
|
|
381
|
-
* - ```diff blocks
|
|
474
|
+
* - ```diff blocks use delta when available, with word-level fallback
|
|
382
475
|
* - Other fenced blocks get syntax highlighting via Pi's highlightCode
|
|
383
476
|
* - Non-fenced content is rendered with markdown-aware styling
|
|
384
477
|
*/
|
package/package.json
CHANGED