fix: revert jsonl.ts to inline implementation — @gsd-build/rpc-client not available at source-level test time in CI

The re-export from @gsd-build/rpc-client fails in CI because tests run against
TypeScript source (--experimental-strip-types) before any build step. The npm
dependency resolves to node_modules/ which requires dist/ to exist. Reverting
to the original inline implementation eliminates the cross-package dependency
for source-level imports.
This commit is contained in:
Lex Christopherson 2026-03-26 23:20:37 -06:00
parent 2cc7653efb
commit 98eb2ae802
3 changed files with 64 additions and 3 deletions

1
package-lock.json generated
View file

@ -9221,7 +9221,6 @@
"name": "@gsd/pi-coding-agent",
"version": "2.52.0",
"dependencies": {
"@gsd-build/rpc-client": "^2.52.0",
"@mariozechner/jiti": "^2.6.2",
"@silvia-odwyer/photon-node": "^0.3.4",
"chalk": "^5.5.0",

View file

@ -20,7 +20,6 @@
"copy-assets": "node scripts/copy-assets.cjs"
},
"dependencies": {
"@gsd-build/rpc-client": "^2.52.0",
"@mariozechner/jiti": "^2.6.2",
"@silvia-odwyer/photon-node": "^0.3.4",
"chalk": "^5.5.0",

View file

@ -1 +1,64 @@
export { serializeJsonLine, attachJsonlLineReader } from '@gsd-build/rpc-client';
import type { Readable } from "node:stream";
import { StringDecoder } from "node:string_decoder";
/**
* Serialize a single strict JSONL record.
*
* Framing is LF-only. Payload strings may contain other Unicode separators such as
* U+2028 and U+2029. Clients must split records on `\n` only.
*/
export function serializeJsonLine(value: unknown): string {
return `${JSON.stringify(value)}\n`;
}
/**
* Attach an LF-only JSONL reader to a stream.
*
* This intentionally does not use Node readline. Readline splits on additional
* Unicode separators that are valid inside JSON strings and therefore does not
* implement strict JSONL framing.
*/
export function attachJsonlLineReader(stream: Readable, onLine: (line: string) => void): () => void {
const decoder = new StringDecoder("utf8");
let buffer = "";
const emitLine = (line: string) => {
onLine(line.endsWith("\r") ? line.slice(0, -1) : line);
};
const onData = (chunk: string | Buffer) => {
buffer += typeof chunk === "string" ? chunk : decoder.write(chunk);
while (true) {
const newlineIndex = buffer.indexOf("\n");
if (newlineIndex === -1) {
return;
}
emitLine(buffer.slice(0, newlineIndex));
buffer = buffer.slice(newlineIndex + 1);
}
};
const onEnd = () => {
buffer += decoder.end();
if (buffer.length > 0) {
emitLine(buffer);
buffer = "";
}
};
const onError = (_err: Error) => {
// Stream errors are non-fatal for JSONL reading
};
stream.on("data", onData);
stream.on("end", onEnd);
stream.on("error", onError);
return () => {
stream.off("data", onData);
stream.off("end", onEnd);
stream.off("error", onError);
};
}