@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.
- package/bundle/manifest.json +10 -10
- package/bundle/parall-claude-agent.js +107 -86
- package/bundle/parall-codex-agent.js +130 -101
- package/bundle/parall-daemon.js +161 -67
- package/bundle/parall-openclaw-agent.js +22 -14
- package/dist/index.js +4 -10
- package/dist/runtimes.d.ts +8 -1
- package/dist/runtimes.d.ts.map +1 -1
- package/dist/runtimes.js +49 -3
- package/dist/supervisor.d.ts +5 -6
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +41 -2
- package/package.json +7 -5
|
@@ -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 = [
|
|
147
|
-
|
|
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(`[
|
|
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(`[
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3483
|
+
log2?.warn(`parall[${this.opts.accountId}]: dispatch catch-up failed: ${String(err)}`);
|
|
3477
3484
|
});
|
|
3478
3485
|
} catch (err) {
|
|
3479
|
-
|
|
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
|
-
|
|
3608
|
+
log2?.warn(`platform config fetch failed, using cached version ${cachedVersion}: ${String(err)}`);
|
|
3602
3609
|
return currentDefaults;
|
|
3603
3610
|
}
|
|
3604
|
-
|
|
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
|
-
|
|
3618
|
+
log2?.warn(`platform config schema_version ${fresh.schema_version} > supported (${SUPPORTED_SCHEMA_VERSION}), keeping current`);
|
|
3612
3619
|
return currentDefaults;
|
|
3613
3620
|
}
|
|
3614
|
-
|
|
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 {
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
5156
|
+
setActiveTurn(threadId, sink, log2) {
|
|
5131
5157
|
const existing = this.activeTurns.get(threadId);
|
|
5132
5158
|
if (existing) {
|
|
5133
|
-
(
|
|
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
|
|
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
|
-
|
|
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,
|
|
5192
|
-
const groupKey =
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
|
5370
|
+
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
5371
|
+
proc.kill("SIGTERM");
|
|
5372
|
+
}
|
|
5345
5373
|
}
|
|
5346
5374
|
}
|
|
5347
|
-
async ensureStarted(
|
|
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(
|
|
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(
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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,
|
|
5396
|
-
proc.once("error", (err) => this.handleSubprocessClose(proc, null, null,
|
|
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.
|
|
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,
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
6419
|
+
log2?.warn(`Codex config.toml has non-canonical header for ${normalizedPath}; skipping trust write`);
|
|
6384
6420
|
} else if (projects && !content.includes("[projects.")) {
|
|
6385
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
6628
|
+
log.error(`fatal: ${String(err)}`);
|
|
6600
6629
|
process.exitCode = 1;
|
|
6601
6630
|
});
|
|
6602
6631
|
/*! Bundled license information:
|