Skip to content

Commit dc5e526

Browse files
committed
Use stream reader instead of async iteration for reading messages
This makes the TS library not dependent on node types so it can also run in the browser. It is likely the previous code would be ok, but this method is supported in more environments Signed-off-by: Ben Brandt <benjamin.j.brandt@gmail.com>
1 parent 631a750 commit dc5e526

4 files changed

Lines changed: 41 additions & 34 deletions

File tree

typescript/acp.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { describe, it, expect, beforeEach } from "vitest";
2-
import { TransformStream } from "node:stream/web";
32
import {
43
Agent,
54
ClientSideConnection,

typescript/acp.ts

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import { z } from "zod";
22
import * as schema from "./schema.js";
33
export * from "./schema.js";
44

5-
import { WritableStream, ReadableStream } from "node:stream/web";
6-
75
/**
86
* An agent-side connection to a client.
97
*
@@ -605,39 +603,51 @@ class Connection {
605603
async #receive(output: ReadableStream<Uint8Array>) {
606604
let content = "";
607605
const decoder = new TextDecoder();
608-
for await (const chunk of output) {
609-
content += decoder.decode(chunk, { stream: true });
610-
const lines = content.split("\n");
611-
content = lines.pop() || "";
612-
613-
for (const line of lines) {
614-
const trimmedLine = line.trim();
615-
616-
if (trimmedLine) {
617-
let id;
618-
try {
619-
const message = JSON.parse(trimmedLine);
620-
id = message.id;
621-
this.#processMessage(message);
622-
} catch (err) {
623-
console.error(
624-
"Unexpected error during message processing:",
625-
trimmedLine,
626-
err,
627-
);
628-
if (id) {
629-
this.#sendMessage({
630-
jsonrpc: "2.0",
631-
id,
632-
error: {
633-
code: -32700,
634-
message: "Parse error",
635-
},
636-
});
606+
const reader = output.getReader();
607+
try {
608+
while (true) {
609+
const { value, done } = await reader.read();
610+
if (done) {
611+
break;
612+
}
613+
if (!value) {
614+
continue;
615+
}
616+
content += decoder.decode(value, { stream: true });
617+
const lines = content.split("\n");
618+
content = lines.pop() || "";
619+
620+
for (const line of lines) {
621+
const trimmedLine = line.trim();
622+
623+
if (trimmedLine) {
624+
let id;
625+
try {
626+
const message = JSON.parse(trimmedLine);
627+
id = message.id;
628+
this.#processMessage(message);
629+
} catch (err) {
630+
console.error(
631+
"Unexpected error during message processing:",
632+
trimmedLine,
633+
err,
634+
);
635+
if (id) {
636+
this.#sendMessage({
637+
jsonrpc: "2.0",
638+
id,
639+
error: {
640+
code: -32700,
641+
message: "Parse error",
642+
},
643+
});
644+
}
637645
}
638646
}
639647
}
640648
}
649+
} finally {
650+
reader.releaseLock();
641651
}
642652
}
643653

typescript/examples/agent.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { AgentSideConnection, Agent, PROTOCOL_VERSION } from "../acp.js";
44
import * as schema from "../schema.js";
5-
import { WritableStream, ReadableStream } from "node:stream/web";
65
import { Readable, Writable } from "node:stream";
76

87
interface AgentSession {

typescript/examples/client.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import { spawn } from "node:child_process";
44
import { fileURLToPath } from "node:url";
55
import { dirname, join } from "node:path";
6-
import { WritableStream, ReadableStream } from "node:stream/web";
76
import { Writable, Readable } from "node:stream";
87
import readline from "node:readline/promises";
98

0 commit comments

Comments
 (0)