@ycodium-ai/agent-codex 0.2.2130 → 0.2.2147
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/dist/index.js +180 -48
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -92,6 +92,7 @@ var CODEX_CARD = {
|
|
|
92
92
|
|
|
93
93
|
// src/codexInstance.ts
|
|
94
94
|
import * as NodeProcess from "node:process";
|
|
95
|
+
import { ExecutorSpawnRefusedError } from "@ycodium-ai/plugin-api/executor";
|
|
95
96
|
|
|
96
97
|
// src/codexAccount.ts
|
|
97
98
|
import * as NodeFS from "node:fs";
|
|
@@ -755,6 +756,10 @@ function asString(value) {
|
|
|
755
756
|
function asNumber(value) {
|
|
756
757
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
757
758
|
}
|
|
759
|
+
function codexVersionFromInitialize(initializeResult) {
|
|
760
|
+
const userAgent = isRecord3(initializeResult) ? asString(initializeResult["userAgent"]) : null;
|
|
761
|
+
return userAgent?.match(/\/(\S+)/)?.[1] ?? null;
|
|
762
|
+
}
|
|
758
763
|
function decodeThreadOpen(result) {
|
|
759
764
|
const thread = isRecord3(result) ? isRecord3(result["thread"]) ? result["thread"] : result : null;
|
|
760
765
|
const id = thread ? asString(thread["id"]) : null;
|
|
@@ -992,7 +997,15 @@ async function createCodexRpcClient(handle, handlers) {
|
|
|
992
997
|
const settled = new Promise((resolve2, reject) => {
|
|
993
998
|
pending.set(id, { resolve: resolve2, reject, method });
|
|
994
999
|
});
|
|
995
|
-
|
|
1000
|
+
try {
|
|
1001
|
+
await Promise.race([
|
|
1002
|
+
writeLine({ id, method, ...params === void 0 ? {} : { params } }),
|
|
1003
|
+
settled
|
|
1004
|
+
]);
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
pending.delete(id);
|
|
1007
|
+
throw error;
|
|
1008
|
+
}
|
|
996
1009
|
const limit = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
997
1010
|
if (limit <= 0) return await settled;
|
|
998
1011
|
let timer;
|
|
@@ -1033,7 +1046,15 @@ async function createCodexRpcClient(handle, handlers) {
|
|
|
1033
1046
|
failAll("the client was closed");
|
|
1034
1047
|
await Promise.all([pumpStdout, pumpStderr]);
|
|
1035
1048
|
};
|
|
1036
|
-
return {
|
|
1049
|
+
return {
|
|
1050
|
+
request,
|
|
1051
|
+
notify,
|
|
1052
|
+
respond,
|
|
1053
|
+
respondError,
|
|
1054
|
+
close,
|
|
1055
|
+
pid: handle.pid,
|
|
1056
|
+
pendingCountForTests: () => pending.size
|
|
1057
|
+
};
|
|
1037
1058
|
}
|
|
1038
1059
|
|
|
1039
1060
|
// src/approvalGrant.ts
|
|
@@ -1339,6 +1360,20 @@ function toTurnStatus(status) {
|
|
|
1339
1360
|
return "completed";
|
|
1340
1361
|
}
|
|
1341
1362
|
}
|
|
1363
|
+
var COLLAB_CHILD_STATUSES = /* @__PURE__ */ new Set([
|
|
1364
|
+
"running",
|
|
1365
|
+
"idle",
|
|
1366
|
+
"failed",
|
|
1367
|
+
"interrupted",
|
|
1368
|
+
"cancelled"
|
|
1369
|
+
]);
|
|
1370
|
+
function asCollabChildStatus(value) {
|
|
1371
|
+
return typeof value === "string" && COLLAB_CHILD_STATUSES.has(value) ? value : void 0;
|
|
1372
|
+
}
|
|
1373
|
+
function collabTurnEndStatus(turnStatus) {
|
|
1374
|
+
const state = toTurnStatus(turnStatus);
|
|
1375
|
+
return state === "completed" ? "idle" : state;
|
|
1376
|
+
}
|
|
1342
1377
|
function threadStateFromStatus(status) {
|
|
1343
1378
|
const type = isRecord3(status) ? asString(status["type"]) : asString(status);
|
|
1344
1379
|
if (type === "idle") return "idle";
|
|
@@ -1561,11 +1596,12 @@ function mapCollabAgentEvent(input) {
|
|
|
1561
1596
|
];
|
|
1562
1597
|
}
|
|
1563
1598
|
if (method === "collabAgent/completed" || method === "task.completed") {
|
|
1599
|
+
const status = collabTurnEndStatus(asString(input.params["turnStatus"]) ?? void 0);
|
|
1564
1600
|
return [
|
|
1565
1601
|
baseEvent({
|
|
1566
1602
|
type: "task.updated",
|
|
1567
1603
|
threadId,
|
|
1568
|
-
payload: { taskId: agentThreadId, status
|
|
1604
|
+
payload: { taskId: agentThreadId, status, ...linkage },
|
|
1569
1605
|
method,
|
|
1570
1606
|
providerInstanceId: input.providerInstanceId
|
|
1571
1607
|
})
|
|
@@ -1584,6 +1620,19 @@ function mapCollabAgentEvent(input) {
|
|
|
1584
1620
|
})
|
|
1585
1621
|
];
|
|
1586
1622
|
}
|
|
1623
|
+
if (method === "collabAgent/metadata") {
|
|
1624
|
+
const status = asCollabChildStatus(input.params["status"]);
|
|
1625
|
+
if (status === void 0) return [];
|
|
1626
|
+
return [
|
|
1627
|
+
baseEvent({
|
|
1628
|
+
type: "task.updated",
|
|
1629
|
+
threadId,
|
|
1630
|
+
payload: { taskId: agentThreadId, status, ...linkage },
|
|
1631
|
+
method,
|
|
1632
|
+
providerInstanceId: input.providerInstanceId
|
|
1633
|
+
})
|
|
1634
|
+
];
|
|
1635
|
+
}
|
|
1587
1636
|
if (method === "collabAgent/tokenUsage") {
|
|
1588
1637
|
const tokenUsage = isRecord3(input.params["tokenUsage"]) ? input.params["tokenUsage"] : void 0;
|
|
1589
1638
|
const total = tokenUsage && isRecord3(tokenUsage["total"]) ? tokenUsage["total"] : void 0;
|
|
@@ -2336,11 +2385,25 @@ function isRootChild(agentPath, agentThreadId, rootThreadId) {
|
|
|
2336
2385
|
if (agentThreadId === rootThreadId) return true;
|
|
2337
2386
|
return agentPath === "/root" || agentPath === "/";
|
|
2338
2387
|
}
|
|
2388
|
+
function readSubAgentActivity(method, params) {
|
|
2389
|
+
if (method !== "item/started" && method !== "item/completed") return void 0;
|
|
2390
|
+
if (itemTypeOf(params) !== "subAgentActivity") return void 0;
|
|
2391
|
+
const item = isRecord3(params) ? isRecord3(params["item"]) ? params["item"] : params : {};
|
|
2392
|
+
return {
|
|
2393
|
+
agentThreadId: asString(item["agentThreadId"]) ?? void 0,
|
|
2394
|
+
agentPath: asString(item["agentPath"]) ?? void 0
|
|
2395
|
+
};
|
|
2396
|
+
}
|
|
2339
2397
|
function pathLeaf2(value) {
|
|
2340
2398
|
if (!value) return void 0;
|
|
2341
2399
|
const parts = value.split("/").filter((part) => part.length > 0);
|
|
2342
2400
|
return parts.at(-1);
|
|
2343
2401
|
}
|
|
2402
|
+
function unconfirmedAnswerError(requestId, delivery) {
|
|
2403
|
+
return new Error(
|
|
2404
|
+
delivery === "closed" ? `could not confirm that codex received the answer to request ${requestId}: the session closed before the write was confirmed` : `could not confirm that codex received the answer to request ${requestId}: writing it to the CLI failed`
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2344
2407
|
var CodexSessionRuntime = class {
|
|
2345
2408
|
threadId;
|
|
2346
2409
|
cwd;
|
|
@@ -2379,6 +2442,15 @@ var CodexSessionRuntime = class {
|
|
|
2379
2442
|
codexNativeModeFor(this.runtimeMode, this.nativeModeId)
|
|
2380
2443
|
);
|
|
2381
2444
|
}
|
|
2445
|
+
/** 给 CLI 的应答写入失败:带上线程与方法名记一行 warn。 */
|
|
2446
|
+
#warnAnswerWriteFailed(method, jsonRpcId, error) {
|
|
2447
|
+
this.host.log.warn("writing an answer to codex failed", {
|
|
2448
|
+
threadId: this.threadId,
|
|
2449
|
+
method,
|
|
2450
|
+
jsonRpcId,
|
|
2451
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2382
2454
|
constructor(host, rpc, emit, input, cwd, appServerArgs, grants, declineRelay) {
|
|
2383
2455
|
this.host = host;
|
|
2384
2456
|
this.rpc = rpc;
|
|
@@ -2473,6 +2545,10 @@ var CodexSessionRuntime = class {
|
|
|
2473
2545
|
return;
|
|
2474
2546
|
}
|
|
2475
2547
|
}
|
|
2548
|
+
const activity = readSubAgentActivity(method, params);
|
|
2549
|
+
if (activity?.agentThreadId !== void 0 && !isRootChild(activity.agentPath, activity.agentThreadId, this.nativeThreadId ?? this.threadId)) {
|
|
2550
|
+
this.upsertCollabChild(activity.agentThreadId, { agentPath: activity.agentPath });
|
|
2551
|
+
}
|
|
2476
2552
|
this.dispatchMapped(method, params);
|
|
2477
2553
|
}
|
|
2478
2554
|
dispatchMapped(method, params) {
|
|
@@ -2513,23 +2589,19 @@ var CodexSessionRuntime = class {
|
|
|
2513
2589
|
}
|
|
2514
2590
|
}
|
|
2515
2591
|
interceptCollab(method, params, conversationId) {
|
|
2516
|
-
const
|
|
2592
|
+
const thread = isRecord3(params) && isRecord3(params["thread"]) ? params["thread"] : void 0;
|
|
2593
|
+
const source = thread === void 0 ? void 0 : thread["source"];
|
|
2517
2594
|
const subAgent = isRecord3(source) ? source["subAgent"] : void 0;
|
|
2518
2595
|
const spawn = isRecord3(subAgent) ? subAgent["thread_spawn"] : void 0;
|
|
2519
|
-
if (method === "thread/started" && isRecord3(spawn)) {
|
|
2596
|
+
if (method === "thread/started" && thread !== void 0 && isRecord3(spawn)) {
|
|
2520
2597
|
const agentPath = asString(spawn["agent_path"]) ?? void 0;
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
...asString(spawn["agent_nickname"]) ? { nickname: asString(spawn["agent_nickname"]) } : {},
|
|
2529
|
-
...spawnTurnId ? { spawnTurnId } : {}
|
|
2530
|
-
};
|
|
2531
|
-
this.collabChildren.set(conversationId, child2);
|
|
2532
|
-
this.emitCollab("collabAgent/started", child2);
|
|
2598
|
+
const knownPath = agentPath ?? this.collabChildren.get(conversationId)?.agentPath;
|
|
2599
|
+
if (isRootChild(knownPath, conversationId, this.nativeThreadId ?? this.threadId)) return;
|
|
2600
|
+
this.upsertCollabChild(conversationId, {
|
|
2601
|
+
agentPath,
|
|
2602
|
+
role: asString(spawn["agent_role"]) ?? asString(thread["agentRole"]) ?? void 0,
|
|
2603
|
+
nickname: asString(spawn["agent_nickname"]) ?? asString(thread["agentNickname"]) ?? void 0
|
|
2604
|
+
});
|
|
2533
2605
|
return;
|
|
2534
2606
|
}
|
|
2535
2607
|
const itemType = itemTypeOf(params);
|
|
@@ -2539,21 +2611,13 @@ var CodexSessionRuntime = class {
|
|
|
2539
2611
|
if (receiver && this.activeTurnId) this.collabReceiverTurns.set(receiver, this.activeTurnId);
|
|
2540
2612
|
return;
|
|
2541
2613
|
}
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
const agentThreadId =
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
if (!this.collabChildren.has(agentThreadId)) {
|
|
2548
|
-
const spawnTurnId = this.activeTurnId;
|
|
2549
|
-
const child2 = {
|
|
2550
|
-
agentThreadId,
|
|
2551
|
-
...agentPath ? { agentPath } : {},
|
|
2552
|
-
...spawnTurnId ? { spawnTurnId } : {}
|
|
2553
|
-
};
|
|
2554
|
-
this.collabChildren.set(agentThreadId, child2);
|
|
2555
|
-
this.emitCollab("collabAgent/started", child2);
|
|
2614
|
+
const activity = readSubAgentActivity(method, params);
|
|
2615
|
+
if (activity !== void 0) {
|
|
2616
|
+
const agentThreadId = activity.agentThreadId ?? conversationId;
|
|
2617
|
+
if (isRootChild(activity.agentPath, agentThreadId, this.nativeThreadId ?? this.threadId)) {
|
|
2618
|
+
return;
|
|
2556
2619
|
}
|
|
2620
|
+
this.upsertCollabChild(agentThreadId, { agentPath: activity.agentPath });
|
|
2557
2621
|
}
|
|
2558
2622
|
const child = this.collabChildren.get(conversationId);
|
|
2559
2623
|
if (method === "turn/started") {
|
|
@@ -2567,13 +2631,26 @@ var CodexSessionRuntime = class {
|
|
|
2567
2631
|
if (CHILD_CHATTER_METHODS.has(method) || !CHILD_AGENT_EVENT_METHODS.has(method)) return;
|
|
2568
2632
|
return;
|
|
2569
2633
|
}
|
|
2634
|
+
if (method === "turn/started") {
|
|
2635
|
+
child.status = "running";
|
|
2636
|
+
this.emitCollab("collabAgent/statusChanged", child, { status: "running" });
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2570
2639
|
if (method === "turn/completed") {
|
|
2571
|
-
|
|
2640
|
+
const turn = isRecord3(params) && isRecord3(params["turn"]) ? params["turn"] : void 0;
|
|
2641
|
+
const turnStatus = turn === void 0 ? void 0 : asString(turn["status"]) ?? void 0;
|
|
2642
|
+
child.status = collabTurnEndStatus(turnStatus);
|
|
2643
|
+
this.emitCollab(
|
|
2644
|
+
"collabAgent/completed",
|
|
2645
|
+
child,
|
|
2646
|
+
turnStatus === void 0 ? {} : { turnStatus }
|
|
2647
|
+
);
|
|
2572
2648
|
return;
|
|
2573
2649
|
}
|
|
2574
2650
|
if (method === "error") {
|
|
2575
2651
|
const willRetry = isRecord3(params) ? params["willRetry"] === true : false;
|
|
2576
2652
|
if (willRetry) return;
|
|
2653
|
+
child.status = "failed";
|
|
2577
2654
|
this.emitCollab("collabAgent/statusChanged", child, { status: "systemError" });
|
|
2578
2655
|
return;
|
|
2579
2656
|
}
|
|
@@ -2586,6 +2663,44 @@ var CodexSessionRuntime = class {
|
|
|
2586
2663
|
this.emitCollab("collabAgent/progress", child, params);
|
|
2587
2664
|
}
|
|
2588
2665
|
}
|
|
2666
|
+
/**
|
|
2667
|
+
* 两条登记路(根线程的 subAgentActivity、子线程的 thread/started)都走这里。
|
|
2668
|
+
* 第一次见到就登记并宣布;已登记的只合并身份:已有的字段保留,缺的补上,补到了就发
|
|
2669
|
+
* 一条带当前状态的元数据更新。不能再宣布一次:一轮结束之后才到的宣布,会让宿主把
|
|
2670
|
+
* idle 当成新一轮开始。
|
|
2671
|
+
*/
|
|
2672
|
+
upsertCollabChild(agentThreadId, identity) {
|
|
2673
|
+
const fill = (known, next) => known ?? (next !== void 0 && next.length > 0 ? next : void 0);
|
|
2674
|
+
const existing = this.collabChildren.get(agentThreadId);
|
|
2675
|
+
const agentPath = fill(existing?.agentPath, identity.agentPath);
|
|
2676
|
+
const role = fill(existing?.role, identity.role);
|
|
2677
|
+
const nickname = fill(existing?.nickname, identity.nickname);
|
|
2678
|
+
if (existing === void 0) {
|
|
2679
|
+
const spawnTurnId = this.activeTurnId;
|
|
2680
|
+
const child = {
|
|
2681
|
+
agentThreadId,
|
|
2682
|
+
...agentPath ? { agentPath } : {},
|
|
2683
|
+
...role ? { role } : {},
|
|
2684
|
+
...nickname ? { nickname } : {},
|
|
2685
|
+
...spawnTurnId ? { spawnTurnId } : {},
|
|
2686
|
+
status: "running"
|
|
2687
|
+
};
|
|
2688
|
+
this.collabChildren.set(agentThreadId, child);
|
|
2689
|
+
this.emitCollab("collabAgent/started", child);
|
|
2690
|
+
return;
|
|
2691
|
+
}
|
|
2692
|
+
if (agentPath === existing.agentPath && role === existing.role && nickname === existing.nickname) {
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
2695
|
+
const merged = {
|
|
2696
|
+
...existing,
|
|
2697
|
+
...agentPath ? { agentPath } : {},
|
|
2698
|
+
...role ? { role } : {},
|
|
2699
|
+
...nickname ? { nickname } : {}
|
|
2700
|
+
};
|
|
2701
|
+
this.collabChildren.set(agentThreadId, merged);
|
|
2702
|
+
this.emitCollab("collabAgent/metadata", merged, { status: merged.status });
|
|
2703
|
+
}
|
|
2589
2704
|
emitCollab(method, child, extra) {
|
|
2590
2705
|
const params = {
|
|
2591
2706
|
agentThreadId: child.agentThreadId,
|
|
@@ -2648,7 +2763,7 @@ var CodexSessionRuntime = class {
|
|
|
2648
2763
|
jsonRpcId: id,
|
|
2649
2764
|
settle: (result) => {
|
|
2650
2765
|
this.pendingUserInputs.delete(requestId);
|
|
2651
|
-
void this.rpc.respond(id, result).finally(resolve2);
|
|
2766
|
+
void this.rpc.respond(id, result).catch((error) => this.#warnAnswerWriteFailed(method, id, error)).finally(resolve2);
|
|
2652
2767
|
}
|
|
2653
2768
|
});
|
|
2654
2769
|
for (const event of events) this.emit(event);
|
|
@@ -2682,7 +2797,7 @@ var CodexSessionRuntime = class {
|
|
|
2682
2797
|
identity,
|
|
2683
2798
|
settle: (decision) => {
|
|
2684
2799
|
this.pendingApprovals.delete(requestId);
|
|
2685
|
-
void this.rpc.respond(id, decision).finally(resolve2);
|
|
2800
|
+
void this.rpc.respond(id, decision).catch((error) => this.#warnAnswerWriteFailed(method, id, error)).finally(resolve2);
|
|
2686
2801
|
}
|
|
2687
2802
|
});
|
|
2688
2803
|
for (const event of events) this.emit(event);
|
|
@@ -2704,7 +2819,7 @@ var CodexSessionRuntime = class {
|
|
|
2704
2819
|
}
|
|
2705
2820
|
const ack = this.registerWriteAck(pending.jsonRpcId);
|
|
2706
2821
|
pending.settle(wire);
|
|
2707
|
-
await ack.catch(() => "closed");
|
|
2822
|
+
const delivery = await ack.catch(() => "closed");
|
|
2708
2823
|
this.emit({
|
|
2709
2824
|
eventId: `codex-req-${requestId}`,
|
|
2710
2825
|
provider: CODEX_DRIVER_KIND,
|
|
@@ -2719,6 +2834,7 @@ var CodexSessionRuntime = class {
|
|
|
2719
2834
|
...reason ? { reason } : {}
|
|
2720
2835
|
}
|
|
2721
2836
|
});
|
|
2837
|
+
if (delivery !== "written") throw unconfirmedAnswerError(requestId, delivery);
|
|
2722
2838
|
}
|
|
2723
2839
|
async respondToUserInput(requestId, answers) {
|
|
2724
2840
|
const pending = this.pendingUserInputs.get(requestId);
|
|
@@ -2727,7 +2843,9 @@ var CodexSessionRuntime = class {
|
|
|
2727
2843
|
if (mapped === void 0) {
|
|
2728
2844
|
throw new Error(`invalid user input answers for request ${requestId}`);
|
|
2729
2845
|
}
|
|
2846
|
+
const ack = this.registerWriteAck(pending.jsonRpcId);
|
|
2730
2847
|
pending.settle({ answers: mapped });
|
|
2848
|
+
const delivery = await ack.catch(() => "closed");
|
|
2731
2849
|
this.emit({
|
|
2732
2850
|
eventId: `codex-ui-${requestId}`,
|
|
2733
2851
|
provider: CODEX_DRIVER_KIND,
|
|
@@ -2738,6 +2856,7 @@ var CodexSessionRuntime = class {
|
|
|
2738
2856
|
// 契约的 answers 是 questionId → 答案 的 record,不是数组。
|
|
2739
2857
|
payload: { answers: toCanonicalUserInputAnswers(mapped) }
|
|
2740
2858
|
});
|
|
2859
|
+
if (delivery !== "written") throw unconfirmedAnswerError(requestId, delivery);
|
|
2741
2860
|
}
|
|
2742
2861
|
async withActiveWriterRecovery(run, allowUnsubscribe) {
|
|
2743
2862
|
let lastError;
|
|
@@ -3539,15 +3658,18 @@ async function verifyCodexSignIn(input) {
|
|
|
3539
3658
|
onServerRequest: () => void 0,
|
|
3540
3659
|
onStderrLine: () => void 0
|
|
3541
3660
|
});
|
|
3661
|
+
let version = null;
|
|
3542
3662
|
try {
|
|
3543
|
-
|
|
3663
|
+
version = codexVersionFromInitialize(
|
|
3664
|
+
await rpc.request("initialize", CODEX_INITIALIZE_PARAMS, 15e3)
|
|
3665
|
+
);
|
|
3544
3666
|
await rpc.notify("initialized");
|
|
3545
3667
|
const account = await rpc.request("account/read", { refreshToken: true }, 15e3);
|
|
3546
3668
|
const type = isRecord3(account) ? asString(account["type"]) : null;
|
|
3547
3669
|
if (type !== "chatgpt") {
|
|
3548
3670
|
return {
|
|
3549
3671
|
installed: true,
|
|
3550
|
-
version
|
|
3672
|
+
version,
|
|
3551
3673
|
readiness: "unchecked",
|
|
3552
3674
|
auth: { status: "unauthenticated" },
|
|
3553
3675
|
...CODEX_NATIVE_MODE_REPORT
|
|
@@ -3556,7 +3678,7 @@ async function verifyCodexSignIn(input) {
|
|
|
3556
3678
|
const models = await listCodexModels(rpc);
|
|
3557
3679
|
return {
|
|
3558
3680
|
installed: true,
|
|
3559
|
-
version
|
|
3681
|
+
version,
|
|
3560
3682
|
readiness: "ready",
|
|
3561
3683
|
auth,
|
|
3562
3684
|
...models === void 0 ? {} : { models },
|
|
@@ -3565,7 +3687,7 @@ async function verifyCodexSignIn(input) {
|
|
|
3565
3687
|
} catch {
|
|
3566
3688
|
return {
|
|
3567
3689
|
installed: true,
|
|
3568
|
-
version
|
|
3690
|
+
version,
|
|
3569
3691
|
readiness: "unchecked",
|
|
3570
3692
|
auth: { status: "unknown" },
|
|
3571
3693
|
...CODEX_NATIVE_MODE_REPORT
|
|
@@ -4101,7 +4223,7 @@ var createCodexInstance = (config, host) => {
|
|
|
4101
4223
|
return booked;
|
|
4102
4224
|
};
|
|
4103
4225
|
const probeAuth = () => accountToAuth2(readCodexAccount(accountHomeFromLayout(layoutFor(recipe))));
|
|
4104
|
-
const
|
|
4226
|
+
const probeAppServer = async (input) => {
|
|
4105
4227
|
const layout = layoutFor(recipe);
|
|
4106
4228
|
const env = buildCodexSpawnEnv({
|
|
4107
4229
|
recipe,
|
|
@@ -4110,6 +4232,7 @@ var createCodexInstance = (config, host) => {
|
|
|
4110
4232
|
});
|
|
4111
4233
|
let handle;
|
|
4112
4234
|
let rpc;
|
|
4235
|
+
let version = null;
|
|
4113
4236
|
try {
|
|
4114
4237
|
handle = await host.process.spawn({
|
|
4115
4238
|
program: recipe.binaryPath,
|
|
@@ -4123,11 +4246,14 @@ var createCodexInstance = (config, host) => {
|
|
|
4123
4246
|
onServerRequest: () => void 0,
|
|
4124
4247
|
onStderrLine: () => void 0
|
|
4125
4248
|
});
|
|
4126
|
-
|
|
4249
|
+
version = codexVersionFromInitialize(
|
|
4250
|
+
await rpc.request("initialize", CODEX_INITIALIZE_PARAMS)
|
|
4251
|
+
);
|
|
4127
4252
|
await rpc.notify("initialized");
|
|
4128
|
-
return await listCodexModels(rpc);
|
|
4129
|
-
} catch {
|
|
4130
|
-
|
|
4253
|
+
return { version, models: input.listModels ? await listCodexModels(rpc) : void 0 };
|
|
4254
|
+
} catch (error) {
|
|
4255
|
+
if (error instanceof ExecutorSpawnRefusedError) throw error;
|
|
4256
|
+
return { version, models: void 0 };
|
|
4131
4257
|
} finally {
|
|
4132
4258
|
await rpc?.close().catch(() => void 0);
|
|
4133
4259
|
await handle?.kill("SIGTERM").catch(() => void 0);
|
|
@@ -4154,20 +4280,20 @@ var createCodexInstance = (config, host) => {
|
|
|
4154
4280
|
};
|
|
4155
4281
|
}
|
|
4156
4282
|
const connectionError = codexApiConnectionError(recipe, recipe.environment);
|
|
4283
|
+
const { version, models } = await probeAppServer({ listModels: connectionError === null });
|
|
4157
4284
|
if (connectionError) {
|
|
4158
4285
|
return {
|
|
4159
4286
|
installed: true,
|
|
4160
|
-
version
|
|
4287
|
+
version,
|
|
4161
4288
|
readiness: "error",
|
|
4162
4289
|
auth: probeAuth(),
|
|
4163
4290
|
detail: connectionError,
|
|
4164
4291
|
...CODEX_NATIVE_MODE_REPORT
|
|
4165
4292
|
};
|
|
4166
4293
|
}
|
|
4167
|
-
const models = await probeModels();
|
|
4168
4294
|
return {
|
|
4169
4295
|
installed: true,
|
|
4170
|
-
version
|
|
4296
|
+
version,
|
|
4171
4297
|
readiness: models === void 0 ? "unchecked" : "ready",
|
|
4172
4298
|
auth: probeAuth(),
|
|
4173
4299
|
...models === void 0 ? {} : { models },
|
|
@@ -4219,7 +4345,13 @@ var createCodexInstance = (config, host) => {
|
|
|
4219
4345
|
runtime?.handleNotification(notification.method, notification.params);
|
|
4220
4346
|
},
|
|
4221
4347
|
onServerRequest: (request) => {
|
|
4222
|
-
void runtime?.handleServerRequest(request.id, request.method, request.params)
|
|
4348
|
+
void runtime?.handleServerRequest(request.id, request.method, request.params).catch((error) => {
|
|
4349
|
+
host.log.warn("codex server request was not answered", {
|
|
4350
|
+
threadId: input.threadId,
|
|
4351
|
+
method: request.method,
|
|
4352
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4353
|
+
});
|
|
4354
|
+
});
|
|
4223
4355
|
},
|
|
4224
4356
|
onStderrLine: (line) => {
|
|
4225
4357
|
runtime?.handleStderrLine(line);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-codex",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2147",
|
|
4
4
|
"description": "Codex executor: Codex CLI over the app-server JSON-RPC protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@types/node": "24.12.4",
|
|
21
21
|
"esbuild": "0.28.1",
|
|
22
22
|
"vite-plus": "0.2.2",
|
|
23
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
23
|
+
"@ycodium-ai/plugin-api": "0.2.0"
|
|
24
24
|
},
|
|
25
25
|
"ycodium": {
|
|
26
26
|
"plugin": "./dist/index.js",
|