@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 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 readFileSync7, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
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 { statSync as statSync2, readFileSync as readFileSync3 } from "fs";
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 content;
22324
+ let summary;
22286
22325
  try {
22287
- content = readFileSync3(jsonlPath, "utf8");
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
- const lines = content.split("\n").filter((l2) => l2.trim().length > 0);
22293
- if (lines.length !== expectedRecordCount) {
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(lines[0]);
22299
- const lastRec = JSON.parse(lines[lines.length - 1]);
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 readFileSync4 } from "fs";
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(readFileSync4(path, "utf-8"));
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(readFileSync4(path, "utf8"));
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 readFileSync5 } from "fs";
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 = readFileSync5(agentsPath, "utf-8").trim();
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 readFileSync6 } from "fs";
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 = readFileSync6(path, "utf8").trim();
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(readFileSync7(realPath).subarray(0, 16));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanillagreen/pi-claude-bridge",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Pi provider bridge that runs Claude Code through the Claude Agent SDK, with opt-in forwarding for Pi prompt context.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -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 { statSync, readFileSync } from "fs";
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 content;
63
+ let summary;
17
64
  try {
18
- content = readFileSync(jsonlPath, "utf8");
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
- const lines = content.split("\n").filter((l) => l.trim().length > 0);
24
- if (lines.length !== expectedRecordCount) {
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(lines[0]);
30
- const lastRec = JSON.parse(lines[lines.length - 1]);
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
  }