@getpaseo/server 0.1.13 → 0.1.14

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 (65) hide show
  1. package/dist/server/client/daemon-client.d.ts +84 -77
  2. package/dist/server/client/daemon-client.d.ts.map +1 -1
  3. package/dist/server/client/daemon-client.js +252 -265
  4. package/dist/server/client/daemon-client.js.map +1 -1
  5. package/dist/server/server/agent/agent-manager.d.ts +2 -1
  6. package/dist/server/server/agent/agent-manager.d.ts.map +1 -1
  7. package/dist/server/server/agent/agent-manager.js +23 -0
  8. package/dist/server/server/agent/agent-manager.js.map +1 -1
  9. package/dist/server/server/agent/agent-sdk-types.d.ts +0 -15
  10. package/dist/server/server/agent/agent-sdk-types.d.ts.map +1 -1
  11. package/dist/server/server/agent/providers/claude-agent.d.ts.map +1 -1
  12. package/dist/server/server/agent/providers/claude-agent.js +268 -35
  13. package/dist/server/server/agent/providers/claude-agent.js.map +1 -1
  14. package/dist/server/server/agent/providers/codex-app-server-agent.d.ts.map +1 -1
  15. package/dist/server/server/agent/providers/codex-app-server-agent.js +85 -36
  16. package/dist/server/server/agent/providers/codex-app-server-agent.js.map +1 -1
  17. package/dist/server/server/bootstrap.d.ts.map +1 -1
  18. package/dist/server/server/bootstrap.js +3 -1
  19. package/dist/server/server/bootstrap.js.map +1 -1
  20. package/dist/server/server/daemon-version.d.ts +5 -0
  21. package/dist/server/server/daemon-version.d.ts.map +1 -0
  22. package/dist/server/server/daemon-version.js +22 -0
  23. package/dist/server/server/daemon-version.js.map +1 -0
  24. package/dist/server/server/dictation/dictation-stream-manager.d.ts +1 -0
  25. package/dist/server/server/dictation/dictation-stream-manager.d.ts.map +1 -1
  26. package/dist/server/server/dictation/dictation-stream-manager.js +32 -1
  27. package/dist/server/server/dictation/dictation-stream-manager.js.map +1 -1
  28. package/dist/server/server/package-version.d.ts +13 -0
  29. package/dist/server/server/package-version.d.ts.map +1 -0
  30. package/dist/server/server/package-version.js +47 -0
  31. package/dist/server/server/package-version.js.map +1 -0
  32. package/dist/server/server/persisted-config.d.ts +2 -2
  33. package/dist/server/server/pid-lock.d.ts.map +1 -1
  34. package/dist/server/server/pid-lock.js +16 -2
  35. package/dist/server/server/pid-lock.js.map +1 -1
  36. package/dist/server/server/session.d.ts +20 -20
  37. package/dist/server/server/session.d.ts.map +1 -1
  38. package/dist/server/server/session.js +871 -798
  39. package/dist/server/server/session.js.map +1 -1
  40. package/dist/server/server/websocket-server.d.ts +5 -1
  41. package/dist/server/server/websocket-server.d.ts.map +1 -1
  42. package/dist/server/server/websocket-server.js +27 -16
  43. package/dist/server/server/websocket-server.js.map +1 -1
  44. package/dist/server/shared/agent-attention-notification.d.ts +40 -0
  45. package/dist/server/shared/agent-attention-notification.d.ts.map +1 -0
  46. package/dist/server/shared/agent-attention-notification.js +130 -0
  47. package/dist/server/shared/agent-attention-notification.js.map +1 -0
  48. package/dist/server/shared/messages.d.ts +886 -410
  49. package/dist/server/shared/messages.d.ts.map +1 -1
  50. package/dist/server/shared/messages.js +272 -267
  51. package/dist/server/shared/messages.js.map +1 -1
  52. package/dist/server/utils/checkout-git.d.ts +3 -0
  53. package/dist/server/utils/checkout-git.d.ts.map +1 -1
  54. package/dist/server/utils/checkout-git.js +102 -23
  55. package/dist/server/utils/checkout-git.js.map +1 -1
  56. package/dist/server/utils/directory-suggestions.d.ts +15 -0
  57. package/dist/server/utils/directory-suggestions.d.ts.map +1 -1
  58. package/dist/server/utils/directory-suggestions.js +348 -21
  59. package/dist/server/utils/directory-suggestions.js.map +1 -1
  60. package/dist/server/utils/worktree-metadata.d.ts +4 -4
  61. package/dist/server/utils/worktree.d.ts +1 -0
  62. package/dist/server/utils/worktree.d.ts.map +1 -1
  63. package/dist/server/utils/worktree.js +41 -77
  64. package/dist/server/utils/worktree.js.map +1 -1
  65. package/package.json +2 -2
@@ -1,10 +1,10 @@
1
- import { AgentCreateFailedStatusPayloadSchema, AgentCreatedStatusPayloadSchema, AgentRefreshedStatusPayloadSchema, AgentResumedStatusPayloadSchema, RestartRequestedStatusPayloadSchema, SessionInboundMessageSchema, WSOutboundMessageSchema, } from "../shared/messages.js";
2
- import { getAgentProviderDefinition } from "../server/agent/provider-manifest.js";
3
- import { isRelayClientWebSocketUrl } from "../shared/daemon-endpoints.js";
4
- import { asUint8Array, decodeBinaryMuxFrame, encodeBinaryMuxFrame, BinaryMuxChannel, TerminalBinaryFlags, TerminalBinaryMessageType, } from "../shared/binary-mux.js";
5
- import { encodeTerminalKeyInput, } from "../shared/terminal-key-input.js";
6
- import { TerminalStreamManager, } from "./daemon-client-terminal-stream-manager.js";
7
- import { createRelayE2eeTransportFactory, createWebSocketTransportFactory, decodeMessageData, defaultWebSocketFactory, describeTransportClose, describeTransportError, encodeUtf8String, safeRandomId, } from "./daemon-client-transport.js";
1
+ import { AgentCreateFailedStatusPayloadSchema, AgentCreatedStatusPayloadSchema, AgentRefreshedStatusPayloadSchema, AgentResumedStatusPayloadSchema, RestartRequestedStatusPayloadSchema, SessionInboundMessageSchema, WSOutboundMessageSchema, } from '../shared/messages.js';
2
+ import { getAgentProviderDefinition } from '../server/agent/provider-manifest.js';
3
+ import { isRelayClientWebSocketUrl } from '../shared/daemon-endpoints.js';
4
+ import { asUint8Array, decodeBinaryMuxFrame, encodeBinaryMuxFrame, BinaryMuxChannel, TerminalBinaryFlags, TerminalBinaryMessageType, } from '../shared/binary-mux.js';
5
+ import { encodeTerminalKeyInput } from '../shared/terminal-key-input.js';
6
+ import { TerminalStreamManager, } from './daemon-client-terminal-stream-manager.js';
7
+ import { createRelayE2eeTransportFactory, createWebSocketTransportFactory, decodeMessageData, defaultWebSocketFactory, describeTransportClose, describeTransportError, encodeUtf8String, safeRandomId, } from './daemon-client-transport.js';
8
8
  const consoleLogger = {
9
9
  debug: (obj, msg) => console.debug(msg, obj),
10
10
  info: (obj, msg) => console.info(msg, obj),
@@ -14,7 +14,7 @@ const consoleLogger = {
14
14
  class DaemonRpcError extends Error {
15
15
  constructor(params) {
16
16
  super(params.error);
17
- this.name = "DaemonRpcError";
17
+ this.name = 'DaemonRpcError';
18
18
  this.requestId = params.requestId;
19
19
  this.requestType = params.requestType;
20
20
  this.code = params.code;
@@ -28,7 +28,7 @@ const DEFAULT_DICTATION_FINISH_ACCEPT_TIMEOUT_MS = 15000;
28
28
  const DEFAULT_DICTATION_FINISH_FALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
29
29
  const DEFAULT_DICTATION_FINISH_TIMEOUT_GRACE_MS = 5000;
30
30
  function isWaiterTimeoutError(error) {
31
- return (error instanceof Error && error.message.startsWith("Timeout waiting for message"));
31
+ return error instanceof Error && error.message.startsWith('Timeout waiting for message');
32
32
  }
33
33
  export class DaemonClient {
34
34
  constructor(config) {
@@ -49,7 +49,7 @@ export class DaemonClient {
49
49
  this.connectResolve = null;
50
50
  this.connectReject = null;
51
51
  this.lastErrorValue = null;
52
- this.connectionState = { status: "idle" };
52
+ this.connectionState = { status: 'idle' };
53
53
  this.checkoutDiffSubscriptions = new Map();
54
54
  this.terminalDirectorySubscriptions = new Set();
55
55
  this.pendingSendQueue = [];
@@ -72,9 +72,9 @@ export class DaemonClient {
72
72
  if (isRelayClientWebSocketUrl(this.config.url)) {
73
73
  try {
74
74
  const parsed = new URL(this.config.url);
75
- if (!parsed.searchParams.get("clientId")) {
75
+ if (!parsed.searchParams.get('clientId')) {
76
76
  this.relayClientId = `clt_${safeRandomId()}`;
77
- parsed.searchParams.set("clientId", this.relayClientId);
77
+ parsed.searchParams.set('clientId', this.relayClientId);
78
78
  this.config.url = parsed.toString();
79
79
  }
80
80
  }
@@ -87,7 +87,7 @@ export class DaemonClient {
87
87
  // Connection
88
88
  // ============================================================================
89
89
  async connect() {
90
- if (this.connectionState.status === "connected") {
90
+ if (this.connectionState.status === 'connected') {
91
91
  return;
92
92
  }
93
93
  if (this.connectPromise) {
@@ -103,15 +103,15 @@ export class DaemonClient {
103
103
  }
104
104
  attemptConnect() {
105
105
  if (!this.shouldReconnect) {
106
- this.rejectConnect(new Error("Daemon client is closed"));
106
+ this.rejectConnect(new Error('Daemon client is closed'));
107
107
  return;
108
108
  }
109
- if (this.connectionState.status === "connecting") {
109
+ if (this.connectionState.status === 'connecting') {
110
110
  return;
111
111
  }
112
112
  const headers = {};
113
113
  if (this.config.authHeader) {
114
- headers["Authorization"] = this.config.authHeader;
114
+ headers['Authorization'] = this.config.authHeader;
115
115
  }
116
116
  try {
117
117
  // If we reconnect while the previous socket is still open (common in browsers
@@ -121,13 +121,12 @@ export class DaemonClient {
121
121
  this.disposeTransport();
122
122
  const baseTransportFactory = this.config.transportFactory ??
123
123
  createWebSocketTransportFactory(this.config.webSocketFactory ?? defaultWebSocketFactory);
124
- const shouldUseRelayE2ee = this.config.e2ee?.enabled === true &&
125
- isRelayClientWebSocketUrl(this.config.url);
124
+ const shouldUseRelayE2ee = this.config.e2ee?.enabled === true && isRelayClientWebSocketUrl(this.config.url);
126
125
  let transportFactory = baseTransportFactory;
127
126
  if (shouldUseRelayE2ee) {
128
127
  const daemonPublicKeyB64 = this.config.e2ee?.daemonPublicKeyB64;
129
128
  if (!daemonPublicKeyB64) {
130
- throw new Error("daemonPublicKeyB64 is required for relay E2EE");
129
+ throw new Error('daemonPublicKeyB64 is required for relay E2EE');
131
130
  }
132
131
  transportFactory = createRelayE2eeTransportFactory({
133
132
  baseFactory: baseTransportFactory,
@@ -138,7 +137,7 @@ export class DaemonClient {
138
137
  const transport = transportFactory({ url: this.config.url, headers });
139
138
  this.transport = transport;
140
139
  this.updateConnectionState({
141
- status: "connecting",
140
+ status: 'connecting',
142
141
  attempt: this.reconnectAttempt,
143
142
  });
144
143
  this.transportCleanup = [
@@ -149,7 +148,7 @@ export class DaemonClient {
149
148
  }
150
149
  this.lastErrorValue = null;
151
150
  this.reconnectAttempt = 0;
152
- this.updateConnectionState({ status: "connected" });
151
+ this.updateConnectionState({ status: 'connected' });
153
152
  this.resubscribeCheckoutDiffSubscriptions();
154
153
  this.resubscribeTerminalDirectorySubscriptions();
155
154
  this.flushPendingSendQueue();
@@ -161,10 +160,10 @@ export class DaemonClient {
161
160
  this.pendingGenericTransportErrorTimeout = null;
162
161
  }
163
162
  const closeRecord = event;
164
- const closeCode = closeRecord && typeof closeRecord === "object" && typeof closeRecord.code === "number"
163
+ const closeCode = closeRecord && typeof closeRecord === 'object' && typeof closeRecord.code === 'number'
165
164
  ? closeRecord.code
166
165
  : null;
167
- const closeReason = closeRecord && typeof closeRecord === "object" && typeof closeRecord.reason === "string"
166
+ const closeReason = closeRecord && typeof closeRecord === 'object' && typeof closeRecord.reason === 'string'
168
167
  ? closeRecord.reason
169
168
  : null;
170
169
  const reason = describeTransportClose(event);
@@ -172,7 +171,7 @@ export class DaemonClient {
172
171
  this.lastErrorValue = reason;
173
172
  }
174
173
  this.updateConnectionState({
175
- status: "disconnected",
174
+ status: 'disconnected',
176
175
  ...(reason ? { reason } : {}),
177
176
  });
178
177
  // When connecting over the relay, only one client connection is allowed at a time.
@@ -180,18 +179,18 @@ export class DaemonClient {
180
179
  // connection (which causes flapping where both sides repeatedly replace each other).
181
180
  if (isRelayClientWebSocketUrl(this.config.url) &&
182
181
  closeCode === 1008 &&
183
- (closeReason ?? reason) === "Replaced by new connection") {
182
+ (closeReason ?? reason) === 'Replaced by new connection') {
184
183
  this.shouldReconnect = false;
185
- this.clearWaiters(new Error(reason ?? "Replaced by new connection"));
186
- this.rejectPendingSendQueue(new Error(reason ?? "Replaced by new connection"));
187
- this.rejectConnect(new Error(reason ?? "Replaced by new connection"));
184
+ this.clearWaiters(new Error(reason ?? 'Replaced by new connection'));
185
+ this.rejectPendingSendQueue(new Error(reason ?? 'Replaced by new connection'));
186
+ this.rejectConnect(new Error(reason ?? 'Replaced by new connection'));
188
187
  return;
189
188
  }
190
189
  this.scheduleReconnect(reason);
191
190
  }),
192
191
  transport.onError((event) => {
193
192
  const reason = describeTransportError(event);
194
- const isGeneric = reason === "Transport error";
193
+ const isGeneric = reason === 'Transport error';
195
194
  // Browser WebSocket.onerror often provides no useful details and is followed
196
195
  // by a close event (often with code 1006). Prefer surfacing the close details
197
196
  // instead of immediately disconnecting with a generic "Transport error".
@@ -200,10 +199,10 @@ export class DaemonClient {
200
199
  if (!this.pendingGenericTransportErrorTimeout) {
201
200
  this.pendingGenericTransportErrorTimeout = setTimeout(() => {
202
201
  this.pendingGenericTransportErrorTimeout = null;
203
- if (this.connectionState.status === "connected" ||
204
- this.connectionState.status === "connecting") {
202
+ if (this.connectionState.status === 'connected' ||
203
+ this.connectionState.status === 'connecting') {
205
204
  this.lastErrorValue = reason;
206
- this.updateConnectionState({ status: "disconnected", reason });
205
+ this.updateConnectionState({ status: 'disconnected', reason });
207
206
  this.scheduleReconnect(reason);
208
207
  }
209
208
  }, 250);
@@ -215,14 +214,14 @@ export class DaemonClient {
215
214
  this.pendingGenericTransportErrorTimeout = null;
216
215
  }
217
216
  this.lastErrorValue = reason;
218
- this.updateConnectionState({ status: "disconnected", reason });
217
+ this.updateConnectionState({ status: 'disconnected', reason });
219
218
  this.scheduleReconnect(reason);
220
219
  }),
221
220
  transport.onMessage((data) => this.handleTransportMessage(data)),
222
221
  ];
223
222
  }
224
223
  catch (error) {
225
- const message = error instanceof Error ? error.message : "Failed to connect";
224
+ const message = error instanceof Error ? error.message : 'Failed to connect';
226
225
  this.lastErrorValue = message;
227
226
  this.scheduleReconnect(message);
228
227
  this.rejectConnect(error instanceof Error ? error : new Error(message));
@@ -253,20 +252,20 @@ export class DaemonClient {
253
252
  clearTimeout(this.reconnectTimeout);
254
253
  this.reconnectTimeout = null;
255
254
  }
256
- this.disposeTransport(1000, "Client closed");
257
- this.clearWaiters(new Error("Daemon client closed"));
255
+ this.disposeTransport(1000, 'Client closed');
256
+ this.clearWaiters(new Error('Daemon client closed'));
258
257
  this.terminalStreams.clearAll();
259
258
  this.updateConnectionState({
260
- status: "disconnected",
261
- reason: "client_closed",
259
+ status: 'disconnected',
260
+ reason: 'client_closed',
262
261
  });
263
262
  }
264
263
  ensureConnected() {
265
264
  if (!this.shouldReconnect) {
266
265
  this.shouldReconnect = true;
267
266
  }
268
- if (this.connectionState.status === "connected" ||
269
- this.connectionState.status === "connecting") {
267
+ if (this.connectionState.status === 'connected' ||
268
+ this.connectionState.status === 'connecting') {
270
269
  return;
271
270
  }
272
271
  void this.connect();
@@ -282,10 +281,10 @@ export class DaemonClient {
282
281
  };
283
282
  }
284
283
  get isConnected() {
285
- return this.connectionState.status === "connected";
284
+ return this.connectionState.status === 'connected';
286
285
  }
287
286
  get isConnecting() {
288
- return this.connectionState.status === "connecting";
287
+ return this.connectionState.status === 'connecting';
289
288
  }
290
289
  get lastError() {
291
290
  return this.lastErrorValue;
@@ -304,7 +303,7 @@ export class DaemonClient {
304
303
  };
305
304
  }
306
305
  on(arg1, arg2) {
307
- if (typeof arg1 === "function") {
306
+ if (typeof arg1 === 'function') {
308
307
  return this.subscribe(arg1);
309
308
  }
310
309
  const type = arg1;
@@ -333,7 +332,7 @@ export class DaemonClient {
333
332
  * For RPC methods that wait for responses, use `sendSessionMessageOrThrow` instead.
334
333
  */
335
334
  sendSessionMessage(message) {
336
- if (!this.transport || this.connectionState.status !== "connected") {
335
+ if (!this.transport || this.connectionState.status !== 'connected') {
337
336
  if (this.config.suppressSendErrors) {
338
337
  return;
339
338
  }
@@ -341,7 +340,7 @@ export class DaemonClient {
341
340
  }
342
341
  const payload = SessionInboundMessageSchema.parse(message);
343
342
  try {
344
- this.transport.send(JSON.stringify({ type: "session", message: payload }));
343
+ this.transport.send(JSON.stringify({ type: 'session', message: payload }));
345
344
  }
346
345
  catch (error) {
347
346
  if (this.config.suppressSendErrors) {
@@ -351,7 +350,7 @@ export class DaemonClient {
351
350
  }
352
351
  }
353
352
  sendBinaryFrame(frame) {
354
- if (!this.transport || this.connectionState.status !== "connected") {
353
+ if (!this.transport || this.connectionState.status !== 'connected') {
355
354
  if (this.config.suppressSendErrors) {
356
355
  return;
357
356
  }
@@ -376,13 +375,13 @@ export class DaemonClient {
376
375
  sendSessionMessageOrThrow(message) {
377
376
  const status = this.connectionState.status;
378
377
  // If connected, send immediately
379
- if (this.transport && status === "connected") {
378
+ if (this.transport && status === 'connected') {
380
379
  const payload = SessionInboundMessageSchema.parse(message);
381
- this.transport.send(JSON.stringify({ type: "session", message: payload }));
380
+ this.transport.send(JSON.stringify({ type: 'session', message: payload }));
382
381
  return Promise.resolve();
383
382
  }
384
383
  // If connecting, queue the message to be sent once connected
385
- if (status === "connecting") {
384
+ if (status === 'connecting') {
386
385
  return new Promise((resolve, reject) => {
387
386
  const timeoutHandle = setTimeout(() => {
388
387
  // Remove from queue
@@ -407,13 +406,13 @@ export class DaemonClient {
407
406
  for (const pending of queue) {
408
407
  clearTimeout(pending.timeoutHandle);
409
408
  try {
410
- if (this.transport && this.connectionState.status === "connected") {
409
+ if (this.transport && this.connectionState.status === 'connected') {
411
410
  const payload = SessionInboundMessageSchema.parse(pending.message);
412
- this.transport.send(JSON.stringify({ type: "session", message: payload }));
411
+ this.transport.send(JSON.stringify({ type: 'session', message: payload }));
413
412
  pending.resolve();
414
413
  }
415
414
  else {
416
- pending.reject(new Error("Connection lost before message could be sent"));
415
+ pending.reject(new Error('Connection lost before message could be sent'));
417
416
  }
418
417
  }
419
418
  catch (error) {
@@ -434,9 +433,9 @@ export class DaemonClient {
434
433
  }
435
434
  async sendRequest(params) {
436
435
  const { promise, cancel } = this.waitForWithCancel((msg) => {
437
- if (msg.type === "rpc_error" && msg.payload.requestId === params.requestId) {
436
+ if (msg.type === 'rpc_error' && msg.payload.requestId === params.requestId) {
438
437
  return {
439
- kind: "error",
438
+ kind: 'error',
440
439
  error: new DaemonRpcError({
441
440
  requestId: msg.payload.requestId,
442
441
  error: msg.payload.error,
@@ -449,7 +448,7 @@ export class DaemonClient {
449
448
  if (value === null) {
450
449
  return null;
451
450
  }
452
- return { kind: "ok", value };
451
+ return { kind: 'ok', value };
453
452
  }, params.timeout, params.options);
454
453
  try {
455
454
  await this.sendSessionMessageOrThrow(params.message);
@@ -461,7 +460,7 @@ export class DaemonClient {
461
460
  throw err;
462
461
  }
463
462
  const result = await promise;
464
- if (result.kind === "error") {
463
+ if (result.kind === 'error') {
465
464
  throw result.error;
466
465
  }
467
466
  return result.value;
@@ -504,23 +503,23 @@ export class DaemonClient {
504
503
  });
505
504
  }
506
505
  sendSessionMessageStrict(message) {
507
- if (!this.transport || this.connectionState.status !== "connected") {
508
- throw new Error("Transport not connected");
506
+ if (!this.transport || this.connectionState.status !== 'connected') {
507
+ throw new Error('Transport not connected');
509
508
  }
510
509
  const payload = SessionInboundMessageSchema.parse(message);
511
510
  try {
512
- this.transport.send(JSON.stringify({ type: "session", message: payload }));
511
+ this.transport.send(JSON.stringify({ type: 'session', message: payload }));
513
512
  }
514
513
  catch (error) {
515
514
  throw error instanceof Error ? error : new Error(String(error));
516
515
  }
517
516
  }
518
517
  clearAgentAttention(agentId) {
519
- this.sendSessionMessage({ type: "clear_agent_attention", agentId });
518
+ this.sendSessionMessage({ type: 'clear_agent_attention', agentId });
520
519
  }
521
520
  sendHeartbeat(params) {
522
521
  this.sendSessionMessage({
523
- type: "client_heartbeat",
522
+ type: 'client_heartbeat',
524
523
  deviceType: params.deviceType,
525
524
  focusedAgentId: params.focusedAgentId,
526
525
  lastActivityAt: params.lastActivityAt,
@@ -530,26 +529,25 @@ export class DaemonClient {
530
529
  }
531
530
  registerPushToken(token) {
532
531
  this.sendSessionMessage({
533
- type: "register_push_token",
532
+ type: 'register_push_token',
534
533
  token,
535
534
  });
536
535
  }
537
536
  async ping(params) {
538
- const requestId = params?.requestId ??
539
- `ping-${Date.now()}-${Math.random().toString(36).slice(2)}`;
537
+ const requestId = params?.requestId ?? `ping-${Date.now()}-${Math.random().toString(36).slice(2)}`;
540
538
  const clientSentAt = Date.now();
541
539
  const payload = await this.sendRequest({
542
540
  requestId,
543
- message: { type: "ping", requestId, clientSentAt },
541
+ message: { type: 'ping', requestId, clientSentAt },
544
542
  timeout: params?.timeoutMs ?? 5000,
545
543
  select: (msg) => {
546
- if (msg.type !== "pong")
544
+ if (msg.type !== 'pong')
547
545
  return null;
548
546
  if (msg.payload.requestId !== requestId)
549
547
  return null;
550
- if (typeof msg.payload.serverReceivedAt !== "number")
548
+ if (typeof msg.payload.serverReceivedAt !== 'number')
551
549
  return null;
552
- if (typeof msg.payload.serverSentAt !== "number")
550
+ if (typeof msg.payload.serverSentAt !== 'number')
553
551
  return null;
554
552
  return msg.payload;
555
553
  },
@@ -568,7 +566,7 @@ export class DaemonClient {
568
566
  async fetchAgents(options) {
569
567
  const resolvedRequestId = this.createRequestId(options?.requestId);
570
568
  const message = SessionInboundMessageSchema.parse({
571
- type: "fetch_agents_request",
569
+ type: 'fetch_agents_request',
572
570
  requestId: resolvedRequestId,
573
571
  ...(options?.filter ? { filter: options.filter } : {}),
574
572
  ...(options?.sort ? { sort: options.sort } : {}),
@@ -581,7 +579,7 @@ export class DaemonClient {
581
579
  timeout: 10000,
582
580
  options: { skipQueue: true },
583
581
  select: (msg) => {
584
- if (msg.type !== "fetch_agents_response") {
582
+ if (msg.type !== 'fetch_agents_response') {
585
583
  return null;
586
584
  }
587
585
  if (msg.payload.requestId !== resolvedRequestId) {
@@ -594,7 +592,7 @@ export class DaemonClient {
594
592
  async fetchAgent(agentId, requestId) {
595
593
  const resolvedRequestId = this.createRequestId(requestId);
596
594
  const message = SessionInboundMessageSchema.parse({
597
- type: "fetch_agent_request",
595
+ type: 'fetch_agent_request',
598
596
  requestId: resolvedRequestId,
599
597
  agentId,
600
598
  });
@@ -604,7 +602,7 @@ export class DaemonClient {
604
602
  timeout: 10000,
605
603
  options: { skipQueue: true },
606
604
  select: (msg) => {
607
- if (msg.type !== "fetch_agent_response") {
605
+ if (msg.type !== 'fetch_agent_response') {
608
606
  return null;
609
607
  }
610
608
  if (msg.payload.requestId !== resolvedRequestId) {
@@ -624,7 +622,7 @@ export class DaemonClient {
624
622
  }
625
623
  for (const [subscriptionId, subscription] of this.checkoutDiffSubscriptions) {
626
624
  const message = SessionInboundMessageSchema.parse({
627
- type: "subscribe_checkout_diff_request",
625
+ type: 'subscribe_checkout_diff_request',
628
626
  subscriptionId,
629
627
  cwd: subscription.cwd,
630
628
  compare: subscription.compare,
@@ -639,7 +637,7 @@ export class DaemonClient {
639
637
  }
640
638
  for (const cwd of this.terminalDirectorySubscriptions) {
641
639
  this.sendSessionMessage({
642
- type: "subscribe_terminals_request",
640
+ type: 'subscribe_terminals_request',
643
641
  cwd,
644
642
  });
645
643
  }
@@ -651,14 +649,12 @@ export class DaemonClient {
651
649
  const requestId = this.createRequestId(options.requestId);
652
650
  const config = resolveAgentConfig(options);
653
651
  const message = SessionInboundMessageSchema.parse({
654
- type: "create_agent_request",
652
+ type: 'create_agent_request',
655
653
  requestId,
656
654
  config,
657
655
  ...(options.initialPrompt ? { initialPrompt: options.initialPrompt } : {}),
658
656
  ...(options.outputSchema ? { outputSchema: options.outputSchema } : {}),
659
- ...(options.images && options.images.length > 0
660
- ? { images: options.images }
661
- : {}),
657
+ ...(options.images && options.images.length > 0 ? { images: options.images } : {}),
662
658
  ...(options.git ? { git: options.git } : {}),
663
659
  ...(options.worktreeName ? { worktreeName: options.worktreeName } : {}),
664
660
  ...(options.labels && Object.keys(options.labels).length > 0
@@ -671,7 +667,7 @@ export class DaemonClient {
671
667
  timeout: 15000,
672
668
  options: { skipQueue: true },
673
669
  select: (msg) => {
674
- if (msg.type !== "status") {
670
+ if (msg.type !== 'status') {
675
671
  return null;
676
672
  }
677
673
  const created = AgentCreatedStatusPayloadSchema.safeParse(msg.payload);
@@ -685,7 +681,7 @@ export class DaemonClient {
685
681
  return null;
686
682
  },
687
683
  });
688
- if (status.status === "agent_create_failed") {
684
+ if (status.status === 'agent_create_failed') {
689
685
  throw new Error(status.error);
690
686
  }
691
687
  return status.agent;
@@ -693,7 +689,7 @@ export class DaemonClient {
693
689
  async deleteAgent(agentId) {
694
690
  const requestId = this.createRequestId();
695
691
  const message = SessionInboundMessageSchema.parse({
696
- type: "delete_agent_request",
692
+ type: 'delete_agent_request',
697
693
  agentId,
698
694
  requestId,
699
695
  });
@@ -703,7 +699,7 @@ export class DaemonClient {
703
699
  timeout: 10000,
704
700
  options: { skipQueue: true },
705
701
  select: (msg) => {
706
- if (msg.type !== "agent_deleted") {
702
+ if (msg.type !== 'agent_deleted') {
707
703
  return null;
708
704
  }
709
705
  if (msg.payload.requestId !== requestId) {
@@ -716,7 +712,7 @@ export class DaemonClient {
716
712
  async archiveAgent(agentId) {
717
713
  const requestId = this.createRequestId();
718
714
  const message = SessionInboundMessageSchema.parse({
719
- type: "archive_agent_request",
715
+ type: 'archive_agent_request',
720
716
  agentId,
721
717
  requestId,
722
718
  });
@@ -726,7 +722,7 @@ export class DaemonClient {
726
722
  timeout: 10000,
727
723
  options: { skipQueue: true },
728
724
  select: (msg) => {
729
- if (msg.type !== "agent_archived") {
725
+ if (msg.type !== 'agent_archived') {
730
726
  return null;
731
727
  }
732
728
  if (msg.payload.requestId !== requestId) {
@@ -740,7 +736,7 @@ export class DaemonClient {
740
736
  async updateAgent(agentId, updates) {
741
737
  const requestId = this.createRequestId();
742
738
  const message = SessionInboundMessageSchema.parse({
743
- type: "update_agent_request",
739
+ type: 'update_agent_request',
744
740
  agentId,
745
741
  ...(updates.name !== undefined ? { name: updates.name } : {}),
746
742
  ...(updates.labels && Object.keys(updates.labels).length > 0
@@ -754,7 +750,7 @@ export class DaemonClient {
754
750
  timeout: 10000,
755
751
  options: { skipQueue: true },
756
752
  select: (msg) => {
757
- if (msg.type !== "update_agent_response") {
753
+ if (msg.type !== 'update_agent_response') {
758
754
  return null;
759
755
  }
760
756
  if (msg.payload.requestId !== requestId) {
@@ -764,13 +760,13 @@ export class DaemonClient {
764
760
  },
765
761
  });
766
762
  if (!payload.accepted) {
767
- throw new Error(payload.error ?? "updateAgent rejected");
763
+ throw new Error(payload.error ?? 'updateAgent rejected');
768
764
  }
769
765
  }
770
766
  async resumeAgent(handle, overrides) {
771
767
  const requestId = this.createRequestId();
772
768
  const message = SessionInboundMessageSchema.parse({
773
- type: "resume_agent_request",
769
+ type: 'resume_agent_request',
774
770
  requestId,
775
771
  handle,
776
772
  ...(overrides ? { overrides } : {}),
@@ -781,7 +777,7 @@ export class DaemonClient {
781
777
  timeout: 15000,
782
778
  options: { skipQueue: true },
783
779
  select: (msg) => {
784
- if (msg.type !== "status") {
780
+ if (msg.type !== 'status') {
785
781
  return null;
786
782
  }
787
783
  const resumed = AgentResumedStatusPayloadSchema.safeParse(msg.payload);
@@ -796,7 +792,7 @@ export class DaemonClient {
796
792
  async refreshAgent(agentId, requestId) {
797
793
  const resolvedRequestId = this.createRequestId(requestId);
798
794
  const message = SessionInboundMessageSchema.parse({
799
- type: "refresh_agent_request",
795
+ type: 'refresh_agent_request',
800
796
  agentId,
801
797
  requestId: resolvedRequestId,
802
798
  });
@@ -806,7 +802,7 @@ export class DaemonClient {
806
802
  timeout: 15000,
807
803
  options: { skipQueue: true },
808
804
  select: (msg) => {
809
- if (msg.type !== "status") {
805
+ if (msg.type !== 'status') {
810
806
  return null;
811
807
  }
812
808
  const refreshed = AgentRefreshedStatusPayloadSchema.safeParse(msg.payload);
@@ -820,12 +816,12 @@ export class DaemonClient {
820
816
  async fetchAgentTimeline(agentId, options = {}) {
821
817
  const resolvedRequestId = this.createRequestId(options.requestId);
822
818
  const message = SessionInboundMessageSchema.parse({
823
- type: "fetch_agent_timeline_request",
819
+ type: 'fetch_agent_timeline_request',
824
820
  agentId,
825
821
  requestId: resolvedRequestId,
826
822
  ...(options.direction ? { direction: options.direction } : {}),
827
823
  ...(options.cursor ? { cursor: options.cursor } : {}),
828
- ...(typeof options.limit === "number" ? { limit: options.limit } : {}),
824
+ ...(typeof options.limit === 'number' ? { limit: options.limit } : {}),
829
825
  ...(options.projection ? { projection: options.projection } : {}),
830
826
  });
831
827
  const payload = await this.sendRequest({
@@ -834,7 +830,7 @@ export class DaemonClient {
834
830
  timeout: 15000,
835
831
  options: { skipQueue: true },
836
832
  select: (msg) => {
837
- if (msg.type !== "fetch_agent_timeline_response") {
833
+ if (msg.type !== 'fetch_agent_timeline_response') {
838
834
  return null;
839
835
  }
840
836
  if (msg.payload.requestId !== resolvedRequestId) {
@@ -855,7 +851,7 @@ export class DaemonClient {
855
851
  const requestId = this.createRequestId();
856
852
  const messageId = options?.messageId ?? crypto.randomUUID();
857
853
  const message = SessionInboundMessageSchema.parse({
858
- type: "send_agent_message_request",
854
+ type: 'send_agent_message_request',
859
855
  requestId,
860
856
  agentId,
861
857
  text,
@@ -868,7 +864,7 @@ export class DaemonClient {
868
864
  timeout: 15000,
869
865
  options: { skipQueue: true },
870
866
  select: (msg) => {
871
- if (msg.type !== "send_agent_message_response") {
867
+ if (msg.type !== 'send_agent_message_response') {
872
868
  return null;
873
869
  }
874
870
  if (msg.payload.requestId !== requestId) {
@@ -878,19 +874,19 @@ export class DaemonClient {
878
874
  },
879
875
  });
880
876
  if (!payload.accepted) {
881
- throw new Error(payload.error ?? "sendAgentMessage rejected");
877
+ throw new Error(payload.error ?? 'sendAgentMessage rejected');
882
878
  }
883
879
  }
884
880
  async sendMessage(agentId, text, options) {
885
881
  await this.sendAgentMessage(agentId, text, options);
886
882
  }
887
883
  async cancelAgent(agentId) {
888
- this.sendSessionMessage({ type: "cancel_agent_request", agentId });
884
+ this.sendSessionMessage({ type: 'cancel_agent_request', agentId });
889
885
  }
890
886
  async setAgentMode(agentId, modeId) {
891
887
  const requestId = this.createRequestId();
892
888
  const message = SessionInboundMessageSchema.parse({
893
- type: "set_agent_mode_request",
889
+ type: 'set_agent_mode_request',
894
890
  agentId,
895
891
  modeId,
896
892
  requestId,
@@ -901,7 +897,7 @@ export class DaemonClient {
901
897
  timeout: 15000,
902
898
  options: { skipQueue: true },
903
899
  select: (msg) => {
904
- if (msg.type !== "set_agent_mode_response") {
900
+ if (msg.type !== 'set_agent_mode_response') {
905
901
  return null;
906
902
  }
907
903
  if (msg.payload.requestId !== requestId) {
@@ -911,13 +907,13 @@ export class DaemonClient {
911
907
  },
912
908
  });
913
909
  if (!payload.accepted) {
914
- throw new Error(payload.error ?? "setAgentMode rejected");
910
+ throw new Error(payload.error ?? 'setAgentMode rejected');
915
911
  }
916
912
  }
917
913
  async setAgentModel(agentId, modelId) {
918
914
  const requestId = this.createRequestId();
919
915
  const message = SessionInboundMessageSchema.parse({
920
- type: "set_agent_model_request",
916
+ type: 'set_agent_model_request',
921
917
  agentId,
922
918
  modelId,
923
919
  requestId,
@@ -928,7 +924,7 @@ export class DaemonClient {
928
924
  timeout: 15000,
929
925
  options: { skipQueue: true },
930
926
  select: (msg) => {
931
- if (msg.type !== "set_agent_model_response") {
927
+ if (msg.type !== 'set_agent_model_response') {
932
928
  return null;
933
929
  }
934
930
  if (msg.payload.requestId !== requestId) {
@@ -938,13 +934,13 @@ export class DaemonClient {
938
934
  },
939
935
  });
940
936
  if (!payload.accepted) {
941
- throw new Error(payload.error ?? "setAgentModel rejected");
937
+ throw new Error(payload.error ?? 'setAgentModel rejected');
942
938
  }
943
939
  }
944
940
  async setAgentThinkingOption(agentId, thinkingOptionId) {
945
941
  const requestId = this.createRequestId();
946
942
  const message = SessionInboundMessageSchema.parse({
947
- type: "set_agent_thinking_request",
943
+ type: 'set_agent_thinking_request',
948
944
  agentId,
949
945
  thinkingOptionId,
950
946
  requestId,
@@ -955,7 +951,7 @@ export class DaemonClient {
955
951
  timeout: 15000,
956
952
  options: { skipQueue: true },
957
953
  select: (msg) => {
958
- if (msg.type !== "set_agent_thinking_response") {
954
+ if (msg.type !== 'set_agent_thinking_response') {
959
955
  return null;
960
956
  }
961
957
  if (msg.payload.requestId !== requestId) {
@@ -965,13 +961,13 @@ export class DaemonClient {
965
961
  },
966
962
  });
967
963
  if (!payload.accepted) {
968
- throw new Error(payload.error ?? "setAgentThinkingOption rejected");
964
+ throw new Error(payload.error ?? 'setAgentThinkingOption rejected');
969
965
  }
970
966
  }
971
967
  async restartServer(reason, requestId) {
972
968
  const resolvedRequestId = this.createRequestId(requestId);
973
969
  const message = SessionInboundMessageSchema.parse({
974
- type: "restart_server_request",
970
+ type: 'restart_server_request',
975
971
  ...(reason && reason.trim().length > 0 ? { reason } : {}),
976
972
  requestId: resolvedRequestId,
977
973
  });
@@ -981,7 +977,7 @@ export class DaemonClient {
981
977
  timeout: 10000,
982
978
  options: { skipQueue: true },
983
979
  select: (msg) => {
984
- if (msg.type !== "status") {
980
+ if (msg.type !== 'status') {
985
981
  return null;
986
982
  }
987
983
  const restarted = RestartRequestedStatusPayloadSchema.safeParse(msg.payload);
@@ -1001,7 +997,7 @@ export class DaemonClient {
1001
997
  async setVoiceMode(enabled, agentId) {
1002
998
  const requestId = this.createRequestId();
1003
999
  const message = SessionInboundMessageSchema.parse({
1004
- type: "set_voice_mode",
1000
+ type: 'set_voice_mode',
1005
1001
  enabled,
1006
1002
  ...(agentId ? { agentId } : {}),
1007
1003
  requestId,
@@ -1011,7 +1007,7 @@ export class DaemonClient {
1011
1007
  message,
1012
1008
  timeout: 10000,
1013
1009
  select: (msg) => {
1014
- if (msg.type !== "set_voice_mode_response") {
1010
+ if (msg.type !== 'set_voice_mode_response') {
1015
1011
  return null;
1016
1012
  }
1017
1013
  if (msg.payload.requestId !== requestId) {
@@ -1021,19 +1017,19 @@ export class DaemonClient {
1021
1017
  },
1022
1018
  });
1023
1019
  if (!response.accepted) {
1024
- const codeSuffix = typeof response.reasonCode === "string" && response.reasonCode.trim().length > 0
1020
+ const codeSuffix = typeof response.reasonCode === 'string' && response.reasonCode.trim().length > 0
1025
1021
  ? ` (${response.reasonCode})`
1026
- : "";
1027
- throw new Error((response.error ?? "Failed to set voice mode") + codeSuffix);
1022
+ : '';
1023
+ throw new Error((response.error ?? 'Failed to set voice mode') + codeSuffix);
1028
1024
  }
1029
1025
  return response;
1030
1026
  }
1031
1027
  async sendVoiceAudioChunk(audio, format, isLast) {
1032
- this.sendSessionMessage({ type: "voice_audio_chunk", audio, format, isLast });
1028
+ this.sendSessionMessage({ type: 'voice_audio_chunk', audio, format, isLast });
1033
1029
  }
1034
1030
  async startDictationStream(dictationId, format) {
1035
1031
  const ack = this.waitForWithCancel((msg) => {
1036
- if (msg.type !== "dictation_stream_ack") {
1032
+ if (msg.type !== 'dictation_stream_ack') {
1037
1033
  return null;
1038
1034
  }
1039
1035
  if (msg.payload.dictationId !== dictationId) {
@@ -1046,7 +1042,7 @@ export class DaemonClient {
1046
1042
  }, 30000, { skipQueue: true });
1047
1043
  const ackPromise = ack.promise.then(() => undefined);
1048
1044
  const streamError = this.waitForWithCancel((msg) => {
1049
- if (msg.type !== "dictation_stream_error") {
1045
+ if (msg.type !== 'dictation_stream_error') {
1050
1046
  return null;
1051
1047
  }
1052
1048
  if (msg.payload.dictationId !== dictationId) {
@@ -1057,9 +1053,9 @@ export class DaemonClient {
1057
1053
  const errorPromise = streamError.promise.then((payload) => {
1058
1054
  throw new Error(payload.error);
1059
1055
  });
1060
- const cleanupError = new Error("Cancelled dictation start waiter");
1056
+ const cleanupError = new Error('Cancelled dictation start waiter');
1061
1057
  try {
1062
- this.sendSessionMessageStrict({ type: "dictation_stream_start", dictationId, format });
1058
+ this.sendSessionMessageStrict({ type: 'dictation_stream_start', dictationId, format });
1063
1059
  await Promise.race([ackPromise, errorPromise]);
1064
1060
  }
1065
1061
  finally {
@@ -1070,11 +1066,17 @@ export class DaemonClient {
1070
1066
  }
1071
1067
  }
1072
1068
  sendDictationStreamChunk(dictationId, seq, audio, format) {
1073
- this.sendSessionMessageStrict({ type: "dictation_stream_chunk", dictationId, seq, audio, format });
1069
+ this.sendSessionMessageStrict({
1070
+ type: 'dictation_stream_chunk',
1071
+ dictationId,
1072
+ seq,
1073
+ audio,
1074
+ format,
1075
+ });
1074
1076
  }
1075
1077
  async finishDictationStream(dictationId, finalSeq) {
1076
1078
  const final = this.waitForWithCancel((msg) => {
1077
- if (msg.type !== "dictation_stream_final") {
1079
+ if (msg.type !== 'dictation_stream_final') {
1078
1080
  return null;
1079
1081
  }
1080
1082
  if (msg.payload.dictationId !== dictationId) {
@@ -1083,7 +1085,7 @@ export class DaemonClient {
1083
1085
  return msg.payload;
1084
1086
  }, 0, { skipQueue: true });
1085
1087
  const streamError = this.waitForWithCancel((msg) => {
1086
- if (msg.type !== "dictation_stream_error") {
1088
+ if (msg.type !== 'dictation_stream_error') {
1087
1089
  return null;
1088
1090
  }
1089
1091
  if (msg.payload.dictationId !== dictationId) {
@@ -1092,7 +1094,7 @@ export class DaemonClient {
1092
1094
  return msg.payload;
1093
1095
  }, 0, { skipQueue: true });
1094
1096
  const finishAccepted = this.waitForWithCancel((msg) => {
1095
- if (msg.type !== "dictation_stream_finish_accepted") {
1097
+ if (msg.type !== 'dictation_stream_finish_accepted') {
1096
1098
  return null;
1097
1099
  }
1098
1100
  if (msg.payload.dictationId !== dictationId) {
@@ -1106,68 +1108,64 @@ export class DaemonClient {
1106
1108
  });
1107
1109
  const finishAcceptedPromise = finishAccepted.promise;
1108
1110
  const finalOutcomePromise = finalPromise.then((payload) => ({
1109
- kind: "final",
1111
+ kind: 'final',
1110
1112
  payload,
1111
1113
  }));
1112
1114
  const errorOutcomePromise = errorPromise.then(() => ({
1113
- kind: "error",
1114
- error: new Error("Unexpected dictation stream error state"),
1115
+ kind: 'error',
1116
+ error: new Error('Unexpected dictation stream error state'),
1115
1117
  }), (error) => ({
1116
- kind: "error",
1118
+ kind: 'error',
1117
1119
  error: error instanceof Error ? error : new Error(String(error)),
1118
1120
  }));
1119
- const finishAcceptedOutcomePromise = finishAcceptedPromise.then((payload) => ({ kind: "accepted", payload }), (error) => {
1121
+ const finishAcceptedOutcomePromise = finishAcceptedPromise.then((payload) => ({ kind: 'accepted', payload }), (error) => {
1120
1122
  if (isWaiterTimeoutError(error)) {
1121
- return { kind: "accepted_timeout" };
1123
+ return { kind: 'accepted_timeout' };
1122
1124
  }
1123
1125
  return {
1124
- kind: "accepted_error",
1126
+ kind: 'accepted_error',
1125
1127
  error: error instanceof Error ? error : new Error(String(error)),
1126
1128
  };
1127
1129
  });
1128
1130
  const waitForFinalResult = async (timeoutMs) => {
1129
1131
  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
1130
1132
  const outcome = await Promise.race([finalOutcomePromise, errorOutcomePromise]);
1131
- if (outcome.kind === "error") {
1133
+ if (outcome.kind === 'error') {
1132
1134
  throw outcome.error;
1133
1135
  }
1134
1136
  return outcome.payload;
1135
1137
  }
1136
1138
  let timeoutHandle = null;
1137
1139
  const timeoutPromise = new Promise((resolve) => {
1138
- timeoutHandle = setTimeout(() => resolve({ kind: "timeout" }), timeoutMs);
1140
+ timeoutHandle = setTimeout(() => resolve({ kind: 'timeout' }), timeoutMs);
1139
1141
  });
1140
- const outcome = await Promise.race([
1141
- finalOutcomePromise,
1142
- errorOutcomePromise,
1143
- timeoutPromise,
1144
- ]);
1142
+ const outcome = await Promise.race([finalOutcomePromise, errorOutcomePromise, timeoutPromise]);
1145
1143
  if (timeoutHandle) {
1146
1144
  clearTimeout(timeoutHandle);
1147
1145
  }
1148
- if (outcome.kind === "timeout") {
1146
+ if (outcome.kind === 'timeout') {
1149
1147
  throw new Error(`Timeout waiting for dictation finalization (${timeoutMs}ms)`);
1150
1148
  }
1151
- if (outcome.kind === "error") {
1149
+ if (outcome.kind === 'error') {
1152
1150
  throw outcome.error;
1153
1151
  }
1154
1152
  return outcome.payload;
1155
1153
  };
1156
- const cleanupError = new Error("Cancelled dictation finish waiter");
1154
+ const cleanupError = new Error('Cancelled dictation finish waiter');
1157
1155
  try {
1158
- this.sendSessionMessageStrict({ type: "dictation_stream_finish", dictationId, finalSeq });
1156
+ this.sendSessionMessageStrict({ type: 'dictation_stream_finish', dictationId, finalSeq });
1159
1157
  const firstOutcome = await Promise.race([
1160
1158
  finalOutcomePromise,
1161
1159
  errorOutcomePromise,
1162
1160
  finishAcceptedOutcomePromise,
1163
1161
  ]);
1164
- if (firstOutcome.kind === "final") {
1162
+ if (firstOutcome.kind === 'final') {
1165
1163
  return firstOutcome.payload;
1166
1164
  }
1167
- if (firstOutcome.kind === "error") {
1165
+ if (firstOutcome.kind === 'error') {
1168
1166
  throw firstOutcome.error;
1169
1167
  }
1170
- if (firstOutcome.kind === "accepted") {
1168
+ if (firstOutcome.kind === 'accepted') {
1171
1169
  return await waitForFinalResult(firstOutcome.payload.timeoutMs + DEFAULT_DICTATION_FINISH_TIMEOUT_GRACE_MS);
1172
1170
  }
1173
1171
  return await waitForFinalResult(DEFAULT_DICTATION_FINISH_FALLBACK_TIMEOUT_MS);
@@ -1182,13 +1180,13 @@ export class DaemonClient {
1182
1180
  }
1183
1181
  }
1184
1182
  cancelDictationStream(dictationId) {
1185
- this.sendSessionMessageStrict({ type: "dictation_stream_cancel", dictationId });
1183
+ this.sendSessionMessageStrict({ type: 'dictation_stream_cancel', dictationId });
1186
1184
  }
1187
1185
  async abortRequest() {
1188
- this.sendSessionMessage({ type: "abort_request" });
1186
+ this.sendSessionMessage({ type: 'abort_request' });
1189
1187
  }
1190
1188
  async audioPlayed(id) {
1191
- this.sendSessionMessage({ type: "audio_played", id });
1189
+ this.sendSessionMessage({ type: 'audio_played', id });
1192
1190
  }
1193
1191
  // ============================================================================
1194
1192
  // Git Operations
@@ -1203,7 +1201,7 @@ export class DaemonClient {
1203
1201
  }
1204
1202
  const resolvedRequestId = this.createRequestId(requestId);
1205
1203
  const message = SessionInboundMessageSchema.parse({
1206
- type: "checkout_status_request",
1204
+ type: 'checkout_status_request',
1207
1205
  cwd,
1208
1206
  requestId: resolvedRequestId,
1209
1207
  });
@@ -1213,7 +1211,7 @@ export class DaemonClient {
1213
1211
  timeout: 60000,
1214
1212
  options: { skipQueue: true },
1215
1213
  select: (msg) => {
1216
- if (msg.type !== "checkout_status_response") {
1214
+ if (msg.type !== 'checkout_status_response') {
1217
1215
  return null;
1218
1216
  }
1219
1217
  if (msg.payload.requestId !== resolvedRequestId) {
@@ -1235,14 +1233,14 @@ export class DaemonClient {
1235
1233
  return responsePromise;
1236
1234
  }
1237
1235
  normalizeCheckoutDiffCompare(compare) {
1238
- if (compare.mode === "uncommitted") {
1239
- return { mode: "uncommitted" };
1236
+ if (compare.mode === 'uncommitted') {
1237
+ return { mode: 'uncommitted' };
1240
1238
  }
1241
1239
  const trimmedBaseRef = compare.baseRef?.trim();
1242
1240
  if (!trimmedBaseRef) {
1243
- return { mode: "base" };
1241
+ return { mode: 'base' };
1244
1242
  }
1245
- return { mode: "base", baseRef: trimmedBaseRef };
1243
+ return { mode: 'base', baseRef: trimmedBaseRef };
1246
1244
  }
1247
1245
  async getCheckoutDiff(cwd, compare, requestId) {
1248
1246
  const oneShotSubscriptionId = `oneshot-checkout-diff:${crypto.randomUUID()}`;
@@ -1277,7 +1275,7 @@ export class DaemonClient {
1277
1275
  });
1278
1276
  const resolvedRequestId = this.createRequestId(options?.requestId);
1279
1277
  const message = SessionInboundMessageSchema.parse({
1280
- type: "subscribe_checkout_diff_request",
1278
+ type: 'subscribe_checkout_diff_request',
1281
1279
  subscriptionId,
1282
1280
  cwd,
1283
1281
  compare: normalizedCompare,
@@ -1287,7 +1285,7 @@ export class DaemonClient {
1287
1285
  return await this.sendCorrelatedRequest({
1288
1286
  requestId: resolvedRequestId,
1289
1287
  message,
1290
- responseType: "subscribe_checkout_diff_response",
1288
+ responseType: 'subscribe_checkout_diff_response',
1291
1289
  timeout: 60000,
1292
1290
  options: { skipQueue: true },
1293
1291
  selectPayload: (payload) => {
@@ -1311,7 +1309,7 @@ export class DaemonClient {
1311
1309
  unsubscribeCheckoutDiff(subscriptionId) {
1312
1310
  this.checkoutDiffSubscriptions.delete(subscriptionId);
1313
1311
  this.sendSessionMessage({
1314
- type: "unsubscribe_checkout_diff_request",
1312
+ type: 'unsubscribe_checkout_diff_request',
1315
1313
  subscriptionId,
1316
1314
  });
1317
1315
  }
@@ -1319,12 +1317,12 @@ export class DaemonClient {
1319
1317
  return this.sendCorrelatedSessionRequest({
1320
1318
  requestId,
1321
1319
  message: {
1322
- type: "checkout_commit_request",
1320
+ type: 'checkout_commit_request',
1323
1321
  cwd,
1324
1322
  message: input.message,
1325
1323
  addAll: input.addAll,
1326
1324
  },
1327
- responseType: "checkout_commit_response",
1325
+ responseType: 'checkout_commit_response',
1328
1326
  timeout: 60000,
1329
1327
  });
1330
1328
  }
@@ -1332,13 +1330,13 @@ export class DaemonClient {
1332
1330
  return this.sendCorrelatedSessionRequest({
1333
1331
  requestId,
1334
1332
  message: {
1335
- type: "checkout_merge_request",
1333
+ type: 'checkout_merge_request',
1336
1334
  cwd,
1337
1335
  baseRef: input.baseRef,
1338
1336
  strategy: input.strategy,
1339
1337
  requireCleanTarget: input.requireCleanTarget,
1340
1338
  },
1341
- responseType: "checkout_merge_response",
1339
+ responseType: 'checkout_merge_response',
1342
1340
  timeout: 60000,
1343
1341
  });
1344
1342
  }
@@ -1346,12 +1344,12 @@ export class DaemonClient {
1346
1344
  return this.sendCorrelatedSessionRequest({
1347
1345
  requestId,
1348
1346
  message: {
1349
- type: "checkout_merge_from_base_request",
1347
+ type: 'checkout_merge_from_base_request',
1350
1348
  cwd,
1351
1349
  baseRef: input.baseRef,
1352
1350
  requireCleanTarget: input.requireCleanTarget,
1353
1351
  },
1354
- responseType: "checkout_merge_from_base_response",
1352
+ responseType: 'checkout_merge_from_base_response',
1355
1353
  timeout: 60000,
1356
1354
  });
1357
1355
  }
@@ -1359,10 +1357,10 @@ export class DaemonClient {
1359
1357
  return this.sendCorrelatedSessionRequest({
1360
1358
  requestId,
1361
1359
  message: {
1362
- type: "checkout_push_request",
1360
+ type: 'checkout_push_request',
1363
1361
  cwd,
1364
1362
  },
1365
- responseType: "checkout_push_response",
1363
+ responseType: 'checkout_push_response',
1366
1364
  timeout: 60000,
1367
1365
  });
1368
1366
  }
@@ -1370,13 +1368,13 @@ export class DaemonClient {
1370
1368
  return this.sendCorrelatedSessionRequest({
1371
1369
  requestId,
1372
1370
  message: {
1373
- type: "checkout_pr_create_request",
1371
+ type: 'checkout_pr_create_request',
1374
1372
  cwd,
1375
1373
  title: input.title,
1376
1374
  body: input.body,
1377
1375
  baseRef: input.baseRef,
1378
1376
  },
1379
- responseType: "checkout_pr_create_response",
1377
+ responseType: 'checkout_pr_create_response',
1380
1378
  timeout: 60000,
1381
1379
  });
1382
1380
  }
@@ -1384,10 +1382,10 @@ export class DaemonClient {
1384
1382
  return this.sendCorrelatedSessionRequest({
1385
1383
  requestId,
1386
1384
  message: {
1387
- type: "checkout_pr_status_request",
1385
+ type: 'checkout_pr_status_request',
1388
1386
  cwd,
1389
1387
  },
1390
- responseType: "checkout_pr_status_response",
1388
+ responseType: 'checkout_pr_status_response',
1391
1389
  timeout: 60000,
1392
1390
  });
1393
1391
  }
@@ -1395,11 +1393,11 @@ export class DaemonClient {
1395
1393
  return this.sendCorrelatedSessionRequest({
1396
1394
  requestId,
1397
1395
  message: {
1398
- type: "paseo_worktree_list_request",
1396
+ type: 'paseo_worktree_list_request',
1399
1397
  cwd: input.cwd,
1400
1398
  repoRoot: input.repoRoot,
1401
1399
  },
1402
- responseType: "paseo_worktree_list_response",
1400
+ responseType: 'paseo_worktree_list_response',
1403
1401
  timeout: 60000,
1404
1402
  });
1405
1403
  }
@@ -1407,12 +1405,12 @@ export class DaemonClient {
1407
1405
  return this.sendCorrelatedSessionRequest({
1408
1406
  requestId,
1409
1407
  message: {
1410
- type: "paseo_worktree_archive_request",
1408
+ type: 'paseo_worktree_archive_request',
1411
1409
  worktreePath: input.worktreePath,
1412
1410
  repoRoot: input.repoRoot,
1413
1411
  branchName: input.branchName,
1414
1412
  },
1415
- responseType: "paseo_worktree_archive_response",
1413
+ responseType: 'paseo_worktree_archive_response',
1416
1414
  timeout: 20000,
1417
1415
  });
1418
1416
  }
@@ -1420,11 +1418,11 @@ export class DaemonClient {
1420
1418
  return this.sendCorrelatedSessionRequest({
1421
1419
  requestId,
1422
1420
  message: {
1423
- type: "validate_branch_request",
1421
+ type: 'validate_branch_request',
1424
1422
  cwd: options.cwd,
1425
1423
  branchName: options.branchName,
1426
1424
  },
1427
- responseType: "validate_branch_response",
1425
+ responseType: 'validate_branch_response',
1428
1426
  timeout: 10000,
1429
1427
  });
1430
1428
  }
@@ -1432,12 +1430,12 @@ export class DaemonClient {
1432
1430
  return this.sendCorrelatedSessionRequest({
1433
1431
  requestId,
1434
1432
  message: {
1435
- type: "branch_suggestions_request",
1433
+ type: 'branch_suggestions_request',
1436
1434
  cwd: options.cwd,
1437
1435
  query: options.query,
1438
1436
  limit: options.limit,
1439
1437
  },
1440
- responseType: "branch_suggestions_response",
1438
+ responseType: 'branch_suggestions_response',
1441
1439
  timeout: 10000,
1442
1440
  });
1443
1441
  }
@@ -1445,27 +1443,30 @@ export class DaemonClient {
1445
1443
  return this.sendCorrelatedSessionRequest({
1446
1444
  requestId,
1447
1445
  message: {
1448
- type: "directory_suggestions_request",
1446
+ type: 'directory_suggestions_request',
1449
1447
  query: options.query,
1448
+ cwd: options.cwd,
1449
+ includeFiles: options.includeFiles,
1450
+ includeDirectories: options.includeDirectories,
1450
1451
  limit: options.limit,
1451
1452
  },
1452
- responseType: "directory_suggestions_response",
1453
+ responseType: 'directory_suggestions_response',
1453
1454
  timeout: 10000,
1454
1455
  });
1455
1456
  }
1456
1457
  // ============================================================================
1457
1458
  // File Explorer
1458
1459
  // ============================================================================
1459
- async exploreFileSystem(agentId, path, mode = "list", requestId) {
1460
+ async exploreFileSystem(agentId, path, mode = 'list', requestId) {
1460
1461
  return this.sendCorrelatedSessionRequest({
1461
1462
  requestId,
1462
1463
  message: {
1463
- type: "file_explorer_request",
1464
+ type: 'file_explorer_request',
1464
1465
  agentId,
1465
1466
  path,
1466
1467
  mode,
1467
1468
  },
1468
- responseType: "file_explorer_response",
1469
+ responseType: 'file_explorer_response',
1469
1470
  timeout: 10000,
1470
1471
  });
1471
1472
  }
@@ -1473,11 +1474,11 @@ export class DaemonClient {
1473
1474
  return this.sendCorrelatedSessionRequest({
1474
1475
  requestId,
1475
1476
  message: {
1476
- type: "file_download_token_request",
1477
+ type: 'file_download_token_request',
1477
1478
  agentId,
1478
1479
  path,
1479
1480
  },
1480
- responseType: "file_download_token_response",
1481
+ responseType: 'file_download_token_response',
1481
1482
  timeout: 10000,
1482
1483
  });
1483
1484
  }
@@ -1485,10 +1486,10 @@ export class DaemonClient {
1485
1486
  return this.sendCorrelatedSessionRequest({
1486
1487
  requestId,
1487
1488
  message: {
1488
- type: "project_icon_request",
1489
+ type: 'project_icon_request',
1489
1490
  cwd,
1490
1491
  },
1491
- responseType: "project_icon_response",
1492
+ responseType: 'project_icon_response',
1492
1493
  timeout: 10000,
1493
1494
  });
1494
1495
  }
@@ -1499,11 +1500,11 @@ export class DaemonClient {
1499
1500
  return this.sendCorrelatedSessionRequest({
1500
1501
  requestId: options?.requestId,
1501
1502
  message: {
1502
- type: "list_provider_models_request",
1503
+ type: 'list_provider_models_request',
1503
1504
  provider,
1504
1505
  cwd: options?.cwd,
1505
1506
  },
1506
- responseType: "list_provider_models_response",
1507
+ responseType: 'list_provider_models_response',
1507
1508
  timeout: 30000,
1508
1509
  });
1509
1510
  }
@@ -1511,9 +1512,9 @@ export class DaemonClient {
1511
1512
  return this.sendCorrelatedSessionRequest({
1512
1513
  requestId: options?.requestId,
1513
1514
  message: {
1514
- type: "list_available_providers_request",
1515
+ type: 'list_available_providers_request',
1515
1516
  },
1516
- responseType: "list_available_providers_response",
1517
+ responseType: 'list_available_providers_response',
1517
1518
  timeout: 30000,
1518
1519
  });
1519
1520
  }
@@ -1521,9 +1522,9 @@ export class DaemonClient {
1521
1522
  return this.sendCorrelatedSessionRequest({
1522
1523
  requestId,
1523
1524
  message: {
1524
- type: "speech_models_list_request",
1525
+ type: 'speech_models_list_request',
1525
1526
  },
1526
- responseType: "speech_models_list_response",
1527
+ responseType: 'speech_models_list_response',
1527
1528
  timeout: 30000,
1528
1529
  });
1529
1530
  }
@@ -1531,34 +1532,24 @@ export class DaemonClient {
1531
1532
  return this.sendCorrelatedSessionRequest({
1532
1533
  requestId: options?.requestId,
1533
1534
  message: {
1534
- type: "speech_models_download_request",
1535
+ type: 'speech_models_download_request',
1535
1536
  modelIds: options?.modelIds,
1536
1537
  },
1537
- responseType: "speech_models_download_response",
1538
+ responseType: 'speech_models_download_response',
1538
1539
  timeout: 30 * 60 * 1000,
1539
1540
  });
1540
1541
  }
1541
- async listCommands(agentId, requestId) {
1542
- return this.sendCorrelatedSessionRequest({
1543
- requestId,
1544
- message: {
1545
- type: "list_commands_request",
1546
- agentId,
1547
- },
1548
- responseType: "list_commands_response",
1549
- timeout: 30000,
1550
- });
1551
- }
1552
- async executeCommand(agentId, commandName, args, requestId) {
1542
+ async listCommands(agentId, requestIdOrOptions) {
1543
+ const requestId = typeof requestIdOrOptions === 'string' ? requestIdOrOptions : requestIdOrOptions?.requestId;
1544
+ const draftConfig = typeof requestIdOrOptions === 'string' ? undefined : requestIdOrOptions?.draftConfig;
1553
1545
  return this.sendCorrelatedSessionRequest({
1554
1546
  requestId,
1555
1547
  message: {
1556
- type: "execute_command_request",
1548
+ type: 'list_commands_request',
1557
1549
  agentId,
1558
- commandName,
1559
- args,
1550
+ ...(draftConfig ? { draftConfig } : {}),
1560
1551
  },
1561
- responseType: "execute_command_response",
1552
+ responseType: 'list_commands_response',
1562
1553
  timeout: 30000,
1563
1554
  });
1564
1555
  }
@@ -1567,7 +1558,7 @@ export class DaemonClient {
1567
1558
  // ============================================================================
1568
1559
  async respondToPermission(agentId, requestId, response) {
1569
1560
  this.sendSessionMessage({
1570
- type: "agent_permission_response",
1561
+ type: 'agent_permission_response',
1571
1562
  agentId,
1572
1563
  requestId,
1573
1564
  response,
@@ -1575,7 +1566,7 @@ export class DaemonClient {
1575
1566
  }
1576
1567
  async respondToPermissionAndWait(agentId, requestId, response, timeout = 15000) {
1577
1568
  const message = SessionInboundMessageSchema.parse({
1578
- type: "agent_permission_response",
1569
+ type: 'agent_permission_response',
1579
1570
  agentId,
1580
1571
  requestId,
1581
1572
  response,
@@ -1586,7 +1577,7 @@ export class DaemonClient {
1586
1577
  timeout,
1587
1578
  options: { skipQueue: true },
1588
1579
  select: (msg) => {
1589
- if (msg.type !== "agent_permission_resolved") {
1580
+ if (msg.type !== 'agent_permission_resolved') {
1590
1581
  return null;
1591
1582
  }
1592
1583
  if (msg.payload.requestId !== requestId) {
@@ -1616,7 +1607,7 @@ export class DaemonClient {
1616
1607
  async waitForFinish(agentId, timeout = 60000) {
1617
1608
  const requestId = this.createRequestId();
1618
1609
  const message = SessionInboundMessageSchema.parse({
1619
- type: "wait_for_finish_request",
1610
+ type: 'wait_for_finish_request',
1620
1611
  requestId,
1621
1612
  agentId,
1622
1613
  timeoutMs: timeout,
@@ -1624,7 +1615,7 @@ export class DaemonClient {
1624
1615
  const payload = await this.sendCorrelatedRequest({
1625
1616
  requestId,
1626
1617
  message,
1627
- responseType: "wait_for_finish_response",
1618
+ responseType: 'wait_for_finish_response',
1628
1619
  timeout: timeout + 5000,
1629
1620
  options: { skipQueue: true },
1630
1621
  });
@@ -1640,35 +1631,35 @@ export class DaemonClient {
1640
1631
  // ============================================================================
1641
1632
  subscribeTerminals(input) {
1642
1633
  this.terminalDirectorySubscriptions.add(input.cwd);
1643
- if (!this.transport || this.connectionState.status !== "connected") {
1634
+ if (!this.transport || this.connectionState.status !== 'connected') {
1644
1635
  return;
1645
1636
  }
1646
1637
  this.sendSessionMessage({
1647
- type: "subscribe_terminals_request",
1638
+ type: 'subscribe_terminals_request',
1648
1639
  cwd: input.cwd,
1649
1640
  });
1650
1641
  }
1651
1642
  unsubscribeTerminals(input) {
1652
1643
  this.terminalDirectorySubscriptions.delete(input.cwd);
1653
- if (!this.transport || this.connectionState.status !== "connected") {
1644
+ if (!this.transport || this.connectionState.status !== 'connected') {
1654
1645
  return;
1655
1646
  }
1656
1647
  this.sendSessionMessage({
1657
- type: "unsubscribe_terminals_request",
1648
+ type: 'unsubscribe_terminals_request',
1658
1649
  cwd: input.cwd,
1659
1650
  });
1660
1651
  }
1661
1652
  async listTerminals(cwd, requestId) {
1662
1653
  const resolvedRequestId = this.createRequestId(requestId);
1663
1654
  const message = SessionInboundMessageSchema.parse({
1664
- type: "list_terminals_request",
1655
+ type: 'list_terminals_request',
1665
1656
  cwd,
1666
1657
  requestId: resolvedRequestId,
1667
1658
  });
1668
1659
  return this.sendCorrelatedRequest({
1669
1660
  requestId: resolvedRequestId,
1670
1661
  message,
1671
- responseType: "list_terminals_response",
1662
+ responseType: 'list_terminals_response',
1672
1663
  timeout: 10000,
1673
1664
  options: { skipQueue: true },
1674
1665
  });
@@ -1676,7 +1667,7 @@ export class DaemonClient {
1676
1667
  async createTerminal(cwd, name, requestId) {
1677
1668
  const resolvedRequestId = this.createRequestId(requestId);
1678
1669
  const message = SessionInboundMessageSchema.parse({
1679
- type: "create_terminal_request",
1670
+ type: 'create_terminal_request',
1680
1671
  cwd,
1681
1672
  name,
1682
1673
  requestId: resolvedRequestId,
@@ -1684,7 +1675,7 @@ export class DaemonClient {
1684
1675
  return this.sendCorrelatedRequest({
1685
1676
  requestId: resolvedRequestId,
1686
1677
  message,
1687
- responseType: "create_terminal_response",
1678
+ responseType: 'create_terminal_response',
1688
1679
  timeout: 10000,
1689
1680
  options: { skipQueue: true },
1690
1681
  });
@@ -1692,27 +1683,27 @@ export class DaemonClient {
1692
1683
  async subscribeTerminal(terminalId, requestId) {
1693
1684
  const resolvedRequestId = this.createRequestId(requestId);
1694
1685
  const message = SessionInboundMessageSchema.parse({
1695
- type: "subscribe_terminal_request",
1686
+ type: 'subscribe_terminal_request',
1696
1687
  terminalId,
1697
1688
  requestId: resolvedRequestId,
1698
1689
  });
1699
1690
  return this.sendCorrelatedRequest({
1700
1691
  requestId: resolvedRequestId,
1701
1692
  message,
1702
- responseType: "subscribe_terminal_response",
1693
+ responseType: 'subscribe_terminal_response',
1703
1694
  timeout: 10000,
1704
1695
  options: { skipQueue: true },
1705
1696
  });
1706
1697
  }
1707
1698
  unsubscribeTerminal(terminalId) {
1708
1699
  this.sendSessionMessage({
1709
- type: "unsubscribe_terminal_request",
1700
+ type: 'unsubscribe_terminal_request',
1710
1701
  terminalId,
1711
1702
  });
1712
1703
  }
1713
1704
  sendTerminalInput(terminalId, message) {
1714
1705
  this.sendSessionMessage({
1715
- type: "terminal_input",
1706
+ type: 'terminal_input',
1716
1707
  terminalId,
1717
1708
  message,
1718
1709
  });
@@ -1720,14 +1711,14 @@ export class DaemonClient {
1720
1711
  async killTerminal(terminalId, requestId) {
1721
1712
  const resolvedRequestId = this.createRequestId(requestId);
1722
1713
  const message = SessionInboundMessageSchema.parse({
1723
- type: "kill_terminal_request",
1714
+ type: 'kill_terminal_request',
1724
1715
  terminalId,
1725
1716
  requestId: resolvedRequestId,
1726
1717
  });
1727
1718
  return this.sendCorrelatedRequest({
1728
1719
  requestId: resolvedRequestId,
1729
1720
  message,
1730
- responseType: "kill_terminal_response",
1721
+ responseType: 'kill_terminal_response',
1731
1722
  timeout: 10000,
1732
1723
  options: { skipQueue: true },
1733
1724
  });
@@ -1735,7 +1726,7 @@ export class DaemonClient {
1735
1726
  async attachTerminalStream(terminalId, options, requestId) {
1736
1727
  const resolvedRequestId = this.createRequestId(requestId);
1737
1728
  const message = SessionInboundMessageSchema.parse({
1738
- type: "attach_terminal_stream_request",
1729
+ type: 'attach_terminal_stream_request',
1739
1730
  terminalId,
1740
1731
  requestId: resolvedRequestId,
1741
1732
  ...(options?.resumeOffset !== undefined ? { resumeOffset: options.resumeOffset } : {}),
@@ -1745,7 +1736,7 @@ export class DaemonClient {
1745
1736
  return this.sendCorrelatedRequest({
1746
1737
  requestId: resolvedRequestId,
1747
1738
  message,
1748
- responseType: "attach_terminal_stream_response",
1739
+ responseType: 'attach_terminal_stream_response',
1749
1740
  timeout: 10000,
1750
1741
  options: { skipQueue: true },
1751
1742
  });
@@ -1753,14 +1744,14 @@ export class DaemonClient {
1753
1744
  async detachTerminalStream(streamId, requestId) {
1754
1745
  const resolvedRequestId = this.createRequestId(requestId);
1755
1746
  const message = SessionInboundMessageSchema.parse({
1756
- type: "detach_terminal_stream_request",
1747
+ type: 'detach_terminal_stream_request',
1757
1748
  streamId,
1758
1749
  requestId: resolvedRequestId,
1759
1750
  });
1760
1751
  const payload = await this.sendCorrelatedRequest({
1761
1752
  requestId: resolvedRequestId,
1762
1753
  message,
1763
- responseType: "detach_terminal_stream_response",
1754
+ responseType: 'detach_terminal_stream_response',
1764
1755
  timeout: 10000,
1765
1756
  options: { skipQueue: true },
1766
1757
  });
@@ -1787,7 +1778,7 @@ export class DaemonClient {
1787
1778
  });
1788
1779
  }
1789
1780
  sendTerminalStreamInput(streamId, data) {
1790
- const payload = typeof data === "string" ? encodeUtf8String(data) : data;
1781
+ const payload = typeof data === 'string' ? encodeUtf8String(data) : data;
1791
1782
  this.sendBinaryFrame({
1792
1783
  channel: BinaryMuxChannel.Terminal,
1793
1784
  messageType: TerminalBinaryMessageType.InputUtf8,
@@ -1816,7 +1807,7 @@ export class DaemonClient {
1816
1807
  }
1817
1808
  async waitForTerminalOutput(terminalId, timeout = 5000) {
1818
1809
  return this.waitFor((msg) => {
1819
- if (msg.type !== "terminal_output") {
1810
+ if (msg.type !== 'terminal_output') {
1820
1811
  return null;
1821
1812
  }
1822
1813
  if (msg.payload.terminalId !== terminalId) {
@@ -1831,7 +1822,7 @@ export class DaemonClient {
1831
1822
  createRequestId(requestId) {
1832
1823
  return requestId ?? crypto.randomUUID();
1833
1824
  }
1834
- disposeTransport(code = 1001, reason = "Reconnecting") {
1825
+ disposeTransport(code = 1001, reason = 'Reconnecting') {
1835
1826
  this.cleanupTransport();
1836
1827
  if (this.transport) {
1837
1828
  try {
@@ -1859,9 +1850,7 @@ export class DaemonClient {
1859
1850
  this.transportCleanup = [];
1860
1851
  }
1861
1852
  handleTransportMessage(data) {
1862
- const rawData = data && typeof data === "object" && "data" in data
1863
- ? data.data
1864
- : data;
1853
+ const rawData = data && typeof data === 'object' && 'data' in data ? data.data : data;
1865
1854
  const rawBytes = asUint8Array(rawData);
1866
1855
  if (rawBytes) {
1867
1856
  const frame = decodeBinaryMuxFrame(rawBytes);
@@ -1883,11 +1872,11 @@ export class DaemonClient {
1883
1872
  }
1884
1873
  const parsed = WSOutboundMessageSchema.safeParse(parsedJson);
1885
1874
  if (!parsed.success) {
1886
- const msgType = parsedJson?.message?.type ?? "unknown";
1887
- this.logger.warn({ msgType, error: parsed.error.message }, "Message validation failed");
1875
+ const msgType = parsedJson?.message?.type ?? 'unknown';
1876
+ this.logger.warn({ msgType, error: parsed.error.message }, 'Message validation failed');
1888
1877
  return;
1889
1878
  }
1890
- if (parsed.data.type === "pong") {
1879
+ if (parsed.data.type === 'pong') {
1891
1880
  return;
1892
1881
  }
1893
1882
  this.handleSessionMessage(parsed.data.message);
@@ -1923,7 +1912,7 @@ export class DaemonClient {
1923
1912
  this.reconnectTimeout = null;
1924
1913
  }
1925
1914
  if (!this.shouldReconnect || this.config.reconnect?.enabled === false) {
1926
- this.rejectConnect(new Error(reason ?? "Transport disconnected before connect"));
1915
+ this.rejectConnect(new Error(reason ?? 'Transport disconnected before connect'));
1927
1916
  return;
1928
1917
  }
1929
1918
  const attempt = this.reconnectAttempt;
@@ -1931,16 +1920,16 @@ export class DaemonClient {
1931
1920
  const maxDelay = this.config.reconnect?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;
1932
1921
  const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
1933
1922
  this.reconnectAttempt = attempt + 1;
1934
- if (typeof reason === "string" && reason.trim().length > 0) {
1923
+ if (typeof reason === 'string' && reason.trim().length > 0) {
1935
1924
  this.lastErrorValue = reason.trim();
1936
1925
  }
1937
1926
  // Clear all pending waiters and queued sends since the connection was lost
1938
1927
  // and responses from the previous connection will never arrive.
1939
- this.clearWaiters(new Error(reason ?? "Connection lost"));
1940
- this.rejectPendingSendQueue(new Error(reason ?? "Connection lost"));
1928
+ this.clearWaiters(new Error(reason ?? 'Connection lost'));
1929
+ this.rejectPendingSendQueue(new Error(reason ?? 'Connection lost'));
1941
1930
  this.terminalStreams.clearAll();
1942
1931
  this.updateConnectionState({
1943
- status: "disconnected",
1932
+ status: 'disconnected',
1944
1933
  ...(reason ? { reason } : {}),
1945
1934
  });
1946
1935
  this.reconnectTimeout = setTimeout(() => {
@@ -1952,7 +1941,7 @@ export class DaemonClient {
1952
1941
  }, delay);
1953
1942
  }
1954
1943
  handleSessionMessage(msg) {
1955
- if (msg.type === "terminal_stream_exit") {
1944
+ if (msg.type === 'terminal_stream_exit') {
1956
1945
  this.terminalStreams.clearStream({ streamId: msg.payload.streamId });
1957
1946
  }
1958
1947
  if (this.rawMessageListeners.size > 0) {
@@ -2007,36 +1996,34 @@ export class DaemonClient {
2007
1996
  }
2008
1997
  toEvent(msg) {
2009
1998
  switch (msg.type) {
2010
- case "agent_update":
1999
+ case 'agent_update':
2011
2000
  return {
2012
- type: "agent_update",
2013
- agentId: msg.payload.kind === "upsert"
2014
- ? msg.payload.agent.id
2015
- : msg.payload.agentId,
2001
+ type: 'agent_update',
2002
+ agentId: msg.payload.kind === 'upsert' ? msg.payload.agent.id : msg.payload.agentId,
2016
2003
  payload: msg.payload,
2017
2004
  };
2018
- case "agent_stream":
2005
+ case 'agent_stream':
2019
2006
  return {
2020
- type: "agent_stream",
2007
+ type: 'agent_stream',
2021
2008
  agentId: msg.payload.agentId,
2022
2009
  event: msg.payload.event,
2023
2010
  timestamp: msg.payload.timestamp,
2024
- ...(typeof msg.payload.seq === "number" ? { seq: msg.payload.seq } : {}),
2025
- ...(typeof msg.payload.epoch === "string" ? { epoch: msg.payload.epoch } : {}),
2011
+ ...(typeof msg.payload.seq === 'number' ? { seq: msg.payload.seq } : {}),
2012
+ ...(typeof msg.payload.epoch === 'string' ? { epoch: msg.payload.epoch } : {}),
2026
2013
  };
2027
- case "status":
2028
- return { type: "status", payload: msg.payload };
2029
- case "agent_deleted":
2030
- return { type: "agent_deleted", agentId: msg.payload.agentId };
2031
- case "agent_permission_request":
2014
+ case 'status':
2015
+ return { type: 'status', payload: msg.payload };
2016
+ case 'agent_deleted':
2017
+ return { type: 'agent_deleted', agentId: msg.payload.agentId };
2018
+ case 'agent_permission_request':
2032
2019
  return {
2033
- type: "agent_permission_request",
2020
+ type: 'agent_permission_request',
2034
2021
  agentId: msg.payload.agentId,
2035
2022
  request: msg.payload.request,
2036
2023
  };
2037
- case "agent_permission_resolved":
2024
+ case 'agent_permission_resolved':
2038
2025
  return {
2039
- type: "agent_permission_resolved",
2026
+ type: 'agent_permission_resolved',
2040
2027
  agentId: msg.payload.agentId,
2041
2028
  requestId: msg.payload.requestId,
2042
2029
  resolution: msg.payload.resolution,
@@ -2117,7 +2104,7 @@ function resolveAgentConfig(options) {
2117
2104
  };
2118
2105
  const merged = config ? { ...baseConfig, ...config } : baseConfig;
2119
2106
  if (!merged.provider || !merged.cwd) {
2120
- throw new Error("createAgent requires provider and cwd");
2107
+ throw new Error('createAgent requires provider and cwd');
2121
2108
  }
2122
2109
  if (!merged.modeId) {
2123
2110
  merged.modeId = getAgentProviderDefinition(merged.provider).defaultModeId ?? undefined;