gsd-pi 2.53.0-dev.a67436f → 2.53.0

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.
Files changed (165) hide show
  1. package/dist/headless-ui.d.ts +2 -2
  2. package/dist/headless-ui.js +15 -18
  3. package/dist/headless.d.ts +0 -11
  4. package/dist/headless.js +38 -178
  5. package/dist/web/standalone/.next/BUILD_ID +1 -1
  6. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  7. package/dist/web/standalone/.next/build-manifest.json +3 -3
  8. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  9. package/dist/web/standalone/.next/required-server-files.json +4 -4
  10. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  11. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  13. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  19. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  21. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  27. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  31. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  32. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  33. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  34. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  35. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  36. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  37. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  38. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  39. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  40. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  41. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  42. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  43. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  44. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  45. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  47. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  48. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  49. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  50. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  51. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  52. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  53. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  54. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  55. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  56. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  57. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  58. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  59. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  67. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  68. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  74. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  76. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  77. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  83. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  97. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  99. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  101. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  103. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/index.html +1 -1
  113. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  114. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  115. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  116. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  118. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/page.js +2 -2
  120. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  122. package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
  123. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/middleware.js +2 -2
  126. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  128. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  129. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  130. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  131. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  132. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  133. package/dist/web/standalone/.next/static/chunks/app/page-fbecd1237e2d6d1f.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  135. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  136. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  137. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  138. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  139. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  140. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  141. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  142. package/dist/web/standalone/server.js +1 -1
  143. package/package.json +1 -1
  144. package/packages/mcp-server/README.md +6 -6
  145. package/packages/mcp-server/package.json +4 -14
  146. package/packages/mcp-server/src/cli.ts +1 -1
  147. package/packages/mcp-server/src/index.ts +1 -1
  148. package/packages/mcp-server/src/mcp-server.test.ts +2 -2
  149. package/packages/mcp-server/src/session-manager.ts +2 -2
  150. package/packages/mcp-server/src/types.ts +1 -1
  151. package/packages/rpc-client/package.json +3 -17
  152. package/dist/web/standalone/.next/static/chunks/app/page-b950e4e384cc62b3.js +0 -1
  153. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  154. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  155. package/packages/rpc-client/README.md +0 -125
  156. package/packages/rpc-client/examples/basic-usage.ts +0 -13
  157. package/packages/rpc-client/src/index.ts +0 -10
  158. package/packages/rpc-client/src/jsonl.ts +0 -64
  159. package/packages/rpc-client/src/rpc-client.test.ts +0 -568
  160. package/packages/rpc-client/src/rpc-client.ts +0 -666
  161. package/packages/rpc-client/src/rpc-types.ts +0 -399
  162. package/packages/rpc-client/tsconfig.examples.json +0 -17
  163. package/packages/rpc-client/tsconfig.json +0 -24
  164. /package/dist/web/standalone/.next/static/{YO-PWFRitlHM-L-dotlmm → mWBOLPnUoeaTGiD-vhu5O}/_buildManifest.js +0 -0
  165. /package/dist/web/standalone/.next/static/{YO-PWFRitlHM-L-dotlmm → mWBOLPnUoeaTGiD-vhu5O}/_ssgManifest.js +0 -0
@@ -1,666 +0,0 @@
1
- /**
2
- * RPC Client for programmatic access to the coding agent.
3
- *
4
- * Spawns the agent in RPC mode and provides a typed API for all operations.
5
- * This is a standalone SDK client — all types are inlined with zero internal
6
- * package dependencies.
7
- */
8
-
9
- import { type ChildProcess, spawn } from "node:child_process";
10
- import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
11
- import type {
12
- BashResult,
13
- CompactionResult,
14
- ImageContent,
15
- ModelInfo,
16
- RpcCommand,
17
- RpcInitResult,
18
- RpcResponse,
19
- RpcSessionState,
20
- RpcSlashCommand,
21
- ThinkingLevel,
22
- SessionStats,
23
- } from "./rpc-types.js";
24
-
25
- // ============================================================================
26
- // Types
27
- // ============================================================================
28
-
29
- /** Distributive Omit that works with union types */
30
- type DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;
31
-
32
- /** RpcCommand without the id field (for internal send) */
33
- type RpcCommandBody = DistributiveOmit<RpcCommand, "id">;
34
-
35
- /** Agent event — a loosely-typed record from the server. The `type` field is always present. */
36
- export interface SdkAgentEvent {
37
- type: string;
38
- [key: string]: unknown;
39
- }
40
-
41
- export interface RpcClientOptions {
42
- /** Path to the CLI entry point (default: searches for dist/cli.js) */
43
- cliPath?: string;
44
- /** Working directory for the agent */
45
- cwd?: string;
46
- /** Environment variables */
47
- env?: Record<string, string>;
48
- /** Provider to use */
49
- provider?: string;
50
- /** Model ID to use */
51
- model?: string;
52
- /** Additional CLI arguments */
53
- args?: string[];
54
- }
55
-
56
- export type RpcEventListener = (event: SdkAgentEvent) => void;
57
-
58
- // ============================================================================
59
- // RPC Client
60
- // ============================================================================
61
-
62
- export class RpcClient {
63
- private process: ChildProcess | null = null;
64
- private stopReadingStdout: (() => void) | null = null;
65
- private _stderrHandler?: (data: Buffer) => void;
66
- private eventListeners: RpcEventListener[] = [];
67
- private pendingRequests: Map<string, { resolve: (response: RpcResponse) => void; reject: (error: Error) => void }> =
68
- new Map();
69
- private requestId = 0;
70
- private stderr = "";
71
- private _stopped = false;
72
-
73
- constructor(private options: RpcClientOptions = {}) {}
74
-
75
- /**
76
- * Start the RPC agent process.
77
- */
78
- async start(): Promise<void> {
79
- if (this.process) {
80
- throw new Error("Client already started");
81
- }
82
-
83
- this._stopped = false;
84
-
85
- const cliPath = this.options.cliPath ?? "dist/cli.js";
86
- const args = ["--mode", "rpc"];
87
-
88
- if (this.options.provider) {
89
- args.push("--provider", this.options.provider);
90
- }
91
- if (this.options.model) {
92
- args.push("--model", this.options.model);
93
- }
94
- if (this.options.args) {
95
- args.push(...this.options.args);
96
- }
97
-
98
- this.process = spawn("node", [cliPath, ...args], {
99
- cwd: this.options.cwd,
100
- env: { ...process.env, ...this.options.env },
101
- stdio: ["pipe", "pipe", "pipe"],
102
- });
103
-
104
- // Collect stderr for debugging
105
- this._stderrHandler = (data: Buffer) => {
106
- this.stderr += data.toString();
107
- };
108
- this.process.stderr?.on("data", this._stderrHandler);
109
-
110
- // Set up strict JSONL reader for stdout.
111
- this.stopReadingStdout = attachJsonlLineReader(this.process.stdout!, (line) => {
112
- this.handleLine(line);
113
- });
114
-
115
- // Detect unexpected subprocess exit and reject all pending requests
116
- this.process.on("exit", (code, signal) => {
117
- if (this.pendingRequests.size > 0) {
118
- const reason = signal ? `signal ${signal}` : `code ${code}`;
119
- const error = new Error(`Agent process exited unexpectedly (${reason}). Stderr: ${this.stderr}`);
120
- for (const [id, pending] of this.pendingRequests) {
121
- this.pendingRequests.delete(id);
122
- pending.reject(error);
123
- }
124
- }
125
- });
126
-
127
- // Wait a moment for process to initialize
128
- await new Promise((resolve) => setTimeout(resolve, 100));
129
-
130
- if (this.process.exitCode !== null) {
131
- throw new Error(`Agent process exited immediately with code ${this.process.exitCode}. Stderr: ${this.stderr}`);
132
- }
133
- }
134
-
135
- /**
136
- * Stop the RPC agent process.
137
- */
138
- async stop(): Promise<void> {
139
- if (!this.process) return;
140
-
141
- this._stopped = true;
142
-
143
- this.stopReadingStdout?.();
144
- this.stopReadingStdout = null;
145
- if (this._stderrHandler) {
146
- this.process.stderr?.removeListener("data", this._stderrHandler);
147
- this._stderrHandler = undefined;
148
- }
149
- this.process.kill("SIGTERM");
150
-
151
- // Wait for process to exit
152
- await new Promise<void>((resolve) => {
153
- const timeout = setTimeout(() => {
154
- this.process?.kill("SIGKILL");
155
- resolve();
156
- }, 1000);
157
-
158
- this.process?.on("exit", () => {
159
- clearTimeout(timeout);
160
- resolve();
161
- });
162
- });
163
-
164
- this.process = null;
165
- this.pendingRequests.clear();
166
- }
167
-
168
- /**
169
- * Subscribe to agent events via callback.
170
- */
171
- onEvent(listener: RpcEventListener): () => void {
172
- this.eventListeners.push(listener);
173
- return () => {
174
- const index = this.eventListeners.indexOf(listener);
175
- if (index !== -1) {
176
- this.eventListeners.splice(index, 1);
177
- }
178
- };
179
- }
180
-
181
- /**
182
- * Async generator that yields agent events as they arrive.
183
- *
184
- * Usage:
185
- * ```ts
186
- * for await (const event of client.events()) {
187
- * console.log(event.type, event);
188
- * }
189
- * ```
190
- *
191
- * The generator terminates when:
192
- * - `stop()` is called
193
- * - The agent process exits
194
- * - The consumer breaks out of the loop
195
- */
196
- async *events(): AsyncGenerator<SdkAgentEvent, void, undefined> {
197
- if (!this.process) {
198
- throw new Error("Client not started — call start() before events()");
199
- }
200
-
201
- if (this._stopped) {
202
- return;
203
- }
204
-
205
- const buffer: SdkAgentEvent[] = [];
206
- let resolve: ((value: void) => void) | null = null;
207
- let done = false;
208
-
209
- // When a new event arrives, either push to buffer or wake up the awaiting generator
210
- const listener = (event: SdkAgentEvent) => {
211
- buffer.push(event);
212
- if (resolve) {
213
- const r = resolve;
214
- resolve = null;
215
- r();
216
- }
217
- };
218
-
219
- // When the process exits, signal the generator to stop
220
- const onExit = () => {
221
- done = true;
222
- if (resolve) {
223
- const r = resolve;
224
- resolve = null;
225
- r();
226
- }
227
- };
228
-
229
- const unsubscribe = this.onEvent(listener);
230
- this.process.on("exit", onExit);
231
-
232
- try {
233
- while (!done && !this._stopped) {
234
- // Drain buffer first
235
- while (buffer.length > 0) {
236
- yield buffer.shift()!;
237
- }
238
-
239
- // If done after draining, break
240
- if (done || this._stopped) {
241
- break;
242
- }
243
-
244
- // Wait for next event or process exit
245
- await new Promise<void>((r) => {
246
- resolve = r;
247
- });
248
- }
249
-
250
- // Drain any remaining events that arrived with the exit signal
251
- while (buffer.length > 0) {
252
- yield buffer.shift()!;
253
- }
254
- } finally {
255
- unsubscribe();
256
- this.process?.removeListener("exit", onExit);
257
- }
258
- }
259
-
260
- /**
261
- * Get collected stderr output (useful for debugging).
262
- */
263
- getStderr(): string {
264
- return this.stderr;
265
- }
266
-
267
- // =========================================================================
268
- // Command Methods
269
- // =========================================================================
270
-
271
- /**
272
- * Send a prompt to the agent.
273
- * Returns immediately after sending; use onEvent() or events() to receive streaming events.
274
- * Use waitForIdle() to wait for completion.
275
- */
276
- async prompt(message: string, images?: ImageContent[]): Promise<void> {
277
- await this.send({ type: "prompt", message, images });
278
- }
279
-
280
- /**
281
- * Queue a steering message to interrupt the agent mid-run.
282
- */
283
- async steer(message: string, images?: ImageContent[]): Promise<void> {
284
- await this.send({ type: "steer", message, images });
285
- }
286
-
287
- /**
288
- * Queue a follow-up message to be processed after the agent finishes.
289
- */
290
- async followUp(message: string, images?: ImageContent[]): Promise<void> {
291
- await this.send({ type: "follow_up", message, images });
292
- }
293
-
294
- /**
295
- * Abort current operation.
296
- */
297
- async abort(): Promise<void> {
298
- await this.send({ type: "abort" });
299
- }
300
-
301
- /**
302
- * Start a new session, optionally with parent tracking.
303
- * @param parentSession - Optional parent session path for lineage tracking
304
- * @returns Object with `cancelled: true` if an extension cancelled the new session
305
- */
306
- async newSession(parentSession?: string): Promise<{ cancelled: boolean }> {
307
- const response = await this.send({ type: "new_session", parentSession });
308
- return this.getData(response);
309
- }
310
-
311
- /**
312
- * Get current session state.
313
- */
314
- async getState(): Promise<RpcSessionState> {
315
- const response = await this.send({ type: "get_state" });
316
- return this.getData(response);
317
- }
318
-
319
- /**
320
- * Set model by provider and ID.
321
- */
322
- async setModel(provider: string, modelId: string): Promise<{ provider: string; id: string }> {
323
- const response = await this.send({ type: "set_model", provider, modelId });
324
- return this.getData(response);
325
- }
326
-
327
- /**
328
- * Cycle to next model.
329
- */
330
- async cycleModel(): Promise<{
331
- model: { provider: string; id: string };
332
- thinkingLevel: ThinkingLevel;
333
- isScoped: boolean;
334
- } | null> {
335
- const response = await this.send({ type: "cycle_model" });
336
- return this.getData(response);
337
- }
338
-
339
- /**
340
- * Get list of available models.
341
- */
342
- async getAvailableModels(): Promise<ModelInfo[]> {
343
- const response = await this.send({ type: "get_available_models" });
344
- return this.getData<{ models: ModelInfo[] }>(response).models;
345
- }
346
-
347
- /**
348
- * Set thinking level.
349
- */
350
- async setThinkingLevel(level: ThinkingLevel): Promise<void> {
351
- await this.send({ type: "set_thinking_level", level });
352
- }
353
-
354
- /**
355
- * Cycle thinking level.
356
- */
357
- async cycleThinkingLevel(): Promise<{ level: ThinkingLevel } | null> {
358
- const response = await this.send({ type: "cycle_thinking_level" });
359
- return this.getData(response);
360
- }
361
-
362
- /**
363
- * Set steering mode.
364
- */
365
- async setSteeringMode(mode: "all" | "one-at-a-time"): Promise<void> {
366
- await this.send({ type: "set_steering_mode", mode });
367
- }
368
-
369
- /**
370
- * Set follow-up mode.
371
- */
372
- async setFollowUpMode(mode: "all" | "one-at-a-time"): Promise<void> {
373
- await this.send({ type: "set_follow_up_mode", mode });
374
- }
375
-
376
- /**
377
- * Compact session context.
378
- */
379
- async compact(customInstructions?: string): Promise<CompactionResult> {
380
- const response = await this.send({ type: "compact", customInstructions });
381
- return this.getData(response);
382
- }
383
-
384
- /**
385
- * Set auto-compaction enabled/disabled.
386
- */
387
- async setAutoCompaction(enabled: boolean): Promise<void> {
388
- await this.send({ type: "set_auto_compaction", enabled });
389
- }
390
-
391
- /**
392
- * Set auto-retry enabled/disabled.
393
- */
394
- async setAutoRetry(enabled: boolean): Promise<void> {
395
- await this.send({ type: "set_auto_retry", enabled });
396
- }
397
-
398
- /**
399
- * Abort in-progress retry.
400
- */
401
- async abortRetry(): Promise<void> {
402
- await this.send({ type: "abort_retry" });
403
- }
404
-
405
- /**
406
- * Execute a bash command.
407
- */
408
- async bash(command: string): Promise<BashResult> {
409
- const response = await this.send({ type: "bash", command });
410
- return this.getData(response);
411
- }
412
-
413
- /**
414
- * Abort running bash command.
415
- */
416
- async abortBash(): Promise<void> {
417
- await this.send({ type: "abort_bash" });
418
- }
419
-
420
- /**
421
- * Get session statistics.
422
- */
423
- async getSessionStats(): Promise<SessionStats> {
424
- const response = await this.send({ type: "get_session_stats" });
425
- return this.getData(response);
426
- }
427
-
428
- /**
429
- * Export session to HTML.
430
- */
431
- async exportHtml(outputPath?: string): Promise<{ path: string }> {
432
- const response = await this.send({ type: "export_html", outputPath });
433
- return this.getData(response);
434
- }
435
-
436
- /**
437
- * Switch to a different session file.
438
- * @returns Object with `cancelled: true` if an extension cancelled the switch
439
- */
440
- async switchSession(sessionPath: string): Promise<{ cancelled: boolean }> {
441
- const response = await this.send({ type: "switch_session", sessionPath });
442
- return this.getData(response);
443
- }
444
-
445
- /**
446
- * Fork from a specific message.
447
- * @returns Object with `text` (the message text) and `cancelled` (if extension cancelled)
448
- */
449
- async fork(entryId: string): Promise<{ text: string; cancelled: boolean }> {
450
- const response = await this.send({ type: "fork", entryId });
451
- return this.getData(response);
452
- }
453
-
454
- /**
455
- * Get messages available for forking.
456
- */
457
- async getForkMessages(): Promise<Array<{ entryId: string; text: string }>> {
458
- const response = await this.send({ type: "get_fork_messages" });
459
- return this.getData<{ messages: Array<{ entryId: string; text: string }> }>(response).messages;
460
- }
461
-
462
- /**
463
- * Get text of last assistant message.
464
- */
465
- async getLastAssistantText(): Promise<string | null> {
466
- const response = await this.send({ type: "get_last_assistant_text" });
467
- return this.getData<{ text: string | null }>(response).text;
468
- }
469
-
470
- /**
471
- * Set the session display name.
472
- */
473
- async setSessionName(name: string): Promise<void> {
474
- await this.send({ type: "set_session_name", name });
475
- }
476
-
477
- /**
478
- * Get all messages in the session.
479
- * Messages are returned as opaque objects — the internal structure may vary.
480
- */
481
- async getMessages(): Promise<unknown[]> {
482
- const response = await this.send({ type: "get_messages" });
483
- return this.getData<{ messages: unknown[] }>(response).messages;
484
- }
485
-
486
- /**
487
- * Get available commands (extension commands, prompt templates, skills).
488
- */
489
- async getCommands(): Promise<RpcSlashCommand[]> {
490
- const response = await this.send({ type: "get_commands" });
491
- return this.getData<{ commands: RpcSlashCommand[] }>(response).commands;
492
- }
493
-
494
- /**
495
- * Send a UI response to a pending extension_ui_request.
496
- * Fire-and-forget — no request/response correlation.
497
- */
498
- sendUIResponse(id: string, response: { value?: string; values?: string[]; confirmed?: boolean; cancelled?: boolean }): void {
499
- if (!this.process?.stdin) {
500
- throw new Error("Client not started");
501
- }
502
- this.process.stdin.write(serializeJsonLine({
503
- type: "extension_ui_response",
504
- id,
505
- ...response,
506
- }));
507
- }
508
-
509
- /**
510
- * Initialize a v2 protocol session. Must be sent as the first command.
511
- * Returns the negotiated protocol version, session ID, and server capabilities.
512
- */
513
- async init(options?: { clientId?: string }): Promise<RpcInitResult> {
514
- const response = await this.send({ type: "init", protocolVersion: 2, clientId: options?.clientId });
515
- return this.getData<RpcInitResult>(response);
516
- }
517
-
518
- /**
519
- * Request a graceful shutdown of the agent process.
520
- * Waits for the response before the process exits.
521
- */
522
- async shutdown(): Promise<void> {
523
- await this.send({ type: "shutdown" });
524
- // Wait for process to exit after shutdown acknowledgment
525
- if (this.process) {
526
- await new Promise<void>((resolve) => {
527
- const timeout = setTimeout(() => {
528
- this.process?.kill("SIGKILL");
529
- resolve();
530
- }, 5000);
531
- this.process?.on("exit", () => {
532
- clearTimeout(timeout);
533
- resolve();
534
- });
535
- });
536
- }
537
- }
538
-
539
- /**
540
- * Subscribe to specific event types (v2 only).
541
- * Pass ["*"] to receive all events, or a list of event type strings to filter.
542
- */
543
- async subscribe(events: string[]): Promise<void> {
544
- await this.send({ type: "subscribe", events });
545
- }
546
-
547
- // =========================================================================
548
- // Helpers
549
- // =========================================================================
550
-
551
- /**
552
- * Wait for agent to become idle (no streaming).
553
- * Resolves when agent_end event is received.
554
- */
555
- waitForIdle(timeout = 60000): Promise<void> {
556
- return new Promise((resolve, reject) => {
557
- const timer = setTimeout(() => {
558
- unsubscribe();
559
- reject(new Error(`Timeout waiting for agent to become idle. Stderr: ${this.stderr}`));
560
- }, timeout);
561
-
562
- const unsubscribe = this.onEvent((event) => {
563
- if (event.type === "agent_end") {
564
- clearTimeout(timer);
565
- unsubscribe();
566
- resolve();
567
- }
568
- });
569
- });
570
- }
571
-
572
- /**
573
- * Collect events until agent becomes idle.
574
- */
575
- collectEvents(timeout = 60000): Promise<SdkAgentEvent[]> {
576
- return new Promise((resolve, reject) => {
577
- const events: SdkAgentEvent[] = [];
578
- const timer = setTimeout(() => {
579
- unsubscribe();
580
- reject(new Error(`Timeout collecting events. Stderr: ${this.stderr}`));
581
- }, timeout);
582
-
583
- const unsubscribe = this.onEvent((event) => {
584
- events.push(event);
585
- if (event.type === "agent_end") {
586
- clearTimeout(timer);
587
- unsubscribe();
588
- resolve(events);
589
- }
590
- });
591
- });
592
- }
593
-
594
- /**
595
- * Send prompt and wait for completion, returning all events.
596
- */
597
- async promptAndWait(message: string, images?: ImageContent[], timeout = 60000): Promise<SdkAgentEvent[]> {
598
- const eventsPromise = this.collectEvents(timeout);
599
- await this.prompt(message, images);
600
- return eventsPromise;
601
- }
602
-
603
- // =========================================================================
604
- // Internal
605
- // =========================================================================
606
-
607
- private handleLine(line: string): void {
608
- try {
609
- const data = JSON.parse(line);
610
-
611
- // Check if it's a response to a pending request
612
- if (data.type === "response" && data.id && this.pendingRequests.has(data.id)) {
613
- const pending = this.pendingRequests.get(data.id)!;
614
- this.pendingRequests.delete(data.id);
615
- pending.resolve(data as RpcResponse);
616
- return;
617
- }
618
-
619
- // Otherwise it's an event — dispatch to listeners
620
- for (const listener of this.eventListeners) {
621
- listener(data as SdkAgentEvent);
622
- }
623
- } catch {
624
- // Ignore non-JSON lines
625
- }
626
- }
627
-
628
- private async send(command: RpcCommandBody): Promise<RpcResponse> {
629
- if (!this.process?.stdin) {
630
- throw new Error("Client not started");
631
- }
632
-
633
- const id = `req_${++this.requestId}`;
634
- const fullCommand = { ...command, id } as RpcCommand;
635
-
636
- return new Promise((resolve, reject) => {
637
- const timeout = setTimeout(() => {
638
- this.pendingRequests.delete(id);
639
- reject(new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`));
640
- }, 30000);
641
-
642
- this.pendingRequests.set(id, {
643
- resolve: (response) => {
644
- clearTimeout(timeout);
645
- resolve(response);
646
- },
647
- reject: (error) => {
648
- clearTimeout(timeout);
649
- reject(error);
650
- },
651
- });
652
-
653
- this.process!.stdin!.write(serializeJsonLine(fullCommand));
654
- });
655
- }
656
-
657
- private getData<T>(response: RpcResponse): T {
658
- if (!response.success) {
659
- const errorResponse = response as Extract<RpcResponse, { success: false }>;
660
- throw new Error(errorResponse.error);
661
- }
662
- // Type assertion: we trust response.data matches T based on the command sent.
663
- const successResponse = response as Extract<RpcResponse, { success: true; data: unknown }>;
664
- return successResponse.data as T;
665
- }
666
- }