@vanillagreen/pi-claude-bridge 1.4.0 → 1.4.1
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/bundle/index.js +55 -17
- package/package.json +1 -1
- package/src/session-verify.ts +54 -8
package/bundle/index.js
CHANGED
|
@@ -21976,7 +21976,7 @@ function readSession(jsonlPath, projectPath) {
|
|
|
21976
21976
|
// src/index.ts
|
|
21977
21977
|
import { spawn as spawnProcess } from "child_process";
|
|
21978
21978
|
import { createHash } from "crypto";
|
|
21979
|
-
import { accessSync, appendFileSync as appendFileSync3, chmodSync, constants as fsConstants, mkdirSync as mkdirSync3, readFileSync as
|
|
21979
|
+
import { accessSync, appendFileSync as appendFileSync3, chmodSync, constants as fsConstants, mkdirSync as mkdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
21980
21980
|
import { resolve as pathResolve } from "path";
|
|
21981
21981
|
import { homedir as homedir5 } from "os";
|
|
21982
21982
|
import { delimiter, dirname as dirname5, join as join5 } from "path";
|
|
@@ -22272,7 +22272,46 @@ function rewriteSkillsBlock(skillsBlock) {
|
|
|
22272
22272
|
}
|
|
22273
22273
|
|
|
22274
22274
|
// src/session-verify.ts
|
|
22275
|
-
import {
|
|
22275
|
+
import { closeSync as closeSync2, openSync as openSync2, readSync as readSync2, statSync as statSync2 } from "fs";
|
|
22276
|
+
import { StringDecoder } from "node:string_decoder";
|
|
22277
|
+
function forEachJsonlLine(path, onLine) {
|
|
22278
|
+
const fd = openSync2(path, "r");
|
|
22279
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
22280
|
+
const decoder = new StringDecoder("utf8");
|
|
22281
|
+
let pending = "";
|
|
22282
|
+
try {
|
|
22283
|
+
for (; ; ) {
|
|
22284
|
+
const bytesRead = readSync2(fd, buffer, 0, buffer.length, null);
|
|
22285
|
+
if (bytesRead === 0) break;
|
|
22286
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
22287
|
+
let start = 0;
|
|
22288
|
+
for (; ; ) {
|
|
22289
|
+
const newline = pending.indexOf("\n", start);
|
|
22290
|
+
if (newline < 0) {
|
|
22291
|
+
pending = pending.slice(start);
|
|
22292
|
+
break;
|
|
22293
|
+
}
|
|
22294
|
+
const line = pending.slice(start, newline);
|
|
22295
|
+
onLine(line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
22296
|
+
start = newline + 1;
|
|
22297
|
+
}
|
|
22298
|
+
}
|
|
22299
|
+
pending += decoder.end();
|
|
22300
|
+
if (pending.length > 0) onLine(pending.endsWith("\r") ? pending.slice(0, -1) : pending);
|
|
22301
|
+
} finally {
|
|
22302
|
+
closeSync2(fd);
|
|
22303
|
+
}
|
|
22304
|
+
}
|
|
22305
|
+
function summarizeJsonl(path) {
|
|
22306
|
+
const summary = { count: 0 };
|
|
22307
|
+
forEachJsonlLine(path, (line) => {
|
|
22308
|
+
if (!line.trim()) return;
|
|
22309
|
+
summary.count += 1;
|
|
22310
|
+
if (summary.firstLine === void 0) summary.firstLine = line;
|
|
22311
|
+
summary.lastLine = line;
|
|
22312
|
+
});
|
|
22313
|
+
return summary;
|
|
22314
|
+
}
|
|
22276
22315
|
function verifyWrittenSession(jsonlPath, expectedSessionId, expectedRecordCount) {
|
|
22277
22316
|
const warnings = [];
|
|
22278
22317
|
let st;
|
|
@@ -22282,21 +22321,20 @@ function verifyWrittenSession(jsonlPath, expectedSessionId, expectedRecordCount)
|
|
|
22282
22321
|
warnings.push(`file missing after save \u2014 path=${jsonlPath} err=${e2.message}`);
|
|
22283
22322
|
return warnings;
|
|
22284
22323
|
}
|
|
22285
|
-
let
|
|
22324
|
+
let summary;
|
|
22286
22325
|
try {
|
|
22287
|
-
|
|
22326
|
+
summary = summarizeJsonl(jsonlPath);
|
|
22288
22327
|
} catch (e2) {
|
|
22289
22328
|
warnings.push(`file unreadable \u2014 path=${jsonlPath} size=${st.size} err=${e2.message}`);
|
|
22290
22329
|
return warnings;
|
|
22291
22330
|
}
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
warnings.push(`record count mismatch \u2014 expected=${expectedRecordCount} actual=${lines.length} path=${jsonlPath} bytes=${content.length}`);
|
|
22331
|
+
if (summary.count !== expectedRecordCount) {
|
|
22332
|
+
warnings.push(`record count mismatch \u2014 expected=${expectedRecordCount} actual=${summary.count} path=${jsonlPath} bytes=${st.size}`);
|
|
22295
22333
|
return warnings;
|
|
22296
22334
|
}
|
|
22297
22335
|
try {
|
|
22298
|
-
const firstRec = JSON.parse(
|
|
22299
|
-
const lastRec = JSON.parse(
|
|
22336
|
+
const firstRec = JSON.parse(summary.firstLine ?? "");
|
|
22337
|
+
const lastRec = JSON.parse(summary.lastLine ?? "");
|
|
22300
22338
|
if (firstRec.sessionId !== expectedSessionId || lastRec.sessionId !== expectedSessionId) {
|
|
22301
22339
|
warnings.push(`sessionId drift \u2014 expected=${expectedSessionId} first=${firstRec.sessionId} last=${lastRec.sessionId}`);
|
|
22302
22340
|
}
|
|
@@ -22564,7 +22602,7 @@ function summarizeMissingToolNames(missing) {
|
|
|
22564
22602
|
}
|
|
22565
22603
|
|
|
22566
22604
|
// src/config.ts
|
|
22567
|
-
import { existsSync as existsSync3, readFileSync as
|
|
22605
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
22568
22606
|
import { homedir as homedir2 } from "os";
|
|
22569
22607
|
import { dirname as dirname2, join as join2, resolve } from "path";
|
|
22570
22608
|
var PACKAGE_ID = "@vanillagreen/pi-claude-bridge";
|
|
@@ -22606,7 +22644,7 @@ function settingsPaths(cwd) {
|
|
|
22606
22644
|
function tryParseJson(path) {
|
|
22607
22645
|
if (!existsSync3(path)) return {};
|
|
22608
22646
|
try {
|
|
22609
|
-
return JSON.parse(
|
|
22647
|
+
return JSON.parse(readFileSync3(path, "utf-8"));
|
|
22610
22648
|
} catch {
|
|
22611
22649
|
return {};
|
|
22612
22650
|
}
|
|
@@ -22616,7 +22654,7 @@ function readManagerConfig(cwd) {
|
|
|
22616
22654
|
for (const path of settingsPaths(cwd)) {
|
|
22617
22655
|
if (!existsSync3(path)) continue;
|
|
22618
22656
|
try {
|
|
22619
|
-
const parsed = JSON.parse(
|
|
22657
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
22620
22658
|
const configRoot = asRecord(asRecord(asRecord(parsed?.vstack)?.extensionManager)?.config);
|
|
22621
22659
|
const config2 = asRecord(configRoot?.[PACKAGE_ID]);
|
|
22622
22660
|
if (config2) mergeDeep(merged, config2);
|
|
@@ -22720,7 +22758,7 @@ function loadConfig(cwd) {
|
|
|
22720
22758
|
}
|
|
22721
22759
|
|
|
22722
22760
|
// src/agents-md.ts
|
|
22723
|
-
import { existsSync as existsSync4, readFileSync as
|
|
22761
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
22724
22762
|
import { homedir as homedir3 } from "os";
|
|
22725
22763
|
import { dirname as dirname3, join as join3, resolve as resolve2 } from "path";
|
|
22726
22764
|
var GLOBAL_AGENTS_PATH = join3(homedir3(), ".pi", "agent", "AGENTS.md");
|
|
@@ -22745,7 +22783,7 @@ function extractAgentsAppend() {
|
|
|
22745
22783
|
const agentsPath = resolveAgentsMdPath();
|
|
22746
22784
|
if (!agentsPath) return void 0;
|
|
22747
22785
|
try {
|
|
22748
|
-
const content =
|
|
22786
|
+
const content = readFileSync4(agentsPath, "utf-8").trim();
|
|
22749
22787
|
if (!content) return void 0;
|
|
22750
22788
|
const sanitized = sanitizeAgentsContent(content);
|
|
22751
22789
|
return sanitized.length > 0 ? `# CLAUDE.md
|
|
@@ -22765,7 +22803,7 @@ function sanitizeAgentsContent(content) {
|
|
|
22765
22803
|
}
|
|
22766
22804
|
|
|
22767
22805
|
// src/prompt-context.ts
|
|
22768
|
-
import { existsSync as existsSync5, readFileSync as
|
|
22806
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
22769
22807
|
import { homedir as homedir4 } from "os";
|
|
22770
22808
|
import { dirname as dirname4, join as join4, resolve as resolve3 } from "path";
|
|
22771
22809
|
function piUserDir2() {
|
|
@@ -22776,7 +22814,7 @@ function piUserDir2() {
|
|
|
22776
22814
|
function readTrimmed(path) {
|
|
22777
22815
|
try {
|
|
22778
22816
|
if (!existsSync5(path)) return void 0;
|
|
22779
|
-
const content =
|
|
22817
|
+
const content = readFileSync5(path, "utf8").trim();
|
|
22780
22818
|
return content.length > 0 ? content : void 0;
|
|
22781
22819
|
} catch {
|
|
22782
22820
|
return void 0;
|
|
@@ -37607,7 +37645,7 @@ function preflightClaudeExecutable(path, cwd) {
|
|
|
37607
37645
|
}
|
|
37608
37646
|
let fileType;
|
|
37609
37647
|
try {
|
|
37610
|
-
fileType = classifyClaudeExecutableBytes(
|
|
37648
|
+
fileType = classifyClaudeExecutableBytes(readFileSync6(realPath).subarray(0, 16));
|
|
37611
37649
|
} catch (err) {
|
|
37612
37650
|
throw makeClaudePreflightError("Claude Code executable preflight failed: cannot read executable header before spawning Claude Code.", {
|
|
37613
37651
|
code: codeValue(err, "EACCES"),
|
package/package.json
CHANGED
package/src/session-verify.ts
CHANGED
|
@@ -2,7 +2,54 @@
|
|
|
2
2
|
// callers decide how to surface them (debug log, piUI, diagDump, etc.).
|
|
3
3
|
// Extracted from index.ts so tests can import without activating the extension.
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { closeSync, openSync, readSync, statSync } from "fs";
|
|
6
|
+
import { StringDecoder } from "node:string_decoder";
|
|
7
|
+
|
|
8
|
+
interface JsonlSummary {
|
|
9
|
+
count: number;
|
|
10
|
+
firstLine?: string;
|
|
11
|
+
lastLine?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function forEachJsonlLine(path: string, onLine: (line: string) => void): void {
|
|
15
|
+
const fd = openSync(path, "r");
|
|
16
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
17
|
+
const decoder = new StringDecoder("utf8");
|
|
18
|
+
let pending = "";
|
|
19
|
+
try {
|
|
20
|
+
for (;;) {
|
|
21
|
+
const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
|
|
22
|
+
if (bytesRead === 0) break;
|
|
23
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
24
|
+
let start = 0;
|
|
25
|
+
for (;;) {
|
|
26
|
+
const newline = pending.indexOf("\n", start);
|
|
27
|
+
if (newline < 0) {
|
|
28
|
+
pending = pending.slice(start);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
const line = pending.slice(start, newline);
|
|
32
|
+
onLine(line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
33
|
+
start = newline + 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
pending += decoder.end();
|
|
37
|
+
if (pending.length > 0) onLine(pending.endsWith("\r") ? pending.slice(0, -1) : pending);
|
|
38
|
+
} finally {
|
|
39
|
+
closeSync(fd);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function summarizeJsonl(path: string): JsonlSummary {
|
|
44
|
+
const summary: JsonlSummary = { count: 0 };
|
|
45
|
+
forEachJsonlLine(path, (line) => {
|
|
46
|
+
if (!line.trim()) return;
|
|
47
|
+
summary.count += 1;
|
|
48
|
+
if (summary.firstLine === undefined) summary.firstLine = line;
|
|
49
|
+
summary.lastLine = line;
|
|
50
|
+
});
|
|
51
|
+
return summary;
|
|
52
|
+
}
|
|
6
53
|
|
|
7
54
|
export function verifyWrittenSession(jsonlPath: string, expectedSessionId: string, expectedRecordCount: number): string[] {
|
|
8
55
|
const warnings = [];
|
|
@@ -13,21 +60,20 @@ export function verifyWrittenSession(jsonlPath: string, expectedSessionId: strin
|
|
|
13
60
|
warnings.push(`file missing after save — path=${jsonlPath} err=${e.message}`);
|
|
14
61
|
return warnings;
|
|
15
62
|
}
|
|
16
|
-
let
|
|
63
|
+
let summary;
|
|
17
64
|
try {
|
|
18
|
-
|
|
65
|
+
summary = summarizeJsonl(jsonlPath);
|
|
19
66
|
} catch (e) {
|
|
20
67
|
warnings.push(`file unreadable — path=${jsonlPath} size=${st.size} err=${e.message}`);
|
|
21
68
|
return warnings;
|
|
22
69
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
warnings.push(`record count mismatch — expected=${expectedRecordCount} actual=${lines.length} path=${jsonlPath} bytes=${content.length}`);
|
|
70
|
+
if (summary.count !== expectedRecordCount) {
|
|
71
|
+
warnings.push(`record count mismatch — expected=${expectedRecordCount} actual=${summary.count} path=${jsonlPath} bytes=${st.size}`);
|
|
26
72
|
return warnings;
|
|
27
73
|
}
|
|
28
74
|
try {
|
|
29
|
-
const firstRec = JSON.parse(
|
|
30
|
-
const lastRec = JSON.parse(
|
|
75
|
+
const firstRec = JSON.parse(summary.firstLine ?? "");
|
|
76
|
+
const lastRec = JSON.parse(summary.lastLine ?? "");
|
|
31
77
|
if (firstRec.sessionId !== expectedSessionId || lastRec.sessionId !== expectedSessionId) {
|
|
32
78
|
warnings.push(`sessionId drift — expected=${expectedSessionId} first=${firstRec.sessionId} last=${lastRec.sessionId}`);
|
|
33
79
|
}
|