@rahularya01/pi-cursor 1.4.8 → 1.4.10
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/CHANGELOG.md +15 -0
- package/dist/h2-bridge.mjs +32 -5
- package/dist/index.js +20 -20
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.4.10] - 2026-08-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Hardened permission handling, transport framing, OAuth cancellation, recovery journals, logging, and MCP tool validation.
|
|
8
|
+
- Startup model discovery now uses stale-while-revalidate behavior so Pi can activate from cached or bundled models without waiting for network discovery.
|
|
9
|
+
- Added bounded payloads, backpressure handling, cleanup on aborted/failing streams, and expanded regression coverage.
|
|
10
|
+
|
|
11
|
+
## [1.4.9] - 2026-08-12
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **Tool continuation recovery after a silent resumed bridge.** Idle-timeout, abort, and transport-retry persistence now retain the mid-pause checkpoint and pending tool-call metadata when a tool result is being resumed, preventing valid checkpoints from being discarded as stale after the 3-minute watchdog fires.
|
|
16
|
+
- Added a recovery guard that refuses to replay tool results into a checkpoint when no matching durable mid-pause snapshot exists.
|
|
17
|
+
|
|
3
18
|
## [1.4.8] - 2026-08-02
|
|
4
19
|
|
|
5
20
|
### Fixed
|
package/dist/h2-bridge.mjs
CHANGED
|
@@ -22,15 +22,20 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import http2 from "node:http2";
|
|
24
24
|
import crypto from "node:crypto";
|
|
25
|
+
import { once } from "node:events";
|
|
25
26
|
|
|
26
27
|
const CURSOR_CLIENT_VERSION = process.env.PI_CURSOR_CLIENT_VERSION || "cli-2026.05.01-eea359f";
|
|
28
|
+
const MAX_BRIDGE_MESSAGE_BYTES = 64 * 1024 * 1024;
|
|
29
|
+
const MAX_ERROR_BODY_BYTES = 1024 * 1024;
|
|
27
30
|
|
|
28
31
|
/** Write one length-prefixed message to stdout. */
|
|
29
32
|
function writeMessage(data) {
|
|
33
|
+
if (data.length > MAX_BRIDGE_MESSAGE_BYTES) {
|
|
34
|
+
throw new Error(`bridge output exceeds ${MAX_BRIDGE_MESSAGE_BYTES} bytes`);
|
|
35
|
+
}
|
|
30
36
|
const lenBuf = Buffer.alloc(4);
|
|
31
37
|
lenBuf.writeUInt32BE(data.length, 0);
|
|
32
|
-
process.stdout.write(lenBuf);
|
|
33
|
-
process.stdout.write(data);
|
|
38
|
+
return process.stdout.write(Buffer.concat([lenBuf, data]));
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
function connectEndStreamError(code, message) {
|
|
@@ -50,6 +55,10 @@ let stdinEnded = false;
|
|
|
50
55
|
|
|
51
56
|
process.stdin.on("data", (chunk) => {
|
|
52
57
|
stdinBuf = Buffer.concat([stdinBuf, chunk]);
|
|
58
|
+
if (stdinBuf.length > MAX_BRIDGE_MESSAGE_BYTES + 4) {
|
|
59
|
+
process.stderr.write("[h2-bridge] stdin buffer limit exceeded\n");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
53
62
|
if (stdinResolve) {
|
|
54
63
|
const r = stdinResolve;
|
|
55
64
|
stdinResolve = null;
|
|
@@ -86,6 +95,9 @@ async function readMessage() {
|
|
|
86
95
|
const lenBuf = await readExact(4);
|
|
87
96
|
if (!lenBuf) return null;
|
|
88
97
|
const len = lenBuf.readUInt32BE(0);
|
|
98
|
+
if (len > MAX_BRIDGE_MESSAGE_BYTES) {
|
|
99
|
+
throw new Error(`bridge input exceeds ${MAX_BRIDGE_MESSAGE_BYTES} bytes`);
|
|
100
|
+
}
|
|
89
101
|
if (len === 0) return Buffer.alloc(0);
|
|
90
102
|
return readExact(len);
|
|
91
103
|
}
|
|
@@ -218,6 +230,7 @@ const h2Stream = client.request(headers);
|
|
|
218
230
|
let responseStatus = 0;
|
|
219
231
|
let responseStatusText = "";
|
|
220
232
|
const errorChunks = [];
|
|
233
|
+
let errorBodyBytes = 0;
|
|
221
234
|
const isErrorStatus = () => responseStatus !== 0 && (responseStatus < 200 || responseStatus >= 300);
|
|
222
235
|
|
|
223
236
|
h2Stream.on("response", (responseHeaders) => {
|
|
@@ -231,9 +244,17 @@ h2Stream.on("response", (responseHeaders) => {
|
|
|
231
244
|
h2Stream.on("data", (chunk) => {
|
|
232
245
|
resetTimeout();
|
|
233
246
|
if (isErrorStatus()) {
|
|
234
|
-
|
|
247
|
+
const remaining = MAX_ERROR_BODY_BYTES - errorBodyBytes;
|
|
248
|
+
if (remaining > 0) {
|
|
249
|
+
const kept = Buffer.from(chunk).subarray(0, remaining);
|
|
250
|
+
errorChunks.push(kept);
|
|
251
|
+
errorBodyBytes += kept.byteLength;
|
|
252
|
+
}
|
|
235
253
|
} else {
|
|
236
|
-
writeMessage(chunk)
|
|
254
|
+
if (!writeMessage(chunk)) {
|
|
255
|
+
h2Stream.pause();
|
|
256
|
+
process.stdout.once("drain", () => h2Stream.resume());
|
|
257
|
+
}
|
|
237
258
|
}
|
|
238
259
|
});
|
|
239
260
|
|
|
@@ -284,7 +305,13 @@ if (unary) {
|
|
|
284
305
|
}
|
|
285
306
|
if (!h2Stream.closed && !h2Stream.destroyed) {
|
|
286
307
|
resetTimeout();
|
|
287
|
-
h2Stream.write(msg)
|
|
308
|
+
if (!h2Stream.write(msg)) {
|
|
309
|
+
try {
|
|
310
|
+
await once(h2Stream, "drain");
|
|
311
|
+
} catch {
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
288
315
|
}
|
|
289
316
|
}
|
|
290
317
|
|