wave-code 0.19.2 → 0.19.4

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.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * StdioServer — reads JSON-RPC messages from stdin, dispatches to AgentBridge,
3
+ * and writes responses / notifications to stdout.
4
+ *
5
+ * One JSON object per line. stderr is reserved for logger output.
6
+ */
7
+ import type { Readable, Writable } from "stream";
8
+ import { AgentBridge, type AgentBridgeOptions } from "./agentBridge.js";
9
+ export interface StdioServerOptions {
10
+ input?: Readable;
11
+ output?: Writable;
12
+ bridgeOptions?: AgentBridgeOptions;
13
+ }
14
+ export declare class StdioServer {
15
+ private rl;
16
+ private bridge;
17
+ private input;
18
+ private output;
19
+ private started;
20
+ constructor(options?: StdioServerOptions);
21
+ get agentBridge(): AgentBridge;
22
+ start(): void;
23
+ stop(): void;
24
+ handleLine(line: string): Promise<void>;
25
+ private handleRequest;
26
+ private handleNotification;
27
+ sendResponse(id: number | string | null, result?: unknown, error?: {
28
+ code: number;
29
+ message: string;
30
+ }): void;
31
+ sendNotification(method: string, params?: unknown, sessionId?: string): void;
32
+ private write;
33
+ }
34
+ //# sourceMappingURL=stdioServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdioServer.d.ts","sourceRoot":"","sources":["../../src/stdio/stdioServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAYxE,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAiC;IAC3C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,kBAAuB;IAU5C,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED,KAAK,IAAI,IAAI;IAwBb,IAAI,IAAI,IAAI;IAMN,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAoC/B,aAAa;IAkB3B,OAAO,CAAC,kBAAkB;IAa1B,YAAY,CACV,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,MAAM,CAAC,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACxC,IAAI;IAUP,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAM5E,OAAO,CAAC,KAAK;CAGd"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * StdioServer — reads JSON-RPC messages from stdin, dispatches to AgentBridge,
3
+ * and writes responses / notifications to stdout.
4
+ *
5
+ * One JSON object per line. stderr is reserved for logger output.
6
+ */
7
+ import readline from "readline";
8
+ import { AgentBridge } from "./agentBridge.js";
9
+ import { PARSE_ERROR, INVALID_REQUEST, INTERNAL_ERROR, isRequest, isNotification, } from "./protocol.js";
10
+ export class StdioServer {
11
+ constructor(options = {}) {
12
+ this.started = false;
13
+ this.input = options.input ?? process.stdin;
14
+ this.output = options.output ?? process.stdout;
15
+ this.bridge = new AgentBridge({
16
+ ...options.bridgeOptions,
17
+ emit: (method, params, sessionId) => this.sendNotification(method, params, sessionId),
18
+ });
19
+ }
20
+ get agentBridge() {
21
+ return this.bridge;
22
+ }
23
+ start() {
24
+ if (this.started)
25
+ return;
26
+ this.started = true;
27
+ this.rl = readline.createInterface({
28
+ input: this.input,
29
+ crlfDelay: Infinity,
30
+ });
31
+ this.rl.on("line", (line) => {
32
+ this.handleLine(line).catch((err) => {
33
+ // Should never reach here — handleLine catches internally
34
+ this.sendResponse(null, undefined, {
35
+ code: INTERNAL_ERROR,
36
+ message: `Unhandled error: ${err.message}`,
37
+ });
38
+ });
39
+ });
40
+ this.rl.on("close", () => {
41
+ this.started = false;
42
+ });
43
+ }
44
+ stop() {
45
+ this.rl?.close();
46
+ this.rl = undefined;
47
+ this.started = false;
48
+ }
49
+ async handleLine(line) {
50
+ const trimmed = line.trim();
51
+ if (!trimmed)
52
+ return;
53
+ let msg;
54
+ try {
55
+ msg = JSON.parse(trimmed);
56
+ }
57
+ catch {
58
+ this.sendResponse(null, undefined, {
59
+ code: PARSE_ERROR,
60
+ message: "Parse error: invalid JSON",
61
+ });
62
+ return;
63
+ }
64
+ if (isRequest(msg)) {
65
+ await this.handleRequest(msg);
66
+ }
67
+ else if (isNotification(msg)) {
68
+ this.handleNotification(msg);
69
+ }
70
+ else {
71
+ // Echo back the id if the message has one, otherwise null
72
+ const id = typeof msg === "object" &&
73
+ msg !== null &&
74
+ "id" in msg &&
75
+ (typeof msg.id === "number" ||
76
+ typeof msg.id === "string")
77
+ ? msg.id
78
+ : null;
79
+ this.sendResponse(id, undefined, {
80
+ code: INVALID_REQUEST,
81
+ message: "Invalid request: must have 'method' field",
82
+ });
83
+ }
84
+ }
85
+ async handleRequest(msg) {
86
+ try {
87
+ const result = await this.bridge.handleRequest(msg.method, msg.params, msg.sessionId);
88
+ this.sendResponse(msg.id, result);
89
+ }
90
+ catch (err) {
91
+ const code = err && typeof err === "object" && "code" in err
92
+ ? err.code
93
+ : INTERNAL_ERROR;
94
+ const message = err instanceof Error ? err.message : String(err);
95
+ this.sendResponse(msg.id, undefined, { code, message });
96
+ }
97
+ }
98
+ handleNotification(msg) {
99
+ try {
100
+ this.bridge.handleNotification(msg.method, msg.params);
101
+ }
102
+ catch (err) {
103
+ // Notifications don't get responses, but we log to stderr
104
+ process.stderr.write(`Error handling notification ${msg.method}: ${err.message}\n`);
105
+ }
106
+ }
107
+ // ── Output helpers ────────────────────────────────────────────
108
+ sendResponse(id, result, error) {
109
+ const response = { id };
110
+ if (error) {
111
+ response.error = error;
112
+ }
113
+ else {
114
+ response.result = result ?? null;
115
+ }
116
+ this.write(response);
117
+ }
118
+ sendNotification(method, params, sessionId) {
119
+ const notification = { method, params };
120
+ if (sessionId)
121
+ notification.sessionId = sessionId;
122
+ this.write(notification);
123
+ }
124
+ write(obj) {
125
+ this.output.write(JSON.stringify(obj) + "\n");
126
+ }
127
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * stdio-cli.ts — Entry point for `wave --stdio` mode.
3
+ *
4
+ * Starts a StdioServer that reads JSON-RPC messages from stdin and writes
5
+ * responses/notifications to stdout. The server creates an Agent lazily when
6
+ * the client sends an "initialize" request.
7
+ */
8
+ export declare function startStdioCli(): Promise<void>;
9
+ //# sourceMappingURL=stdio-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio-cli.d.ts","sourceRoot":"","sources":["../src/stdio-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAOnD"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * stdio-cli.ts — Entry point for `wave --stdio` mode.
3
+ *
4
+ * Starts a StdioServer that reads JSON-RPC messages from stdin and writes
5
+ * responses/notifications to stdout. The server creates an Agent lazily when
6
+ * the client sends an "initialize" request.
7
+ */
8
+ import { StdioServer } from "./stdio/stdioServer.js";
9
+ export async function startStdioCli() {
10
+ const server = new StdioServer();
11
+ server.start();
12
+ // Keep the process alive — readline on stdin handles the event loop.
13
+ // When stdin closes (EOF), the readline interface emits 'close' and
14
+ // the process will exit naturally.
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-code",
3
- "version": "0.19.2",
3
+ "version": "0.19.4",
4
4
  "description": "CLI-based code assistant powered by AI, built with React and Ink",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,6 @@
29
29
  "README.md"
30
30
  ],
31
31
  "dependencies": {
32
- "@agentclientprotocol/sdk": "0.17.1",
33
32
  "chalk": "^5.6.2",
34
33
  "diff": "^8.0.2",
35
34
  "glob": "^13.0.0",
@@ -42,7 +41,7 @@
42
41
  "semver": "^7.7.4",
43
42
  "yargs": "^17.7.2",
44
43
  "zod": "^3.23.8",
45
- "wave-agent-sdk": "0.19.2"
44
+ "wave-agent-sdk": "0.19.4"
46
45
  },
47
46
  "devDependencies": {
48
47
  "@types/react": "^19.1.8",
@@ -61,7 +60,7 @@
61
60
  "react": ">=18.0.0"
62
61
  },
63
62
  "engines": {
64
- "node": ">=22.0.0"
63
+ "node": ">=20"
65
64
  },
66
65
  "license": "MIT",
67
66
  "scripts": {
package/src/index.ts CHANGED
@@ -47,6 +47,12 @@ export async function main() {
47
47
  type: "string",
48
48
  global: false,
49
49
  })
50
+ .option("stdio", {
51
+ description: "Start in stdio mode (JSON-RPC over stdin/stdout)",
52
+ type: "boolean",
53
+ default: false,
54
+ global: false,
55
+ })
50
56
  .option("show-stats", {
51
57
  description: "Show timing and usage statistics in print mode",
52
58
  type: "boolean",
@@ -105,11 +111,6 @@ export async function main() {
105
111
  type: "string",
106
112
  global: false,
107
113
  })
108
- .option("acp", {
109
- description: "Run as an ACP bridge",
110
- type: "boolean",
111
- global: false,
112
- })
113
114
  .command("plugin", "Manage plugins and marketplaces", (yargs) => {
114
115
  return yargs
115
116
  .help()
@@ -343,12 +344,6 @@ export async function main() {
343
344
  process.chdir(workdir);
344
345
  }
345
346
 
346
- // Handle ACP mode
347
- if (argv.acp) {
348
- const { runAcp } = await import("./acp-cli.js");
349
- return runAcp();
350
- }
351
-
352
347
  // Handle restore session command
353
348
  if (
354
349
  argv.restore === "" ||
@@ -404,6 +399,12 @@ export async function main() {
404
399
  });
405
400
  }
406
401
 
402
+ // Handle stdio mode
403
+ if (argv.stdio) {
404
+ const { startStdioCli } = await import("./stdio-cli.js");
405
+ return startStdioCli();
406
+ }
407
+
407
408
  await startCli({
408
409
  restoreSessionId: argv.restore as string | undefined,
409
410
  continueLastSession: argv.continue as boolean | undefined,