@parall/daemon 1.28.1 → 1.29.1

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.
@@ -112,6 +112,9 @@ function buildEventBody(event) {
112
112
  }
113
113
  return lines.join("\n") + buildSendMessageHint(event);
114
114
  }
115
+ function buildEventBodyForForkResult(event) {
116
+ return buildEventBody(event).replace(/\n<system-reminder>[\s\S]*<\/system-reminder>$/, "");
117
+ }
115
118
  function buildSendMessageHint(event) {
116
119
  if (event.noReply)
117
120
  return "";
@@ -143,14 +146,16 @@ function buildForkResultPrefix(results) {
143
146
  if (!results.length)
144
147
  return "";
145
148
  const blocks = results.map((result) => {
146
- const lines = [`[Fork result]`];
147
- lines.push(`[Handled: ${result.sourceEvent.type} \u2014 ${result.sourceEvent.summary}]`);
149
+ const lines = [];
150
+ for (const body of result.eventBodies) {
151
+ lines.push(body);
152
+ }
153
+ lines.push(`[This event was handled by a parallel fork session. Do NOT re-handle, re-reply, or duplicate work for it.]`);
154
+ lines.push(`[Fork summary: ${result.agentSummary ? sanitizeMeta(result.agentSummary) : "No fork summary available \u2014 the fork completed without producing a text summary. Check the target chat/task for any actions the fork already took before acting."}]`);
148
155
  if (result.actions.length)
149
- lines.push(`[Actions: ${result.actions.join("; ")}]`);
150
- if (result.agentSummary)
151
- lines.push(`[Summary: ${sanitizeMeta(result.agentSummary)}]`);
156
+ lines.push(`[Fork actions: ${result.actions.join("; ")}]`);
152
157
  if (result.historyPath)
153
- lines.push(`[History: ${result.historyPath}]`);
158
+ lines.push(`[Fork history: ${result.historyPath}]`);
154
159
  return lines.join("\n");
155
160
  });
156
161
  return blocks.join("\n\n") + "\n\n---\n\n";
@@ -418,11 +423,19 @@ Messages may arrive with a \`[Thread: prll://msg_xxx]\` line in the event block,
418
423
  - Keep thread replies focused on the original topic
419
424
  `;
420
425
 
426
+ // ts/agent-core/dist/logger.js
427
+ function createLogger(prefix) {
428
+ return {
429
+ info: (msg) => console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
430
+ warn: (msg) => console.warn(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
431
+ error: (msg) => console.error(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`)
432
+ };
433
+ }
434
+
421
435
  // ts/agent-core/dist/gateway-base.js
422
436
  import * as os from "node:os";
423
437
  import * as fs from "node:fs";
424
438
  import * as path from "node:path";
425
- import { randomUUID } from "node:crypto";
426
439
 
427
440
  // ts/sdk/dist/types.js
428
441
  var MENTION_ALL_USER_ID = "all";
@@ -440,6 +453,8 @@ var ENDPOINTS = {
440
453
  AUTH_CHECK_EMAIL: `${API_BASE}/auth/check-email`,
441
454
  AUTH_VERIFY_EMAIL: `${API_BASE}/auth/verify-email`,
442
455
  AUTH_RESEND_CODE: `${API_BASE}/auth/resend-code`,
456
+ AUTH_FORGOT_PASSWORD: `${API_BASE}/auth/forgot-password`,
457
+ AUTH_RESET_PASSWORD: `${API_BASE}/auth/reset-password`,
443
458
  // Users
444
459
  USERS_ME: `${API_BASE}/users/me`,
445
460
  USER_AVATAR: `${API_BASE}/users/me/avatar`,
@@ -473,8 +488,10 @@ var ENDPOINTS = {
473
488
  CHAT_MESSAGES: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/messages`,
474
489
  // Messages (global, by message ID)
475
490
  MESSAGE: (id) => `${API_BASE}/messages/${id}`,
476
- MESSAGE_PATCHES: (id) => `${API_BASE}/messages/${id}/patches`,
477
491
  MESSAGE_REPLIES: (id) => `${API_BASE}/messages/${id}/replies`,
492
+ MESSAGE_WATCH: (id) => `${API_BASE}/messages/${id}/watch`,
493
+ MESSAGE_WATCHERS: (id) => `${API_BASE}/messages/${id}/watchers`,
494
+ MESSAGE_WATCHING: (id) => `${API_BASE}/messages/${id}/watching`,
478
495
  // Upload (org-scoped)
479
496
  UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
480
497
  UPLOAD_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/upload/complete`,
@@ -500,6 +517,7 @@ var ENDPOINTS = {
500
517
  AGENT_SESSION: (orgId, agentId, sessionId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}`,
501
518
  AGENT_SESSION_STEPS: (orgId, agentId, sessionId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps`,
502
519
  AGENT_SESSION_STEP: (orgId, agentId, sessionId, stepId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps/${stepId}`,
520
+ AGENT_STEP_BY_ID: (orgId, stepId) => `${API_BASE}/orgs/${orgId}/agent-steps/${stepId}`,
503
521
  AGENT_TASKS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/tasks`,
504
522
  AGENT_RUNTIME_AUTH: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/runtime-auth`,
505
523
  AGENT_RUNTIME_AUTH_SESSIONS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/runtime-auth-sessions`,
@@ -524,9 +542,15 @@ var ENDPOINTS = {
524
542
  // Attach/Detach bind an agent to/from a daemon Machine.
525
543
  MACHINE_ATTACH_AGENT: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
526
544
  MACHINE_DETACH_AGENT: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
545
+ MACHINE_WORKSPACE_STATES: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/workspace-states`,
546
+ MACHINE_AGENT_DAEMON_CONFIG: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/daemon-config`,
547
+ MACHINE_AGENT_WORKSPACE_SETUP: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
548
+ MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
527
549
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
528
550
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
529
551
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
552
+ MACHINE_RUNTIME_AUTH_SESSIONS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions`,
553
+ MACHINE_RUNTIME_AUTH_SESSION_COMPLETE: (orgId, machineId, sessionId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions/${sessionId}/complete`,
530
554
  // Machine self-control-plane (mck_-scoped). The bearer token implicitly
531
555
  // identifies the Machine, so there is no `:mid` URL parameter — these are
532
556
  // "self" routes called by the daemon for its own host.
@@ -534,6 +558,7 @@ var ENDPOINTS = {
534
558
  MACHINES_ME_AGENTS: `${API_BASE}/machines/me/agents`,
535
559
  MACHINES_ME_HEALTH: `${API_BASE}/machines/me/health`,
536
560
  MACHINES_ME_AGENT_LAUNCH_CREDENTIAL: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/launch-credential`,
561
+ MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
537
562
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
538
563
  // Tasks (org-scoped)
539
564
  TASKS: (orgId) => `${API_BASE}/orgs/${orgId}/tasks`,
@@ -713,7 +738,8 @@ var WS_EVENTS = {
713
738
  MACHINE_HELLO: "machine.hello",
714
739
  MACHINE_AGENT_ATTACHED: "machine.agent.attached",
715
740
  MACHINE_AGENT_DETACHED: "machine.agent.detached",
716
- MACHINE_STOP: "machine.stop"
741
+ MACHINE_STOP: "machine.stop",
742
+ MACHINE_WORKSPACE_SETUP_REQUESTED: "machine.workspace.setup.requested"
717
743
  };
718
744
 
719
745
  // ts/sdk/dist/client.js
@@ -733,7 +759,9 @@ var ParallClient = class _ParallClient {
733
759
  "/auth/logout",
734
760
  "/auth/verify-email",
735
761
  "/auth/resend-code",
736
- "/auth/check-email"
762
+ "/auth/check-email",
763
+ "/auth/forgot-password",
764
+ "/auth/reset-password"
737
765
  ]);
738
766
  /** Proactive refresh when token expires within this window (seconds). */
739
767
  static REFRESH_THRESHOLD_S = 5 * 60;
@@ -971,6 +999,12 @@ var ParallClient = class _ParallClient {
971
999
  async resendCode(email) {
972
1000
  return this.request("POST", ENDPOINTS.AUTH_RESEND_CODE, { email });
973
1001
  }
1002
+ async forgotPassword(email) {
1003
+ return this.request("POST", ENDPOINTS.AUTH_FORGOT_PASSWORD, { email });
1004
+ }
1005
+ async resetPassword(token, newPassword) {
1006
+ return this.request("POST", ENDPOINTS.AUTH_RESET_PASSWORD, { token, new_password: newPassword });
1007
+ }
974
1008
  // ---- WebSocket ----
975
1009
  async getWsTicket() {
976
1010
  return this.request("POST", ENDPOINTS.WS_TICKET);
@@ -1167,9 +1201,6 @@ var ParallClient = class _ParallClient {
1167
1201
  async deleteMessage(id) {
1168
1202
  return this.request("DELETE", ENDPOINTS.MESSAGE(id));
1169
1203
  }
1170
- async patchMessage(id, req) {
1171
- return this.request("POST", ENDPOINTS.MESSAGE_PATCHES(id), req);
1172
- }
1173
1204
  async getMessageReplies(id, params) {
1174
1205
  return this.request("GET", ENDPOINTS.MESSAGE_REPLIES(id), void 0, params);
1175
1206
  }
@@ -1180,8 +1211,8 @@ var ParallClient = class _ParallClient {
1180
1211
  async completeUpload(orgId, attachmentId) {
1181
1212
  return this.request("POST", ENDPOINTS.UPLOAD_COMPLETE(orgId), { attachment_id: attachmentId });
1182
1213
  }
1183
- async getFileUrl(id) {
1184
- return this.request("GET", ENDPOINTS.FILE(id));
1214
+ async getFileUrl(id, opts) {
1215
+ return this.request("GET", ENDPOINTS.FILE(id), void 0, opts?.download ? { download: true } : void 0);
1185
1216
  }
1186
1217
  // ---- Approvals ----
1187
1218
  async getApproval(id) {
@@ -1262,8 +1293,7 @@ var ParallClient = class _ParallClient {
1262
1293
  * @param params.status - Comma-separated status filter (e.g., `'open'`).
1263
1294
  */
1264
1295
  async getAgentSessions(orgId, agentId, params) {
1265
- const res = await this.request("GET", ENDPOINTS.AGENT_SESSIONS(orgId, agentId), void 0, params);
1266
- return res.data;
1296
+ return this.request("GET", ENDPOINTS.AGENT_SESSIONS(orgId, agentId), void 0, params);
1267
1297
  }
1268
1298
  async getAgentSession(orgId, agentId, sessionId) {
1269
1299
  return this.request("GET", ENDPOINTS.AGENT_SESSION(orgId, agentId, sessionId));
@@ -1275,12 +1305,14 @@ var ParallClient = class _ParallClient {
1275
1305
  return this.request("POST", ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), req);
1276
1306
  }
1277
1307
  async getAgentSessionSteps(orgId, agentId, sessionId, params) {
1278
- const res = await this.request("GET", ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), void 0, params);
1279
- return res.data;
1308
+ return this.request("GET", ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), void 0, params);
1280
1309
  }
1281
1310
  async getAgentSessionStep(orgId, agentId, sessionId, stepId) {
1282
1311
  return this.request("GET", ENDPOINTS.AGENT_SESSION_STEP(orgId, agentId, sessionId, stepId));
1283
1312
  }
1313
+ async getAgentStepById(orgId, stepId) {
1314
+ return this.request("GET", ENDPOINTS.AGENT_STEP_BY_ID(orgId, stepId));
1315
+ }
1284
1316
  // ---- Agent runtime auth (hosted Claude OAuth) ----
1285
1317
  async getAgentRuntimeAuth(orgId, agentId) {
1286
1318
  return this.request("GET", ENDPOINTS.AGENT_RUNTIME_AUTH(orgId, agentId));
@@ -1377,10 +1409,32 @@ var ParallClient = class _ParallClient {
1377
1409
  async detachAgent(orgId, machineId, agentId) {
1378
1410
  return this.request("DELETE", ENDPOINTS.MACHINE_DETACH_AGENT(orgId, machineId, agentId));
1379
1411
  }
1412
+ async listAgentWorkspaceStates(orgId, machineId) {
1413
+ const res = await this.request("GET", ENDPOINTS.MACHINE_WORKSPACE_STATES(orgId, machineId));
1414
+ return res.data;
1415
+ }
1416
+ async patchAgentDaemonConfig(orgId, machineId, agentId, daemonConfig) {
1417
+ return this.request("PATCH", ENDPOINTS.MACHINE_AGENT_DAEMON_CONFIG(orgId, machineId, agentId), { daemon_config: daemonConfig });
1418
+ }
1419
+ async retryAgentWorkspaceSetup(orgId, machineId, agentId) {
1420
+ return this.request("POST", ENDPOINTS.MACHINE_AGENT_WORKSPACE_SETUP(orgId, machineId, agentId));
1421
+ }
1422
+ async patchMachineLLMSource(orgId, machineId, llmSource) {
1423
+ return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource });
1424
+ }
1380
1425
  /** Get machine-level runtime auth state. */
1381
1426
  async getMachineRuntimeAuth(orgId, machineId) {
1382
1427
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1383
1428
  }
1429
+ async startMachineRuntimeAuthSession(orgId, machineId, req = {}) {
1430
+ return this.request("POST", ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSIONS(orgId, machineId), req);
1431
+ }
1432
+ async completeMachineRuntimeAuthSession(orgId, machineId, sessionId, req) {
1433
+ return this.request("POST", ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSION_COMPLETE(orgId, machineId, sessionId), req);
1434
+ }
1435
+ async disconnectMachineRuntimeAuth(orgId, machineId) {
1436
+ return this.request("DELETE", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1437
+ }
1384
1438
  // ---- Machine self-control-plane (mck_-scoped) ----
1385
1439
  //
1386
1440
  // The four methods below are intended to be called from a daemon-mode
@@ -1410,6 +1464,12 @@ var ParallClient = class _ParallClient {
1410
1464
  async postMachineHeartbeat() {
1411
1465
  return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH);
1412
1466
  }
1467
+ async reportAgentWorkspaceState(agentId, state) {
1468
+ const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
1469
+ if (res?.status === "ignored_stale") {
1470
+ throw new ApiError(409, "Workspace state report ignored as stale", "STALE_WORKSPACE_STATE");
1471
+ }
1472
+ }
1413
1473
  /**
1414
1474
  * `POST /machines/me/agents/{agentId}/launch-credential` — mint a
1415
1475
  * short-lived `agk_*` for one of this Machine's attached agents. The
@@ -1559,6 +1619,20 @@ var ParallClient = class _ParallClient {
1559
1619
  const res = await this.request("GET", ENDPOINTS.TASK_WATCHERS(orgId, taskId));
1560
1620
  return res.data;
1561
1621
  }
1622
+ async watchThread(threadRootId) {
1623
+ return this.request("POST", ENDPOINTS.MESSAGE_WATCH(threadRootId));
1624
+ }
1625
+ async unwatchThread(threadRootId) {
1626
+ return this.request("DELETE", ENDPOINTS.MESSAGE_WATCH(threadRootId));
1627
+ }
1628
+ async getThreadWatchers(threadRootId) {
1629
+ const res = await this.request("GET", ENDPOINTS.MESSAGE_WATCHERS(threadRootId));
1630
+ return res.data;
1631
+ }
1632
+ async isWatchingThread(threadRootId) {
1633
+ const res = await this.request("GET", ENDPOINTS.MESSAGE_WATCHING(threadRootId));
1634
+ return res.watching;
1635
+ }
1562
1636
  async getSubtasks(orgId, taskId) {
1563
1637
  const res = await this.request("GET", ENDPOINTS.TASK_SUBTASKS(orgId, taskId));
1564
1638
  return res.data;
@@ -1855,14 +1929,28 @@ var ParallClient = class _ParallClient {
1855
1929
  params.set("machine_id", opts.machine_id);
1856
1930
  if (opts?.unresolved_machine)
1857
1931
  params.set("unresolved_machine", "true");
1932
+ if (opts?.from)
1933
+ params.set("from", opts.from);
1934
+ if (opts?.to)
1935
+ params.set("to", opts.to);
1858
1936
  const qs = params.toString();
1859
1937
  return this.request("GET", `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}${qs ? `?${qs}` : ""}`);
1860
1938
  }
1861
- async listBillingTransactionAgentGroups(orgId) {
1862
- return this.request("GET", `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?group_by=agent`);
1863
- }
1864
- async listBillingTransactionMachineGroups(orgId) {
1865
- return this.request("GET", `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?group_by=machine`);
1939
+ async listBillingTransactionAgentGroups(orgId, opts) {
1940
+ const params = new URLSearchParams({ group_by: "agent" });
1941
+ if (opts?.from)
1942
+ params.set("from", opts.from);
1943
+ if (opts?.to)
1944
+ params.set("to", opts.to);
1945
+ return this.request("GET", `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?${params}`);
1946
+ }
1947
+ async listBillingTransactionMachineGroups(orgId, opts) {
1948
+ const params = new URLSearchParams({ group_by: "machine" });
1949
+ if (opts?.from)
1950
+ params.set("from", opts.from);
1951
+ if (opts?.to)
1952
+ params.set("to", opts.to);
1953
+ return this.request("GET", `${ENDPOINTS.BILLING_TRANSACTIONS(orgId)}?${params}`);
1866
1954
  }
1867
1955
  async createCheckout(orgId, req) {
1868
1956
  return this.request("POST", ENDPOINTS.BILLING_CHECKOUT(orgId), req);
@@ -1913,6 +2001,12 @@ var ApiError = class extends Error {
1913
2001
  };
1914
2002
 
1915
2003
  // ts/sdk/dist/ws.js
2004
+ function isRetryableNetworkError(err) {
2005
+ return err instanceof Error && err.name === "ApiError" && "status" in err && err.status === 0;
2006
+ }
2007
+ function isBrowserRuntime() {
2008
+ return typeof window !== "undefined";
2009
+ }
1916
2010
  var ParallWs = class {
1917
2011
  ws = null;
1918
2012
  options;
@@ -1948,7 +2042,11 @@ var ParallWs = class {
1948
2042
  try {
1949
2043
  ticket = await this.options.getTicket();
1950
2044
  } catch (err) {
1951
- console.error("Failed to get WS ticket:", err);
2045
+ if (isBrowserRuntime() && isRetryableNetworkError(err)) {
2046
+ console.warn("Failed to get WS ticket:", err);
2047
+ } else {
2048
+ console.error("Failed to get WS ticket:", err);
2049
+ }
1952
2050
  if (this.options.reconnect) {
1953
2051
  this.scheduleReconnect();
1954
2052
  } else {
@@ -2277,6 +2375,7 @@ var ParallAgentGateway = class {
2277
2375
  opts;
2278
2376
  chatInfoMap = /* @__PURE__ */ new Map();
2279
2377
  activeDispatches = /* @__PURE__ */ new Map();
2378
+ injectedTypingCounts = /* @__PURE__ */ new Map();
2280
2379
  dispatchedTasks = /* @__PURE__ */ new Set();
2281
2380
  dispatchedMessages = /* @__PURE__ */ new Set();
2282
2381
  forkStates = /* @__PURE__ */ new Map();
@@ -2312,9 +2411,9 @@ var ParallAgentGateway = class {
2312
2411
  this.SHUTDOWN_DEADLINE_MS = opts.shutdownDeadlineMs ?? 6e4;
2313
2412
  }
2314
2413
  async run(abortSignal) {
2315
- const { ws, log } = this.opts;
2414
+ const { ws, log: log2 } = this.opts;
2316
2415
  ws.onStateChange((state) => {
2317
- log?.info(`parall[${this.opts.accountId}]: connection state \u2192 ${state}`);
2416
+ log2?.info(`parall[${this.opts.accountId}]: connection state \u2192 ${state}`);
2318
2417
  });
2319
2418
  ws.on("hello", async (data) => {
2320
2419
  await this.handleHello(data);
@@ -2471,6 +2570,34 @@ var ParallAgentGateway = class {
2471
2570
  if (this.opts.ws.state === "connected")
2472
2571
  this.opts.ws.sendTyping(chatId, "stop");
2473
2572
  }
2573
+ shouldShowTyping(event) {
2574
+ return event.type === "message" && event.targetId.startsWith("cht_") && !event.noReply;
2575
+ }
2576
+ startInjectedTyping(event) {
2577
+ if (!this.shouldShowTyping(event))
2578
+ return;
2579
+ this.startTyping(event.targetId);
2580
+ this.injectedTypingCounts.set(event.targetId, (this.injectedTypingCounts.get(event.targetId) ?? 0) + 1);
2581
+ }
2582
+ takeInjectedTypingCount(chatId) {
2583
+ const count = this.injectedTypingCounts.get(chatId) ?? 0;
2584
+ this.injectedTypingCounts.delete(chatId);
2585
+ return count;
2586
+ }
2587
+ async runDispatchWithTyping(event, sessionKey, bodyForAgent, earlierEvents = [], captureText, opts = {}) {
2588
+ const showTyping = !opts.suppressStart && (this.shouldShowTyping(event) || earlierEvents.some((e) => this.shouldShowTyping(e)));
2589
+ if (showTyping)
2590
+ this.startTyping(event.targetId);
2591
+ try {
2592
+ return await this.runDispatch(event, sessionKey, bodyForAgent, earlierEvents, captureText);
2593
+ } finally {
2594
+ if (showTyping)
2595
+ this.stopTyping(event.targetId);
2596
+ for (let i = 0; i < (opts.injectedTypingCount ?? 0); i++) {
2597
+ this.stopTyping(event.targetId);
2598
+ }
2599
+ }
2600
+ }
2474
2601
  buildDispatchContext(event, sessionKey) {
2475
2602
  const binding = this.sessionBindings.get(sessionKey);
2476
2603
  return {
@@ -2503,7 +2630,8 @@ var ParallAgentGateway = class {
2503
2630
  trigger_ref: event.type === "task" ? { task_id: event.targetId } : event.type === "task_comment" ? { comment_id: event.messageId, task_id: event.targetId } : event.type === "schedule" ? { schedule_id: event.targetId, run_id: event.messageId } : event.type === "approval" ? { approval_id: event.messageId } : { message_id: event.messageId },
2504
2631
  sender_id: event.senderId,
2505
2632
  sender_name: event.senderName,
2506
- summary: event.body.substring(0, 200)
2633
+ summary: event.body.substring(0, 200),
2634
+ ...event.sentAt ? { sent_at: event.sentAt } : {}
2507
2635
  }
2508
2636
  });
2509
2637
  } catch (err) {
@@ -2727,7 +2855,8 @@ var ParallAgentGateway = class {
2727
2855
  continue;
2728
2856
  }
2729
2857
  if (!binding) {
2730
- throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session`);
2858
+ const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
2859
+ throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
2731
2860
  }
2732
2861
  if (!triggerMessageSet) {
2733
2862
  triggerMessageSet = true;
@@ -2801,7 +2930,7 @@ var ParallAgentGateway = class {
2801
2930
  const earlier = events.slice(0, -1);
2802
2931
  try {
2803
2932
  const batchText = [];
2804
- const dispatched = await this.runDispatch(last, fork.fork.sessionKey, buildForkScopePrefix(last) + buildEventBody(last), earlier, batchText);
2933
+ const dispatched = await this.runDispatchWithTyping(last, fork.fork.sessionKey, buildForkScopePrefix(last) + buildEventBody(last), earlier, batchText);
2805
2934
  if (!dispatched) {
2806
2935
  for (const item of items) {
2807
2936
  item.resolve(false);
@@ -2842,6 +2971,7 @@ var ParallAgentGateway = class {
2842
2971
  targetId: fork.targetId,
2843
2972
  summary: fork.processedEvents.length === 1 ? `${first.type} from ${first.senderName} in ${first.targetName ?? fork.targetId}` : `${fork.processedEvents.length} events in ${first.targetName ?? fork.targetId}`
2844
2973
  },
2974
+ eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
2845
2975
  actions: [],
2846
2976
  agentSummary,
2847
2977
  historyPath
@@ -2881,32 +3011,11 @@ var ParallAgentGateway = class {
2881
3011
  return;
2882
3012
  this.draining = true;
2883
3013
  try {
2884
- while (this.dispatchState.mainBuffer.length > 0 || this.dispatchState.pendingForkResults.length > 0) {
3014
+ while (this.dispatchState.mainBuffer.length > 0) {
2885
3015
  if (this.shuttingDown) {
2886
3016
  this.opts.log?.info(`parall[${this.opts.accountId}]: drainMainBuffer halted (shutting down) \u2014 ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`);
2887
3017
  break;
2888
3018
  }
2889
- if (this.dispatchState.mainBuffer.length === 0 && this.dispatchState.pendingForkResults.length > 0) {
2890
- const pending = this.dispatchState.pendingForkResults.splice(0);
2891
- const forkPrefix2 = buildForkResultPrefix(pending);
2892
- const syntheticEvent = {
2893
- type: "message",
2894
- targetId: "_orchestrator",
2895
- targetType: "system",
2896
- senderId: "system",
2897
- senderName: "system",
2898
- messageId: `synthetic-${this.opts.accountId}-${randomUUID()}`,
2899
- body: "[Orchestrator: fork session(s) completed \u2014 review results above]"
2900
- };
2901
- this.dispatchState.mainCurrentTargetId = void 0;
2902
- this.dispatchState.mainPreDispatchBranchPoint = this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
2903
- const dispatched2 = await this.runDispatch(syntheticEvent, this.opts.runtimeKey, forkPrefix2 + buildEventBody(syntheticEvent));
2904
- if (!dispatched2) {
2905
- this.dispatchState.pendingForkResults.unshift(...pending);
2906
- break;
2907
- }
2908
- continue;
2909
- }
2910
3019
  const targetId = this.dispatchState.mainBuffer[0].targetId;
2911
3020
  const events = [];
2912
3021
  while (this.dispatchState.mainBuffer[0]?.targetId === targetId) {
@@ -2914,12 +3023,13 @@ var ParallAgentGateway = class {
2914
3023
  }
2915
3024
  const event = events[events.length - 1];
2916
3025
  const earlier = events.slice(0, -1);
2917
- const skipForkSplice = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
2918
- const pendingFork = skipForkSplice ? [] : this.dispatchState.pendingForkResults.splice(0);
3026
+ const hasPendingInjections = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
3027
+ const injectedTypingCount = hasPendingInjections ? this.takeInjectedTypingCount(event.targetId) : 0;
3028
+ const pendingFork = hasPendingInjections ? [] : this.dispatchState.pendingForkResults.splice(0);
2919
3029
  const forkPrefix = buildForkResultPrefix(pendingFork);
2920
3030
  this.dispatchState.mainCurrentTargetId = event.targetId;
2921
3031
  this.dispatchState.mainPreDispatchBranchPoint = this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
2922
- const dispatched = await this.runDispatch(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event), earlier);
3032
+ const dispatched = await this.runDispatchWithTyping(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event), earlier, void 0, { suppressStart: injectedTypingCount > 0, injectedTypingCount });
2923
3033
  if (!dispatched) {
2924
3034
  this.dispatchState.mainBuffer.unshift(...events);
2925
3035
  this.dispatchState.pendingForkResults.unshift(...pendingFork);
@@ -2953,7 +3063,7 @@ var ParallAgentGateway = class {
2953
3063
  this.dispatchState.mainPreDispatchBranchPoint = this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
2954
3064
  let dispatched = false;
2955
3065
  try {
2956
- dispatched = await this.runDispatch(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event));
3066
+ dispatched = await this.runDispatchWithTyping(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event));
2957
3067
  if (!dispatched) {
2958
3068
  this.dispatchState.pendingForkResults.unshift(...pendingFork);
2959
3069
  }
@@ -2966,10 +3076,15 @@ var ParallAgentGateway = class {
2966
3076
  if (this.shuttingDown) {
2967
3077
  return false;
2968
3078
  }
2969
- if (this.dispatchState.mainCurrentTargetId === event.targetId && this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
2970
- this.opts.log?.info(`parall[${this.opts.accountId}]: steer injected to stdin for ${event.messageId} (will drain for bookkeeping)`);
2971
- }
2972
3079
  this.dispatchState.mainBuffer.push(event);
3080
+ if (this.dispatchState.mainCurrentTargetId === event.targetId && await this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
3081
+ this.startInjectedTyping(event);
3082
+ this.opts.log?.info(`parall[${this.opts.accountId}]: steer injected for ${event.messageId} (will drain for bookkeeping)`);
3083
+ }
3084
+ if (!this.dispatchState.mainDispatching && !this.draining && this.dispatchState.mainBuffer.length > 0) {
3085
+ this.dispatchState.mainDispatching = true;
3086
+ void this.drainMainBuffer();
3087
+ }
2973
3088
  return false;
2974
3089
  }
2975
3090
  case "buffer-fork": {
@@ -3071,6 +3186,7 @@ var ParallAgentGateway = class {
3071
3186
  threadRootId: message.thread_root_id ?? void 0,
3072
3187
  noReply: message.hints?.no_reply ?? false,
3073
3188
  attachments: attachments.length > 0 ? attachments : void 0,
3189
+ sentAt: message.created_at,
3074
3190
  ackSourceType: "message",
3075
3191
  ackSourceId: message.id
3076
3192
  }
@@ -3092,9 +3208,6 @@ var ParallAgentGateway = class {
3092
3208
  return;
3093
3209
  }
3094
3210
  const event = decision.event;
3095
- const willDispatch = !this.dispatchState.mainDispatching || this.dispatchState.mainCurrentTargetId !== chatId;
3096
- if (willDispatch)
3097
- this.startTyping(chatId);
3098
3211
  try {
3099
3212
  const dispatched = await this.handleInboundEvent(event);
3100
3213
  if (dispatched) {
@@ -3106,9 +3219,6 @@ var ParallAgentGateway = class {
3106
3219
  } catch (err) {
3107
3220
  this.opts.log?.error(`parall[${this.opts.accountId}]: event dispatch failed for ${data.id}: ${String(err)}`);
3108
3221
  this.dispatchedMessages.delete(data.id);
3109
- } finally {
3110
- if (willDispatch)
3111
- this.stopTyping(chatId);
3112
3222
  }
3113
3223
  }
3114
3224
  async handleTaskAssignment(task, ackSourceId) {
@@ -3138,6 +3248,7 @@ var ParallAgentGateway = class {
3138
3248
  senderName: "system",
3139
3249
  messageId: task.id,
3140
3250
  body: parts.join("\n"),
3251
+ sentAt: task.updated_at ?? task.created_at,
3141
3252
  ackSourceType: "task_activity",
3142
3253
  ackSourceId
3143
3254
  };
@@ -3438,12 +3549,12 @@ var ParallAgentGateway = class {
3438
3549
  }
3439
3550
  }
3440
3551
  async handleHello(data) {
3441
- const { client, config, log } = this.opts;
3552
+ const { client, config, log: log2 } = this.opts;
3442
3553
  this.sessionId = data.session_id ?? "";
3443
3554
  const intervalSec = data.heartbeat_interval > 0 ? data.heartbeat_interval : 30;
3444
3555
  try {
3445
3556
  const count = await fetchAllChats(client, config.org_id, this.chatInfoMap);
3446
- log?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
3557
+ log2?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
3447
3558
  await this.opts.onSessionReady?.({
3448
3559
  activeSessionId: this.activeSessionId,
3449
3560
  ws: this.opts.ws,
@@ -3457,7 +3568,7 @@ var ParallAgentGateway = class {
3457
3568
  const expectedMs = intervalSec * 1e3;
3458
3569
  const drift = now - this.lastHeartbeatAt - expectedMs;
3459
3570
  if (drift > 15e3) {
3460
- log?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms \u2014 event loop may be blocked`);
3571
+ log2?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms \u2014 event loop may be blocked`);
3461
3572
  }
3462
3573
  this.lastHeartbeatAt = now;
3463
3574
  if (this.opts.ws.state !== "connected")
@@ -3473,10 +3584,10 @@ var ParallAgentGateway = class {
3473
3584
  const isFirstHello = !this.hadSuccessfulHello;
3474
3585
  this.hadSuccessfulHello = true;
3475
3586
  this.catchUpFromDispatch(isFirstHello).catch((err) => {
3476
- log?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
3587
+ log2?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
3477
3588
  });
3478
3589
  } catch (err) {
3479
- log?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
3590
+ log2?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
3480
3591
  }
3481
3592
  }
3482
3593
  // Resolves when in-flight dispatches hit 0 or the deadline elapses.
@@ -3581,7 +3692,7 @@ function extractDefaults(config, runtimeType) {
3581
3692
  return { model, thinkingEffort };
3582
3693
  }
3583
3694
  function createPlatformConfigManager(opts) {
3584
- const { client, stateDir, runtimeType, log } = opts;
3695
+ const { client, stateDir, runtimeType, log: log2 } = opts;
3585
3696
  let cachedVersion;
3586
3697
  let currentDefaults = { model: null, thinkingEffort: null };
3587
3698
  let currentRawConfig = null;
@@ -3598,20 +3709,20 @@ function createPlatformConfigManager(opts) {
3598
3709
  fresh = await client.getPlatformConfig(cachedVersion);
3599
3710
  } catch (err) {
3600
3711
  if (cached) {
3601
- log?.warn(`platform config fetch failed, using cached version ${cachedVersion}: ${String(err)}`);
3712
+ log2?.warn(`platform config fetch failed, using cached version ${cachedVersion}: ${String(err)}`);
3602
3713
  return currentDefaults;
3603
3714
  }
3604
- log?.warn(`platform config fetch failed and no cache available: ${String(err)}`);
3715
+ log2?.warn(`platform config fetch failed and no cache available: ${String(err)}`);
3605
3716
  return currentDefaults;
3606
3717
  }
3607
3718
  if (fresh === null) {
3608
3719
  return currentDefaults;
3609
3720
  }
3610
3721
  if (fresh.schema_version !== void 0 && fresh.schema_version > SUPPORTED_SCHEMA_VERSION) {
3611
- log?.warn(`platform config schema_version ${fresh.schema_version} > supported (${SUPPORTED_SCHEMA_VERSION}), keeping current`);
3722
+ log2?.warn(`platform config schema_version ${fresh.schema_version} > supported (${SUPPORTED_SCHEMA_VERSION}), keeping current`);
3612
3723
  return currentDefaults;
3613
3724
  }
3614
- log?.info(`platform config updated to version ${fresh.version}`);
3725
+ log2?.info(`platform config updated to version ${fresh.version}`);
3615
3726
  saveCache(stateDir, fresh);
3616
3727
  cachedVersion = fresh.version;
3617
3728
  currentRawConfig = fresh.config;
@@ -4187,8 +4298,8 @@ function stepIdFilePathForSession(stateDir, sessionKey) {
4187
4298
  // ts/claude-agent/dist/dispatch.js
4188
4299
  import * as fs5 from "node:fs";
4189
4300
  import * as path6 from "node:path";
4190
- import { randomUUID as randomUUID2 } from "node:crypto";
4191
- import { spawn } from "node:child_process";
4301
+ import { randomUUID } from "node:crypto";
4302
+ import { execSync as execSync2, spawn } from "node:child_process";
4192
4303
 
4193
4304
  // ts/agent-core/dist/internal/attachment-input.js
4194
4305
  import { execSync } from "node:child_process";
@@ -4489,7 +4600,7 @@ function sameFileIdentity(a, b) {
4489
4600
  function sameFile(a, b) {
4490
4601
  return sameFileIdentity(a, b) && a.size === b.size && a.mtimeMs === b.mtimeMs;
4491
4602
  }
4492
- async function cleanupOldAttachmentFiles(rootDir, ttlMs, log, preserveDirs) {
4603
+ async function cleanupOldAttachmentFiles(rootDir, ttlMs, log2, preserveDirs) {
4493
4604
  let entries;
4494
4605
  try {
4495
4606
  entries = await fs4.readdir(rootDir, { withFileTypes: true });
@@ -4511,11 +4622,11 @@ async function cleanupOldAttachmentFiles(rootDir, ttlMs, log, preserveDirs) {
4511
4622
  await fs4.rm(fullPath, { recursive: true, force: true });
4512
4623
  }
4513
4624
  } catch (err) {
4514
- log?.warn?.(`agent-core: failed to clean attachment temp dir ${fullPath}: ${String(err)}`);
4625
+ log2?.warn?.(`agent-core: failed to clean attachment temp dir ${fullPath}: ${String(err)}`);
4515
4626
  }
4516
4627
  }));
4517
4628
  }
4518
- async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4629
+ async function pruneAttachmentCache(rootDir, maxBytes, log2, preserveDirs) {
4519
4630
  if (maxBytes <= 0)
4520
4631
  return;
4521
4632
  let entries;
@@ -4538,7 +4649,7 @@ async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4538
4649
  dirs.push({ path: fullPath, mtimeMs: stat.mtimeMs, size });
4539
4650
  total += size;
4540
4651
  } catch (err) {
4541
- log?.warn?.(`agent-core: failed to inspect attachment cache dir ${fullPath}: ${String(err)}`);
4652
+ log2?.warn?.(`agent-core: failed to inspect attachment cache dir ${fullPath}: ${String(err)}`);
4542
4653
  }
4543
4654
  }
4544
4655
  if (total <= maxBytes)
@@ -4553,7 +4664,7 @@ async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4553
4664
  await fs4.rm(dir.path, { recursive: true, force: true });
4554
4665
  total -= dir.size;
4555
4666
  } catch (err) {
4556
- log?.warn?.(`agent-core: failed to prune attachment cache dir ${dir.path}: ${String(err)}`);
4667
+ log2?.warn?.(`agent-core: failed to prune attachment cache dir ${dir.path}: ${String(err)}`);
4557
4668
  }
4558
4669
  }
4559
4670
  }
@@ -4948,6 +5059,20 @@ async function* parseClaudeStreamJson(readable) {
4948
5059
  }
4949
5060
 
4950
5061
  // ts/claude-agent/dist/dispatch.js
5062
+ var IS_WIN32 = process.platform === "win32";
5063
+ function quoteWin32Arg(arg) {
5064
+ if (!/[\s"&|^<>()]/.test(arg))
5065
+ return arg;
5066
+ return `"${arg.replace(/"/g, '""')}"`;
5067
+ }
5068
+ function killWin32Tree(pid) {
5069
+ try {
5070
+ execSync2(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio: "ignore" });
5071
+ return true;
5072
+ } catch {
5073
+ return false;
5074
+ }
5075
+ }
4951
5076
  function buildSpawnEnv(parentEnv, claudeHome, context, opts) {
4952
5077
  const env = { ...parentEnv };
4953
5078
  if (!opts.allowApiKey) {
@@ -5089,12 +5214,12 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5089
5214
  * state.steerReadPending so the next runTurn can drain it instead of
5090
5215
  * silently losing the first event of the subsequent turn.
5091
5216
  */
5092
- async *consumeSteerTurn(sessionKey, log) {
5217
+ async *consumeSteerTurn(sessionKey, log2) {
5093
5218
  const state = this.processes.get(sessionKey);
5094
5219
  if (!state || state.done) {
5095
5220
  throw new Error("claude-agent: process dead during steer consumption");
5096
5221
  }
5097
- const groupKey = randomUUID2();
5222
+ const groupKey = randomUUID();
5098
5223
  const parserNext = state.parser.next();
5099
5224
  const firstRead = await Promise.race([
5100
5225
  parserNext.then((r) => ({ kind: "value", result: r })),
@@ -5102,7 +5227,7 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5102
5227
  ]);
5103
5228
  if (firstRead.kind === "timeout") {
5104
5229
  state.steerReadPending = parserNext;
5105
- log?.info?.(`claude-agent: steer turn timeout \u2014 steer was incorporated into previous turn`);
5230
+ log2?.info?.(`claude-agent: steer turn timeout \u2014 steer was incorporated into previous turn`);
5106
5231
  return;
5107
5232
  }
5108
5233
  let next = firstRead.result;
@@ -5132,15 +5257,15 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5132
5257
  next = await state.parser.next();
5133
5258
  }
5134
5259
  }
5135
- async *runTurn(sessionKey, promptBody, log) {
5260
+ async *runTurn(sessionKey, promptBody, log2) {
5136
5261
  let state;
5137
5262
  try {
5138
- state = this.ensureProcess(sessionKey, log);
5263
+ state = this.ensureProcess(sessionKey, log2);
5139
5264
  } catch (err) {
5140
5265
  yield { type: "error", message: `Claude spawn failed: ${String(err)}` };
5141
5266
  return;
5142
5267
  }
5143
- const groupKey = randomUUID2();
5268
+ const groupKey = randomUUID();
5144
5269
  let sawError = false;
5145
5270
  try {
5146
5271
  this.writeUserMessage(state.handle, promptBody);
@@ -5178,9 +5303,12 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5178
5303
  if (next.done) {
5179
5304
  state.done = true;
5180
5305
  this.processes.delete(sessionKey);
5306
+ const detail = state.handle.stderrChunks.join("").trim();
5307
+ const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null }));
5308
+ if (detail) {
5309
+ log2?.warn?.(`claude-agent: subprocess stderr: ${detail}`);
5310
+ }
5181
5311
  if (!sawError) {
5182
- const detail = state.handle.stderrChunks.join("").trim();
5183
- const exit = await state.handle.exitPromise.catch(() => ({ code: null, signal: null }));
5184
5312
  yield {
5185
5313
  type: "error",
5186
5314
  message: detail || `Claude exited with code ${exit.code ?? "unknown"}${exit.signal ? ` (${exit.signal})` : ""}`
@@ -5220,7 +5348,7 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5220
5348
  yield { ...parsed, groupKey };
5221
5349
  }
5222
5350
  }
5223
- ensureProcess(sessionKey, log) {
5351
+ ensureProcess(sessionKey, log2) {
5224
5352
  if (this.shuttingDown) {
5225
5353
  throw new Error("claude-agent: adapter shutting down, refusing new process");
5226
5354
  }
@@ -5235,21 +5363,22 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5235
5363
  this.processes.delete(sessionKey);
5236
5364
  }
5237
5365
  }
5238
- const handle = this.spawnProcess(sessionKey, log);
5366
+ const handle = this.spawnProcess(sessionKey, log2);
5239
5367
  const parser = parseClaudeStreamJson(handle.proc.stdout);
5240
5368
  const state = { handle, parser, done: false, needsRestart: false };
5241
5369
  this.processes.set(sessionKey, state);
5242
5370
  this.opts.sessionManager.registerProcess(sessionKey, handle);
5243
5371
  return state;
5244
5372
  }
5245
- spawnProcess(sessionKey, log) {
5373
+ spawnProcess(sessionKey, log2) {
5246
5374
  const args = this.buildArgs(sessionKey);
5247
5375
  const env = buildSpawnEnv(process.env, this.opts.claudeHome, this.buildPlaceholderContext(sessionKey), { allowApiKey: this.opts.allowApiKey, effortLevel: this._effortLevel });
5248
- log?.info(`claude-agent: spawn long-lived ${this.opts.claudeBin} (session ${sessionKey}, model=${this._model || "default"}, effort=${this._effortLevel || "default"}, mode=${this.opts.permissionMode})`);
5249
- const proc = spawn(this.opts.claudeBin, args, {
5376
+ log2?.info(`claude-agent: spawn long-lived ${this.opts.claudeBin} (session ${sessionKey}, model=${this._model || "default"}, effort=${this._effortLevel || "default"}, mode=${this.opts.permissionMode})`);
5377
+ const proc = spawn(IS_WIN32 ? quoteWin32Arg(this.opts.claudeBin) : this.opts.claudeBin, IS_WIN32 ? args.map(quoteWin32Arg) : args, {
5250
5378
  cwd: this.opts.workspaceDir,
5251
5379
  env,
5252
- stdio: ["pipe", "pipe", "pipe"]
5380
+ stdio: ["pipe", "pipe", "pipe"],
5381
+ shell: IS_WIN32
5253
5382
  });
5254
5383
  if (!proc.stdout || !proc.stderr || !proc.stdin) {
5255
5384
  throw new Error("Claude subprocess did not provide stdio pipes");
@@ -5261,7 +5390,9 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5261
5390
  proc.stdin.on("error", () => {
5262
5391
  proc.stdin.destroy();
5263
5392
  if (proc.exitCode === null && proc.signalCode === null) {
5264
- proc.kill("SIGTERM");
5393
+ if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
5394
+ proc.kill("SIGTERM");
5395
+ }
5265
5396
  }
5266
5397
  });
5267
5398
  const exitPromise = new Promise((resolve3) => {
@@ -5282,7 +5413,9 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5282
5413
  }
5283
5414
  if (state.handle.proc.exitCode === null && state.handle.proc.signalCode === null) {
5284
5415
  try {
5285
- state.handle.proc.kill("SIGTERM");
5416
+ if (!IS_WIN32 || !state.handle.proc.pid || !killWin32Tree(state.handle.proc.pid)) {
5417
+ state.handle.proc.kill("SIGTERM");
5418
+ }
5286
5419
  } catch {
5287
5420
  }
5288
5421
  }
@@ -5300,7 +5433,6 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5300
5433
  }
5301
5434
  buildArgs(sessionKey) {
5302
5435
  const args = [
5303
- "-p",
5304
5436
  "--verbose",
5305
5437
  "--input-format",
5306
5438
  "stream-json",
@@ -5351,7 +5483,7 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
5351
5483
  // ts/claude-agent/dist/session-manager.js
5352
5484
  import * as fs6 from "node:fs";
5353
5485
  import * as path7 from "node:path";
5354
- import { randomUUID as randomUUID3 } from "node:crypto";
5486
+ import { randomUUID as randomUUID2 } from "node:crypto";
5355
5487
  var ClaudeSessionManager = class _ClaudeSessionManager {
5356
5488
  mainSessionKey;
5357
5489
  stateFilePath;
@@ -5388,7 +5520,7 @@ var ClaudeSessionManager = class _ClaudeSessionManager {
5388
5520
  const parentSessionId = this.sessionIds.get(parentSessionKey);
5389
5521
  if (!parentSessionId)
5390
5522
  return null;
5391
- const sessionKey = `claude-fork:${randomUUID3()}`;
5523
+ const sessionKey = `claude-fork:${randomUUID2()}`;
5392
5524
  this.pendingForkParents.set(sessionKey, parentSessionId);
5393
5525
  return {
5394
5526
  sessionKey,
@@ -5522,7 +5654,7 @@ var ClaudeSessionManager = class _ClaudeSessionManager {
5522
5654
  // ts/claude-agent/dist/workspace.js
5523
5655
  import * as fs7 from "node:fs";
5524
5656
  import * as path8 from "node:path";
5525
- function ensureClaudeWorkspace(workspaceDir, log, agentIdentity) {
5657
+ function ensureClaudeWorkspace(workspaceDir, log2, agentIdentity) {
5526
5658
  const systemPrompt = [
5527
5659
  buildIdentity(agentIdentity),
5528
5660
  BRIDGE_WORKSPACE_INSTRUCTIONS,
@@ -5540,13 +5672,7 @@ function ensureClaudeWorkspace(workspaceDir, log, agentIdentity) {
5540
5672
  }
5541
5673
 
5542
5674
  // ts/claude-agent/dist/index.js
5543
- function createLogger(prefix) {
5544
- return {
5545
- info: (msg) => console.log(`[${prefix}] ${msg}`),
5546
- warn: (msg) => console.warn(`[${prefix}] ${msg}`),
5547
- error: (msg) => console.error(`[${prefix}] ${msg}`)
5548
- };
5549
- }
5675
+ var log = createLogger("claude-agent");
5550
5676
  async function getAgentMeWithLegacyFallback(client, orgId) {
5551
5677
  try {
5552
5678
  return await client.getAgentMe(orgId);
@@ -5560,7 +5686,6 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
5560
5686
  }
5561
5687
  async function main() {
5562
5688
  const config = resolveClaudeAgentConfig(process.env);
5563
- const log = createLogger("claude-agent");
5564
5689
  if (config.allowApiKey && (process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN)) {
5565
5690
  log.warn("PRLL_CLAUDE_ALLOW_API_KEY=1 \u2014 ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN will reach the Claude CLI; billing routes through Anthropic API pay-per-use instead of Claude.ai OAuth.");
5566
5691
  }
@@ -5680,6 +5805,6 @@ async function main() {
5680
5805
  }
5681
5806
  }
5682
5807
  main().catch((err) => {
5683
- console.error(`[claude-agent] fatal: ${String(err)}`);
5808
+ log.error(`fatal: ${String(err)}`);
5684
5809
  process.exitCode = 1;
5685
5810
  });