@parall/daemon 1.28.1 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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";
@@ -473,7 +486,6 @@ var ENDPOINTS = {
473
486
  CHAT_MESSAGES: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/messages`,
474
487
  // Messages (global, by message ID)
475
488
  MESSAGE: (id) => `${API_BASE}/messages/${id}`,
476
- MESSAGE_PATCHES: (id) => `${API_BASE}/messages/${id}/patches`,
477
489
  MESSAGE_REPLIES: (id) => `${API_BASE}/messages/${id}/replies`,
478
490
  // Upload (org-scoped)
479
491
  UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
@@ -500,6 +512,7 @@ var ENDPOINTS = {
500
512
  AGENT_SESSION: (orgId, agentId, sessionId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}`,
501
513
  AGENT_SESSION_STEPS: (orgId, agentId, sessionId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps`,
502
514
  AGENT_SESSION_STEP: (orgId, agentId, sessionId, stepId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/sessions/${sessionId}/steps/${stepId}`,
515
+ AGENT_STEP_BY_ID: (orgId, stepId) => `${API_BASE}/orgs/${orgId}/agent-steps/${stepId}`,
503
516
  AGENT_TASKS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/tasks`,
504
517
  AGENT_RUNTIME_AUTH: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/runtime-auth`,
505
518
  AGENT_RUNTIME_AUTH_SESSIONS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/runtime-auth-sessions`,
@@ -524,9 +537,12 @@ var ENDPOINTS = {
524
537
  // Attach/Detach bind an agent to/from a daemon Machine.
525
538
  MACHINE_ATTACH_AGENT: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
526
539
  MACHINE_DETACH_AGENT: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}`,
540
+ MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
527
541
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
528
542
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
529
543
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
544
+ MACHINE_RUNTIME_AUTH_SESSIONS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions`,
545
+ MACHINE_RUNTIME_AUTH_SESSION_COMPLETE: (orgId, machineId, sessionId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions/${sessionId}/complete`,
530
546
  // Machine self-control-plane (mck_-scoped). The bearer token implicitly
531
547
  // identifies the Machine, so there is no `:mid` URL parameter — these are
532
548
  // "self" routes called by the daemon for its own host.
@@ -1167,9 +1183,6 @@ var ParallClient = class _ParallClient {
1167
1183
  async deleteMessage(id) {
1168
1184
  return this.request("DELETE", ENDPOINTS.MESSAGE(id));
1169
1185
  }
1170
- async patchMessage(id, req) {
1171
- return this.request("POST", ENDPOINTS.MESSAGE_PATCHES(id), req);
1172
- }
1173
1186
  async getMessageReplies(id, params) {
1174
1187
  return this.request("GET", ENDPOINTS.MESSAGE_REPLIES(id), void 0, params);
1175
1188
  }
@@ -1262,8 +1275,7 @@ var ParallClient = class _ParallClient {
1262
1275
  * @param params.status - Comma-separated status filter (e.g., `'open'`).
1263
1276
  */
1264
1277
  async getAgentSessions(orgId, agentId, params) {
1265
- const res = await this.request("GET", ENDPOINTS.AGENT_SESSIONS(orgId, agentId), void 0, params);
1266
- return res.data;
1278
+ return this.request("GET", ENDPOINTS.AGENT_SESSIONS(orgId, agentId), void 0, params);
1267
1279
  }
1268
1280
  async getAgentSession(orgId, agentId, sessionId) {
1269
1281
  return this.request("GET", ENDPOINTS.AGENT_SESSION(orgId, agentId, sessionId));
@@ -1275,12 +1287,14 @@ var ParallClient = class _ParallClient {
1275
1287
  return this.request("POST", ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), req);
1276
1288
  }
1277
1289
  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;
1290
+ return this.request("GET", ENDPOINTS.AGENT_SESSION_STEPS(orgId, agentId, sessionId), void 0, params);
1280
1291
  }
1281
1292
  async getAgentSessionStep(orgId, agentId, sessionId, stepId) {
1282
1293
  return this.request("GET", ENDPOINTS.AGENT_SESSION_STEP(orgId, agentId, sessionId, stepId));
1283
1294
  }
1295
+ async getAgentStepById(orgId, stepId) {
1296
+ return this.request("GET", ENDPOINTS.AGENT_STEP_BY_ID(orgId, stepId));
1297
+ }
1284
1298
  // ---- Agent runtime auth (hosted Claude OAuth) ----
1285
1299
  async getAgentRuntimeAuth(orgId, agentId) {
1286
1300
  return this.request("GET", ENDPOINTS.AGENT_RUNTIME_AUTH(orgId, agentId));
@@ -1377,10 +1391,22 @@ var ParallClient = class _ParallClient {
1377
1391
  async detachAgent(orgId, machineId, agentId) {
1378
1392
  return this.request("DELETE", ENDPOINTS.MACHINE_DETACH_AGENT(orgId, machineId, agentId));
1379
1393
  }
1394
+ async patchMachineLLMSource(orgId, machineId, llmSource) {
1395
+ return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource });
1396
+ }
1380
1397
  /** Get machine-level runtime auth state. */
1381
1398
  async getMachineRuntimeAuth(orgId, machineId) {
1382
1399
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1383
1400
  }
1401
+ async startMachineRuntimeAuthSession(orgId, machineId, req = {}) {
1402
+ return this.request("POST", ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSIONS(orgId, machineId), req);
1403
+ }
1404
+ async completeMachineRuntimeAuthSession(orgId, machineId, sessionId, req) {
1405
+ return this.request("POST", ENDPOINTS.MACHINE_RUNTIME_AUTH_SESSION_COMPLETE(orgId, machineId, sessionId), req);
1406
+ }
1407
+ async disconnectMachineRuntimeAuth(orgId, machineId) {
1408
+ return this.request("DELETE", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
1409
+ }
1384
1410
  // ---- Machine self-control-plane (mck_-scoped) ----
1385
1411
  //
1386
1412
  // The four methods below are intended to be called from a daemon-mode
@@ -2312,9 +2338,9 @@ var ParallAgentGateway = class {
2312
2338
  this.SHUTDOWN_DEADLINE_MS = opts.shutdownDeadlineMs ?? 6e4;
2313
2339
  }
2314
2340
  async run(abortSignal) {
2315
- const { ws, log } = this.opts;
2341
+ const { ws, log: log2 } = this.opts;
2316
2342
  ws.onStateChange((state) => {
2317
- log?.info(`parall[${this.opts.accountId}]: connection state \u2192 ${state}`);
2343
+ log2?.info(`parall[${this.opts.accountId}]: connection state \u2192 ${state}`);
2318
2344
  });
2319
2345
  ws.on("hello", async (data) => {
2320
2346
  await this.handleHello(data);
@@ -2727,7 +2753,8 @@ var ParallAgentGateway = class {
2727
2753
  continue;
2728
2754
  }
2729
2755
  if (!binding) {
2730
- throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session`);
2756
+ const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
2757
+ throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
2731
2758
  }
2732
2759
  if (!triggerMessageSet) {
2733
2760
  triggerMessageSet = true;
@@ -2842,6 +2869,7 @@ var ParallAgentGateway = class {
2842
2869
  targetId: fork.targetId,
2843
2870
  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
2871
  },
2872
+ eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
2845
2873
  actions: [],
2846
2874
  agentSummary,
2847
2875
  historyPath
@@ -2881,32 +2909,11 @@ var ParallAgentGateway = class {
2881
2909
  return;
2882
2910
  this.draining = true;
2883
2911
  try {
2884
- while (this.dispatchState.mainBuffer.length > 0 || this.dispatchState.pendingForkResults.length > 0) {
2912
+ while (this.dispatchState.mainBuffer.length > 0) {
2885
2913
  if (this.shuttingDown) {
2886
2914
  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
2915
  break;
2888
2916
  }
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
2917
  const targetId = this.dispatchState.mainBuffer[0].targetId;
2911
2918
  const events = [];
2912
2919
  while (this.dispatchState.mainBuffer[0]?.targetId === targetId) {
@@ -3438,12 +3445,12 @@ var ParallAgentGateway = class {
3438
3445
  }
3439
3446
  }
3440
3447
  async handleHello(data) {
3441
- const { client, config, log } = this.opts;
3448
+ const { client, config, log: log2 } = this.opts;
3442
3449
  this.sessionId = data.session_id ?? "";
3443
3450
  const intervalSec = data.heartbeat_interval > 0 ? data.heartbeat_interval : 30;
3444
3451
  try {
3445
3452
  const count = await fetchAllChats(client, config.org_id, this.chatInfoMap);
3446
- log?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
3453
+ log2?.info(`parall[${this.opts.accountId}]: WebSocket connected, ${count} chats cached`);
3447
3454
  await this.opts.onSessionReady?.({
3448
3455
  activeSessionId: this.activeSessionId,
3449
3456
  ws: this.opts.ws,
@@ -3457,7 +3464,7 @@ var ParallAgentGateway = class {
3457
3464
  const expectedMs = intervalSec * 1e3;
3458
3465
  const drift = now - this.lastHeartbeatAt - expectedMs;
3459
3466
  if (drift > 15e3) {
3460
- log?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms \u2014 event loop may be blocked`);
3467
+ log2?.warn(`parall[${this.opts.accountId}]: heartbeat drift ${drift}ms \u2014 event loop may be blocked`);
3461
3468
  }
3462
3469
  this.lastHeartbeatAt = now;
3463
3470
  if (this.opts.ws.state !== "connected")
@@ -3473,10 +3480,10 @@ var ParallAgentGateway = class {
3473
3480
  const isFirstHello = !this.hadSuccessfulHello;
3474
3481
  this.hadSuccessfulHello = true;
3475
3482
  this.catchUpFromDispatch(isFirstHello).catch((err) => {
3476
- log?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
3483
+ log2?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
3477
3484
  });
3478
3485
  } catch (err) {
3479
- log?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
3486
+ log2?.error(`parall[${this.opts.accountId}]: failed to fetch chats: ${String(err)}`);
3480
3487
  }
3481
3488
  }
3482
3489
  // Resolves when in-flight dispatches hit 0 or the deadline elapses.
@@ -3581,7 +3588,7 @@ function extractDefaults(config, runtimeType) {
3581
3588
  return { model, thinkingEffort };
3582
3589
  }
3583
3590
  function createPlatformConfigManager(opts) {
3584
- const { client, stateDir, runtimeType, log } = opts;
3591
+ const { client, stateDir, runtimeType, log: log2 } = opts;
3585
3592
  let cachedVersion;
3586
3593
  let currentDefaults = { model: null, thinkingEffort: null };
3587
3594
  let currentRawConfig = null;
@@ -3598,20 +3605,20 @@ function createPlatformConfigManager(opts) {
3598
3605
  fresh = await client.getPlatformConfig(cachedVersion);
3599
3606
  } catch (err) {
3600
3607
  if (cached) {
3601
- log?.warn(`platform config fetch failed, using cached version ${cachedVersion}: ${String(err)}`);
3608
+ log2?.warn(`platform config fetch failed, using cached version ${cachedVersion}: ${String(err)}`);
3602
3609
  return currentDefaults;
3603
3610
  }
3604
- log?.warn(`platform config fetch failed and no cache available: ${String(err)}`);
3611
+ log2?.warn(`platform config fetch failed and no cache available: ${String(err)}`);
3605
3612
  return currentDefaults;
3606
3613
  }
3607
3614
  if (fresh === null) {
3608
3615
  return currentDefaults;
3609
3616
  }
3610
3617
  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`);
3618
+ log2?.warn(`platform config schema_version ${fresh.schema_version} > supported (${SUPPORTED_SCHEMA_VERSION}), keeping current`);
3612
3619
  return currentDefaults;
3613
3620
  }
3614
- log?.info(`platform config updated to version ${fresh.version}`);
3621
+ log2?.info(`platform config updated to version ${fresh.version}`);
3615
3622
  saveCache(stateDir, fresh);
3616
3623
  cachedVersion = fresh.version;
3617
3624
  currentRawConfig = fresh.config;
@@ -4199,9 +4206,8 @@ function stepIdFilePathForSession(stateDir, sessionKey) {
4199
4206
  }
4200
4207
 
4201
4208
  // ts/codex-agent/dist/dispatch.js
4202
- import { spawn } from "node:child_process";
4203
- import { execSync as execSync2 } from "node:child_process";
4204
- import { randomUUID as randomUUID2 } from "node:crypto";
4209
+ import { execSync as execSync2, spawn } from "node:child_process";
4210
+ import { randomUUID } from "node:crypto";
4205
4211
  import * as fs5 from "node:fs";
4206
4212
 
4207
4213
  // ts/agent-core/dist/internal/attachment-input.js
@@ -4503,7 +4509,7 @@ function sameFileIdentity(a, b) {
4503
4509
  function sameFile(a, b) {
4504
4510
  return sameFileIdentity(a, b) && a.size === b.size && a.mtimeMs === b.mtimeMs;
4505
4511
  }
4506
- async function cleanupOldAttachmentFiles(rootDir, ttlMs, log, preserveDirs) {
4512
+ async function cleanupOldAttachmentFiles(rootDir, ttlMs, log2, preserveDirs) {
4507
4513
  let entries;
4508
4514
  try {
4509
4515
  entries = await fs4.readdir(rootDir, { withFileTypes: true });
@@ -4525,11 +4531,11 @@ async function cleanupOldAttachmentFiles(rootDir, ttlMs, log, preserveDirs) {
4525
4531
  await fs4.rm(fullPath, { recursive: true, force: true });
4526
4532
  }
4527
4533
  } catch (err) {
4528
- log?.warn?.(`agent-core: failed to clean attachment temp dir ${fullPath}: ${String(err)}`);
4534
+ log2?.warn?.(`agent-core: failed to clean attachment temp dir ${fullPath}: ${String(err)}`);
4529
4535
  }
4530
4536
  }));
4531
4537
  }
4532
- async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4538
+ async function pruneAttachmentCache(rootDir, maxBytes, log2, preserveDirs) {
4533
4539
  if (maxBytes <= 0)
4534
4540
  return;
4535
4541
  let entries;
@@ -4552,7 +4558,7 @@ async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4552
4558
  dirs.push({ path: fullPath, mtimeMs: stat.mtimeMs, size });
4553
4559
  total += size;
4554
4560
  } catch (err) {
4555
- log?.warn?.(`agent-core: failed to inspect attachment cache dir ${fullPath}: ${String(err)}`);
4561
+ log2?.warn?.(`agent-core: failed to inspect attachment cache dir ${fullPath}: ${String(err)}`);
4556
4562
  }
4557
4563
  }
4558
4564
  if (total <= maxBytes)
@@ -4567,7 +4573,7 @@ async function pruneAttachmentCache(rootDir, maxBytes, log, preserveDirs) {
4567
4573
  await fs4.rm(dir.path, { recursive: true, force: true });
4568
4574
  total -= dir.size;
4569
4575
  } catch (err) {
4570
- log?.warn?.(`agent-core: failed to prune attachment cache dir ${dir.path}: ${String(err)}`);
4576
+ log2?.warn?.(`agent-core: failed to prune attachment cache dir ${dir.path}: ${String(err)}`);
4571
4577
  }
4572
4578
  }
4573
4579
  }
@@ -4996,14 +5002,16 @@ var DEFAULT_REQUEST_TIMEOUT_MS = 12e4;
4996
5002
  var JsonRpcStdioClient = class {
4997
5003
  proc;
4998
5004
  requestTimeoutMs;
5005
+ killProcess;
4999
5006
  nextId = 1;
5000
5007
  pending = /* @__PURE__ */ new Map();
5001
5008
  buffer = "";
5002
5009
  onNotification = null;
5003
5010
  disposed = false;
5004
- constructor(proc, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
5011
+ constructor(proc, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, killProcess) {
5005
5012
  this.proc = proc;
5006
5013
  this.requestTimeoutMs = requestTimeoutMs;
5014
+ this.killProcess = killProcess;
5007
5015
  proc.stdout.setEncoding("utf8");
5008
5016
  proc.stdout.on("data", (chunk) => this.ingest(chunk));
5009
5017
  proc.once("close", () => this.dispose(new Error("app-server subprocess closed")));
@@ -5063,7 +5071,11 @@ var JsonRpcStdioClient = class {
5063
5071
  killUnhealthy(err) {
5064
5072
  this.dispose(err);
5065
5073
  if (this.proc.exitCode === null && this.proc.signalCode === null) {
5066
- this.proc.kill("SIGTERM");
5074
+ if (this.killProcess) {
5075
+ this.killProcess(this.proc);
5076
+ } else {
5077
+ this.proc.kill("SIGTERM");
5078
+ }
5067
5079
  }
5068
5080
  }
5069
5081
  ingest(chunk) {
@@ -5110,6 +5122,20 @@ function isNotification(m) {
5110
5122
  }
5111
5123
 
5112
5124
  // ts/codex-agent/dist/dispatch.js
5125
+ var IS_WIN32 = process.platform === "win32";
5126
+ function quoteWin32Arg(arg) {
5127
+ if (!/[\s"&|^<>()]/.test(arg))
5128
+ return arg;
5129
+ return `"${arg.replace(/"/g, '""')}"`;
5130
+ }
5131
+ function killWin32Tree(pid) {
5132
+ try {
5133
+ execSync2(`taskkill /T /F /PID ${pid}`, { windowsHide: true, stdio: "ignore" });
5134
+ return true;
5135
+ } catch {
5136
+ return false;
5137
+ }
5138
+ }
5113
5139
  var CodexAppServerAdapter = class {
5114
5140
  opts;
5115
5141
  client = null;
@@ -5127,10 +5153,10 @@ var CodexAppServerAdapter = class {
5127
5153
  * replacement would be a perpetually hung dispatch generator, which is
5128
5154
  * hard to debug.
5129
5155
  */
5130
- setActiveTurn(threadId, sink, log) {
5156
+ setActiveTurn(threadId, sink, log2) {
5131
5157
  const existing = this.activeTurns.get(threadId);
5132
5158
  if (existing) {
5133
- (log ?? this.opts.log)?.warn?.(`codex-agent: thread ${threadId} already had an active turn; failing the previous dispatch`);
5159
+ (log2 ?? this.opts.log)?.warn?.(`codex-agent: thread ${threadId} already had an active turn; failing the previous dispatch`);
5134
5160
  existing.push({ kind: "error", message: `thread ${threadId} replaced by concurrent turn` });
5135
5161
  existing.close();
5136
5162
  }
@@ -5152,7 +5178,7 @@ var CodexAppServerAdapter = class {
5152
5178
  yield { type: "error", message: "Codex app-server not available (subprocess died during dispatch start)" };
5153
5179
  return;
5154
5180
  }
5155
- const log = this.opts.log ?? context.log;
5181
+ const log2 = this.opts.log ?? context.log;
5156
5182
  const isMainSession = this.opts.sessionManager.isMain(sessionKey);
5157
5183
  let threadId = this.opts.sessionManager.getThreadId(sessionKey);
5158
5184
  if (!threadId) {
@@ -5170,7 +5196,7 @@ var CodexAppServerAdapter = class {
5170
5196
  this.opts.sessionManager.recordThreadId(sessionKey, threadId);
5171
5197
  this.resumedThreadIds.add(threadId);
5172
5198
  } catch (err) {
5173
- log?.warn?.(`codex-agent: thread/resume failed (${errToString(err)}); attempting one-shot fresh-thread start`);
5199
+ log2?.warn?.(`codex-agent: thread/resume failed (${errToString(err)}); attempting one-shot fresh-thread start`);
5174
5200
  let freshThreadId;
5175
5201
  try {
5176
5202
  freshThreadId = await this.openThread(client, { resumeId: void 0 });
@@ -5188,8 +5214,8 @@ var CodexAppServerAdapter = class {
5188
5214
  }
5189
5215
  }
5190
5216
  const sink = new TurnSink();
5191
- this.setActiveTurn(threadId, sink, log);
5192
- const groupKey = randomUUID2();
5217
+ this.setActiveTurn(threadId, sink, log2);
5218
+ const groupKey = randomUUID();
5193
5219
  let sawTurnEnd = false;
5194
5220
  let releasePreparedAttachments = () => {
5195
5221
  };
@@ -5199,13 +5225,13 @@ var CodexAppServerAdapter = class {
5199
5225
  try {
5200
5226
  const prepared = await appendPreparedLocalAttachmentRefs(bodyForAgent, event, context, {
5201
5227
  workspaceDir: this.opts.workspaceDir,
5202
- log
5228
+ log: log2
5203
5229
  });
5204
5230
  preparedBody = prepared.body;
5205
5231
  preparedImages = prepared.attachments.images;
5206
5232
  releasePreparedAttachments = pinLocalAttachmentPaths(preparedImages);
5207
5233
  } catch (err) {
5208
- log?.warn?.(`codex-agent[${context.accountId}]: failed to prepare local attachments: ${errToString(err)}`);
5234
+ log2?.warn?.(`codex-agent[${context.accountId}]: failed to prepare local attachments: ${errToString(err)}`);
5209
5235
  }
5210
5236
  const turnInput = buildTurnInput(preparedBody, preparedImages);
5211
5237
  const startTurn = (targetThreadId) => client.sendRequest("turn/start", {
@@ -5226,7 +5252,7 @@ var CodexAppServerAdapter = class {
5226
5252
  yield { type: "error", message: `Codex turn/start failed: ${message}` };
5227
5253
  return;
5228
5254
  }
5229
- log?.warn?.(`codex-agent: turn/start on thread ${threadId} failed (${message}); attempting one-shot fresh-thread retry`);
5255
+ log2?.warn?.(`codex-agent: turn/start on thread ${threadId} failed (${message}); attempting one-shot fresh-thread retry`);
5230
5256
  this.activeTurns.delete(threadId);
5231
5257
  let freshThreadId;
5232
5258
  try {
@@ -5240,7 +5266,7 @@ var CodexAppServerAdapter = class {
5240
5266
  yield { type: "error", message: `Codex turn/start failed; could not create replacement thread: ${errToString(createErr)}` };
5241
5267
  return;
5242
5268
  }
5243
- this.setActiveTurn(freshThreadId, sink, log);
5269
+ this.setActiveTurn(freshThreadId, sink, log2);
5244
5270
  try {
5245
5271
  turnStartResult = await startTurn(freshThreadId);
5246
5272
  } catch (retryErr) {
@@ -5341,10 +5367,12 @@ var CodexAppServerAdapter = class {
5341
5367
  if (client)
5342
5368
  client.dispose(new Error("adapter stopped"));
5343
5369
  if (proc && proc.exitCode === null && proc.signalCode === null) {
5344
- proc.kill("SIGTERM");
5370
+ if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
5371
+ proc.kill("SIGTERM");
5372
+ }
5345
5373
  }
5346
5374
  }
5347
- async ensureStarted(log) {
5375
+ async ensureStarted(log2) {
5348
5376
  if (this.client?.isDisposed()) {
5349
5377
  for (const activeSink of this.activeTurns.values()) {
5350
5378
  activeSink.push({ kind: "error", message: "Codex app-server disposed; resetting adapter" });
@@ -5360,14 +5388,14 @@ var CodexAppServerAdapter = class {
5360
5388
  return;
5361
5389
  if (this.startPromise)
5362
5390
  return this.startPromise;
5363
- this.startPromise = this.doStart(log);
5391
+ this.startPromise = this.doStart(log2);
5364
5392
  try {
5365
5393
  await this.startPromise;
5366
5394
  } finally {
5367
5395
  this.startPromise = null;
5368
5396
  }
5369
5397
  }
5370
- async doStart(log) {
5398
+ async doStart(log2) {
5371
5399
  this.stopping = false;
5372
5400
  ensureGitRepo(this.opts.workspaceDir);
5373
5401
  const env = {
@@ -5380,20 +5408,25 @@ var CodexAppServerAdapter = class {
5380
5408
  env.PRLL_CONTEXT_FILE = this.opts.contextFilePath;
5381
5409
  }
5382
5410
  const args = ["app-server", "--listen", "stdio://"];
5383
- (log ?? this.opts.log)?.info?.(`codex-agent: spawning ${this.opts.codexBin} ${args.join(" ")}`);
5384
- const proc = spawn(this.opts.codexBin, args, {
5411
+ (log2 ?? this.opts.log)?.info?.(`codex-agent: spawning ${this.opts.codexBin} ${args.join(" ")}`);
5412
+ const proc = spawn(IS_WIN32 ? quoteWin32Arg(this.opts.codexBin) : this.opts.codexBin, IS_WIN32 ? args.map(quoteWin32Arg) : args, {
5385
5413
  cwd: this.opts.workspaceDir,
5386
5414
  env,
5387
- stdio: ["pipe", "pipe", "pipe"]
5415
+ stdio: ["pipe", "pipe", "pipe"],
5416
+ shell: IS_WIN32
5388
5417
  });
5389
5418
  proc.stderr.setEncoding("utf8");
5390
5419
  proc.stderr.on("data", (chunk) => {
5391
- (log ?? this.opts.log)?.warn?.(`codex-agent[stderr]: ${chunk.trim()}`);
5420
+ (log2 ?? this.opts.log)?.warn?.(`codex-agent[stderr]: ${chunk.trim()}`);
5421
+ });
5422
+ const client = new JsonRpcStdioClient(proc, void 0, (p) => {
5423
+ if (!IS_WIN32 || !p.pid || !killWin32Tree(p.pid)) {
5424
+ p.kill("SIGTERM");
5425
+ }
5392
5426
  });
5393
- const client = new JsonRpcStdioClient(proc);
5394
5427
  client.setNotificationHandler((method, params) => this.routeNotification(method, params));
5395
- proc.once("close", (code, signal) => this.handleSubprocessClose(proc, code, signal, log));
5396
- proc.once("error", (err) => this.handleSubprocessClose(proc, null, null, log, err));
5428
+ proc.once("close", (code, signal) => this.handleSubprocessClose(proc, code, signal, log2));
5429
+ proc.once("error", (err) => this.handleSubprocessClose(proc, null, null, log2, err));
5397
5430
  try {
5398
5431
  await client.sendRequest("initialize", {
5399
5432
  clientInfo: { name: "parall-codex-agent", version: "1" },
@@ -5402,19 +5435,22 @@ var CodexAppServerAdapter = class {
5402
5435
  client.sendNotification("initialized", {});
5403
5436
  } catch (err) {
5404
5437
  client.dispose(err instanceof Error ? err : new Error(String(err)));
5405
- if (proc.exitCode === null && proc.signalCode === null)
5406
- proc.kill("SIGTERM");
5438
+ if (proc.exitCode === null && proc.signalCode === null) {
5439
+ if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
5440
+ proc.kill("SIGTERM");
5441
+ }
5442
+ }
5407
5443
  throw err;
5408
5444
  }
5409
5445
  this.proc = proc;
5410
5446
  this.client = client;
5411
5447
  this.initialized = true;
5412
5448
  }
5413
- handleSubprocessClose(proc, code, signal, log, err) {
5449
+ handleSubprocessClose(proc, code, signal, log2, err) {
5414
5450
  if (this.proc !== null && this.proc !== proc)
5415
5451
  return;
5416
5452
  const reason = err ? `spawn error: ${err.message}` : `exited (code=${code ?? "null"}${signal ? `, signal=${signal}` : ""})`;
5417
- const logger = log ?? this.opts.log;
5453
+ const logger = log2 ?? this.opts.log;
5418
5454
  if (this.stopping) {
5419
5455
  logger?.info?.(`codex-agent: app-server subprocess ${reason} during graceful stop`);
5420
5456
  } else {
@@ -6332,7 +6368,7 @@ function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
6332
6368
  }
6333
6369
 
6334
6370
  // ts/codex-agent/dist/workspace.js
6335
- function ensureWorkspaceTrusted(codexHome, workspaceDir, log) {
6371
+ function ensureWorkspaceTrusted(codexHome, workspaceDir, log2) {
6336
6372
  const configPath = path7.join(codexHome, "config.toml");
6337
6373
  const normalizedPath = path7.resolve(workspaceDir);
6338
6374
  try {
@@ -6348,7 +6384,7 @@ function ensureWorkspaceTrusted(codexHome, workspaceDir, log) {
6348
6384
  try {
6349
6385
  parsed = parse(content);
6350
6386
  } catch {
6351
- log?.warn(`Codex config.toml is not valid TOML; skipping trust write for ${normalizedPath}`);
6387
+ log2?.warn(`Codex config.toml is not valid TOML; skipping trust write for ${normalizedPath}`);
6352
6388
  return;
6353
6389
  }
6354
6390
  }
@@ -6380,9 +6416,9 @@ ${trustLine}
6380
6416
  }
6381
6417
  fs7.writeFileSync(configPath, content, "utf8");
6382
6418
  } else if (projects?.[normalizedPath] !== void 0) {
6383
- log?.warn(`Codex config.toml has non-canonical header for ${normalizedPath}; skipping trust write`);
6419
+ log2?.warn(`Codex config.toml has non-canonical header for ${normalizedPath}; skipping trust write`);
6384
6420
  } else if (projects && !content.includes("[projects.")) {
6385
- log?.warn(`Codex config.toml uses inline table for projects; skipping trust write for ${normalizedPath}`);
6421
+ log2?.warn(`Codex config.toml uses inline table for projects; skipping trust write for ${normalizedPath}`);
6386
6422
  } else {
6387
6423
  fs7.mkdirSync(codexHome, { recursive: true });
6388
6424
  fs7.appendFileSync(configPath, `
@@ -6391,7 +6427,7 @@ ${trustLine}
6391
6427
  `, "utf8");
6392
6428
  }
6393
6429
  } catch (err) {
6394
- log?.warn(`failed to write Codex project trust for ${normalizedPath}: ${String(err)}`);
6430
+ log2?.warn(`failed to write Codex project trust for ${normalizedPath}: ${String(err)}`);
6395
6431
  }
6396
6432
  }
6397
6433
  function isParallProxyMode(env = process.env) {
@@ -6401,7 +6437,7 @@ function isParallProxyMode(env = process.env) {
6401
6437
  return false;
6402
6438
  return baseUrl === apiUrl || baseUrl.startsWith(`${apiUrl}/`);
6403
6439
  }
6404
- function ensureParallProvider(codexHome, apiUrl, log) {
6440
+ function ensureParallProvider(codexHome, apiUrl, log2) {
6405
6441
  const configPath = path7.join(codexHome, "config.toml");
6406
6442
  const baseUrl = apiUrl.replace(/\/$/, "") + "/api/llm/v1";
6407
6443
  try {
@@ -6445,7 +6481,7 @@ function findSectionEnd(content, fromIndex) {
6445
6481
  const nextHeader = content.indexOf("\n[", fromIndex);
6446
6482
  return nextHeader === -1 ? content.length : nextHeader;
6447
6483
  }
6448
- function ensureCodexWorkspace(workspaceDir, log, agentIdentity) {
6484
+ function ensureCodexWorkspace(workspaceDir, log2, agentIdentity) {
6449
6485
  const systemPrompt = [
6450
6486
  buildIdentity(agentIdentity),
6451
6487
  BRIDGE_WORKSPACE_INSTRUCTIONS,
@@ -6468,13 +6504,7 @@ ${systemPrompt.replace(/\\/g, "\\\\").replace(/"""/g, '\\"""')}
6468
6504
  }
6469
6505
 
6470
6506
  // ts/codex-agent/dist/index.js
6471
- function createLogger(prefix) {
6472
- return {
6473
- info: (msg) => console.log(`[${prefix}] ${msg}`),
6474
- warn: (msg) => console.warn(`[${prefix}] ${msg}`),
6475
- error: (msg) => console.error(`[${prefix}] ${msg}`)
6476
- };
6477
- }
6507
+ var log = createLogger("codex-agent");
6478
6508
  async function getAgentMeWithLegacyFallback(client, orgId) {
6479
6509
  try {
6480
6510
  return await client.getAgentMe(orgId);
@@ -6488,7 +6518,6 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
6488
6518
  }
6489
6519
  async function main() {
6490
6520
  const config = resolveCodexAgentConfig(process.env);
6491
- const log = createLogger("codex-agent");
6492
6521
  const client = new ParallClient({
6493
6522
  baseUrl: config.apiUrl,
6494
6523
  token: config.apiKey,
@@ -6596,7 +6625,7 @@ async function main() {
6596
6625
  }
6597
6626
  }
6598
6627
  main().catch((err) => {
6599
- console.error(`[codex-agent] fatal: ${String(err)}`);
6628
+ log.error(`fatal: ${String(err)}`);
6600
6629
  process.exitCode = 1;
6601
6630
  });
6602
6631
  /*! Bundled license information: