@ycodium-ai/agent-codex 0.2.2634 → 0.2.2664
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 +217 -31
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -424,7 +424,10 @@ var probeCodexAccount = (accountPath) => {
|
|
|
424
424
|
|
|
425
425
|
// src/codexInstance.ts
|
|
426
426
|
import * as NodeProcess from "node:process";
|
|
427
|
-
import {
|
|
427
|
+
import {
|
|
428
|
+
describeExecutorSpawnFailure,
|
|
429
|
+
ExecutorSpawnRefusedError
|
|
430
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
428
431
|
|
|
429
432
|
// src/config.ts
|
|
430
433
|
import { modelSelectionStringOption } from "@ycodium-ai/plugin-api/executor";
|
|
@@ -782,7 +785,8 @@ function codexCollaborationMode(input) {
|
|
|
782
785
|
mode: input.interactionMode === "plan" ? "plan" : "default",
|
|
783
786
|
settings: {
|
|
784
787
|
model: input.model,
|
|
785
|
-
...effort ? { reasoning_effort: effort } : {}
|
|
788
|
+
...effort ? { reasoning_effort: effort } : {},
|
|
789
|
+
...input.developerInstructions ? { developer_instructions: input.developerInstructions } : {}
|
|
786
790
|
}
|
|
787
791
|
};
|
|
788
792
|
}
|
|
@@ -868,6 +872,8 @@ var CHILD_AGENT_EVENT_METHODS = /* @__PURE__ */ new Set([
|
|
|
868
872
|
"turn/completed",
|
|
869
873
|
"thread/status/changed",
|
|
870
874
|
"thread/tokenUsage/updated",
|
|
875
|
+
"thread/settings/updated",
|
|
876
|
+
"model/rerouted",
|
|
871
877
|
"item/started",
|
|
872
878
|
"item/completed",
|
|
873
879
|
"thread/closed",
|
|
@@ -885,7 +891,6 @@ var CHILD_CHATTER_METHODS = /* @__PURE__ */ new Set([
|
|
|
885
891
|
"turn/plan/updated",
|
|
886
892
|
"turn/diff/updated",
|
|
887
893
|
"thread/name/updated",
|
|
888
|
-
"thread/settings/updated",
|
|
889
894
|
"rawResponseItem/completed",
|
|
890
895
|
// 子线程自己的生命周期通知不能改父线程状态(旧宿主 runtime 同名单)。
|
|
891
896
|
"thread/archived",
|
|
@@ -1672,9 +1677,13 @@ function mapCollabAgentEvent(input) {
|
|
|
1672
1677
|
const role = asString(input.params["agentRole"]) ?? asString(input.params["role"]) ?? pathLeaf(agentPath) ?? "general-purpose";
|
|
1673
1678
|
const knownName = nickname ?? pathLeaf(agentPath);
|
|
1674
1679
|
const title = knownName ?? agentThreadId;
|
|
1680
|
+
const model = trimText(input.params["model"]);
|
|
1681
|
+
const effort = trimText(input.params["effort"]);
|
|
1675
1682
|
const linkage = {
|
|
1676
1683
|
role,
|
|
1677
1684
|
...knownName ? { title: knownName } : {},
|
|
1685
|
+
...model ? { model } : {},
|
|
1686
|
+
...effort ? { effort } : {},
|
|
1678
1687
|
...agentPath ? { agentPath } : {},
|
|
1679
1688
|
timelineBypass: true,
|
|
1680
1689
|
rosterKind: "subagent"
|
|
@@ -1735,6 +1744,17 @@ function mapCollabAgentEvent(input) {
|
|
|
1735
1744
|
})
|
|
1736
1745
|
];
|
|
1737
1746
|
}
|
|
1747
|
+
if (method === "collabAgent/metadataUpdated") {
|
|
1748
|
+
return [
|
|
1749
|
+
baseEvent({
|
|
1750
|
+
type: "task.updated",
|
|
1751
|
+
threadId,
|
|
1752
|
+
payload: { taskId: agentThreadId, ...linkage },
|
|
1753
|
+
method,
|
|
1754
|
+
providerInstanceId: input.providerInstanceId
|
|
1755
|
+
})
|
|
1756
|
+
];
|
|
1757
|
+
}
|
|
1738
1758
|
if (method === "collabAgent/metadata") {
|
|
1739
1759
|
const status = asCollabChildStatus(input.params["status"]);
|
|
1740
1760
|
if (status === void 0) return [];
|
|
@@ -1810,6 +1830,42 @@ function describeFileChangeApproval(params) {
|
|
|
1810
1830
|
fileChanges: toApplyPatchFileChanges(record)
|
|
1811
1831
|
};
|
|
1812
1832
|
}
|
|
1833
|
+
function describePermissionsApproval(params) {
|
|
1834
|
+
const record = isRecord3(params) ? params : {};
|
|
1835
|
+
const permissions = isRecord3(record["permissions"]) ? record["permissions"] : {};
|
|
1836
|
+
const fileSystem = isRecord3(permissions["fileSystem"]) ? permissions["fileSystem"] : {};
|
|
1837
|
+
const network = isRecord3(permissions["network"]) ? permissions["network"] : {};
|
|
1838
|
+
const pathsOf = (value) => Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.length > 0 ? [entry] : []) : [];
|
|
1839
|
+
const read = pathsOf(fileSystem["read"]);
|
|
1840
|
+
const write = pathsOf(fileSystem["write"]);
|
|
1841
|
+
const entries = Array.isArray(fileSystem["entries"]) ? fileSystem["entries"] : [];
|
|
1842
|
+
for (const entry of entries) {
|
|
1843
|
+
if (!isRecord3(entry) || !isRecord3(entry["path"])) continue;
|
|
1844
|
+
const target = entry["path"];
|
|
1845
|
+
const path = target["type"] === "path" ? asString(target["path"]) : target["type"] === "glob_pattern" ? asString(target["pattern"]) : void 0;
|
|
1846
|
+
if (!path) continue;
|
|
1847
|
+
if (entry["access"] === "read") read.push(path);
|
|
1848
|
+
if (entry["access"] === "write") write.push(path);
|
|
1849
|
+
}
|
|
1850
|
+
const reason = trimText(record["reason"]);
|
|
1851
|
+
return {
|
|
1852
|
+
...reason ? { reason } : {},
|
|
1853
|
+
read: [...new Set(read)],
|
|
1854
|
+
write: [...new Set(write)],
|
|
1855
|
+
network: network["enabled"] === true
|
|
1856
|
+
};
|
|
1857
|
+
}
|
|
1858
|
+
function toPermissionsResponse(decision, params, persistent) {
|
|
1859
|
+
if (decision !== "allow") return { permissions: {} };
|
|
1860
|
+
const requested = isRecord3(params) && isRecord3(params["permissions"]) ? params["permissions"] : {};
|
|
1861
|
+
return {
|
|
1862
|
+
permissions: {
|
|
1863
|
+
...requested["fileSystem"] !== void 0 ? { fileSystem: requested["fileSystem"] } : {},
|
|
1864
|
+
...requested["network"] !== void 0 ? { network: requested["network"] } : {}
|
|
1865
|
+
},
|
|
1866
|
+
scope: persistent ? "session" : "turn"
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1813
1869
|
function describeMcpElicitation(params) {
|
|
1814
1870
|
const record = isRecord3(params) ? params : {};
|
|
1815
1871
|
const appName = asString(record["appName"]) ?? asString(record["serverName"]) ?? void 0;
|
|
@@ -2409,6 +2465,8 @@ function toRequestTypeFromKind(kind) {
|
|
|
2409
2465
|
return "apply_patch_approval";
|
|
2410
2466
|
case "mcp-elicitation":
|
|
2411
2467
|
return "mcp_elicitation_approval";
|
|
2468
|
+
// 契约没有单独的权限审批类型;宿主把 unknown 当 tool 类审批卡片渲染。
|
|
2469
|
+
case "permission":
|
|
2412
2470
|
default:
|
|
2413
2471
|
return "unknown";
|
|
2414
2472
|
}
|
|
@@ -2431,6 +2489,7 @@ function toRequestTypeFromMethod(method) {
|
|
|
2431
2489
|
return "tool_user_input";
|
|
2432
2490
|
case "item/tool/call":
|
|
2433
2491
|
return "dynamic_tool_call";
|
|
2492
|
+
case "item/permissions/requestApproval":
|
|
2434
2493
|
default:
|
|
2435
2494
|
return "unknown";
|
|
2436
2495
|
}
|
|
@@ -2475,6 +2534,17 @@ function mapServerRequestToEvents(input) {
|
|
|
2475
2534
|
if (appName) payload["appName"] = appName;
|
|
2476
2535
|
if (described.message) payload["detail"] = described.message;
|
|
2477
2536
|
payload["args"] = input.params;
|
|
2537
|
+
} else if (input.method === "item/permissions/requestApproval") {
|
|
2538
|
+
const described = describePermissionsApproval(input.params);
|
|
2539
|
+
const paths = [...described.read, ...described.write];
|
|
2540
|
+
const detail = described.reason ?? (paths.length > 0 ? paths.join(", ") : void 0);
|
|
2541
|
+
if (detail) payload["detail"] = detail;
|
|
2542
|
+
payload["args"] = {
|
|
2543
|
+
...described.reason ? { reason: described.reason } : {},
|
|
2544
|
+
...described.read.length > 0 ? { read: described.read.join(", ") } : {},
|
|
2545
|
+
...described.write.length > 0 ? { write: described.write.join(", ") } : {},
|
|
2546
|
+
...described.network ? { network: "true" } : {}
|
|
2547
|
+
};
|
|
2478
2548
|
} else if (input.method === "item/fileChange/requestApproval" || input.method.includes("applyPatch")) {
|
|
2479
2549
|
const described = describeFileChangeApproval(input.params);
|
|
2480
2550
|
if (described.detail) payload["detail"] = described.detail;
|
|
@@ -2508,7 +2578,13 @@ function mapServerRequestToEvents(input) {
|
|
|
2508
2578
|
}
|
|
2509
2579
|
|
|
2510
2580
|
// src/sessionRuntime.ts
|
|
2581
|
+
var COLLAB_META_LOOKUP_TIMEOUT_MS = 5e3;
|
|
2582
|
+
function metaValue(value) {
|
|
2583
|
+
const text = asString(value)?.trim();
|
|
2584
|
+
return text === void 0 || text.length === 0 ? void 0 : text;
|
|
2585
|
+
}
|
|
2511
2586
|
function cancelWireFor(pending) {
|
|
2587
|
+
if (pending.kind === "permission") return toPermissionsResponse("cancel", pending.params, false);
|
|
2512
2588
|
return pending.kind === "mcp-elicitation" ? toMcpElicitationResponse("cancel", pending.params) : { decision: "cancel" };
|
|
2513
2589
|
}
|
|
2514
2590
|
var sleep = (ms) => new Promise((resolve2) => {
|
|
@@ -2558,6 +2634,7 @@ var CodexSessionRuntime = class {
|
|
|
2558
2634
|
grants;
|
|
2559
2635
|
declineRelay;
|
|
2560
2636
|
collabChildren = /* @__PURE__ */ new Map();
|
|
2637
|
+
collabChildMeta = /* @__PURE__ */ new Map();
|
|
2561
2638
|
liveForeignTurns = /* @__PURE__ */ new Map();
|
|
2562
2639
|
collabReceiverTurns = /* @__PURE__ */ new Map();
|
|
2563
2640
|
memoryThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -2766,14 +2843,28 @@ var CodexSessionRuntime = class {
|
|
|
2766
2843
|
}
|
|
2767
2844
|
this.upsertCollabChild(agentThreadId, { agentPath: activity.agentPath });
|
|
2768
2845
|
}
|
|
2846
|
+
if (method === "thread/settings/updated" || method === "model/rerouted") {
|
|
2847
|
+
const settings = isRecord3(params) && isRecord3(params["threadSettings"]) ? params["threadSettings"] : {};
|
|
2848
|
+
const reroute = method === "model/rerouted";
|
|
2849
|
+
const model = metaValue(
|
|
2850
|
+
reroute ? isRecord3(params) ? params["toModel"] : void 0 : settings["model"]
|
|
2851
|
+
);
|
|
2852
|
+
const effort = reroute ? void 0 : metaValue(settings["effort"]);
|
|
2853
|
+
this.updateCollabChildMeta(conversationId, { model, effort }, true);
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2769
2856
|
const child = this.collabChildren.get(conversationId);
|
|
2770
2857
|
if (method === "turn/started") {
|
|
2858
|
+
this.reopenCollabChildMeta(conversationId);
|
|
2771
2859
|
const turnId = isRecord3(params) ? asString(params["turnId"]) ?? (isRecord3(params["turn"]) ? asString(params["turn"]["id"]) : null) : null;
|
|
2772
2860
|
if (turnId) this.liveForeignTurns.set(conversationId, turnId);
|
|
2773
2861
|
}
|
|
2774
2862
|
if (method === "turn/completed" || method === "thread/closed") {
|
|
2775
2863
|
this.liveForeignTurns.delete(conversationId);
|
|
2776
2864
|
}
|
|
2865
|
+
if (method === "thread/closed" && this.collabChildren.has(conversationId)) {
|
|
2866
|
+
this.metaOf(conversationId).closed = true;
|
|
2867
|
+
}
|
|
2777
2868
|
if (!child) {
|
|
2778
2869
|
if (CHILD_CHATTER_METHODS.has(method) || !CHILD_AGENT_EVENT_METHODS.has(method)) return;
|
|
2779
2870
|
return;
|
|
@@ -2834,6 +2925,7 @@ var CodexSessionRuntime = class {
|
|
|
2834
2925
|
};
|
|
2835
2926
|
this.collabChildren.set(agentThreadId, child);
|
|
2836
2927
|
this.emitCollab("collabAgent/started", child);
|
|
2928
|
+
this.startCollabChildMetaLookup(agentThreadId);
|
|
2837
2929
|
return;
|
|
2838
2930
|
}
|
|
2839
2931
|
if (agentPath === existing.agentPath && role === existing.role && nickname === existing.nickname) {
|
|
@@ -2848,12 +2940,64 @@ var CodexSessionRuntime = class {
|
|
|
2848
2940
|
this.collabChildren.set(agentThreadId, merged);
|
|
2849
2941
|
this.emitCollab("collabAgent/metadata", merged, { status: merged.status });
|
|
2850
2942
|
}
|
|
2943
|
+
metaOf(agentThreadId) {
|
|
2944
|
+
let meta = this.collabChildMeta.get(agentThreadId);
|
|
2945
|
+
if (meta === void 0) {
|
|
2946
|
+
meta = { lookupStarted: false, closed: false };
|
|
2947
|
+
this.collabChildMeta.set(agentThreadId, meta);
|
|
2948
|
+
}
|
|
2949
|
+
return meta;
|
|
2950
|
+
}
|
|
2951
|
+
reopenCollabChildMeta(agentThreadId) {
|
|
2952
|
+
const meta = this.collabChildMeta.get(agentThreadId);
|
|
2953
|
+
if (meta !== void 0) meta.closed = false;
|
|
2954
|
+
}
|
|
2955
|
+
/**
|
|
2956
|
+
* 合并子线程的型号与推理档;变了且子代理已登记就补发一条不带状态的更新。
|
|
2957
|
+
* 通知报的是当前值(overwrite),回读只补缺:回读的回包可能比通知晚到,不能盖掉更新的值。
|
|
2958
|
+
*/
|
|
2959
|
+
updateCollabChildMeta(agentThreadId, update, overwrite) {
|
|
2960
|
+
const meta = this.metaOf(agentThreadId);
|
|
2961
|
+
const model = update.model !== void 0 && (overwrite || !meta.model) ? update.model : meta.model;
|
|
2962
|
+
const effort = update.effort !== void 0 && (overwrite || !meta.effort) ? update.effort : meta.effort;
|
|
2963
|
+
if (model === meta.model && effort === meta.effort) return;
|
|
2964
|
+
if (model !== void 0) meta.model = model;
|
|
2965
|
+
if (effort !== void 0) meta.effort = effort;
|
|
2966
|
+
const child = this.collabChildren.get(agentThreadId);
|
|
2967
|
+
if (child !== void 0 && !meta.closed) this.emitCollab("collabAgent/metadataUpdated", child);
|
|
2968
|
+
}
|
|
2969
|
+
/**
|
|
2970
|
+
* 子线程已经在 CLI 里加载着:thread/resume 只是重新接上它,不开新一轮;
|
|
2971
|
+
* excludeTurns 避免把它的历史再读一遍。回包带当前的型号与推理档。
|
|
2972
|
+
*/
|
|
2973
|
+
startCollabChildMetaLookup(agentThreadId) {
|
|
2974
|
+
const meta = this.metaOf(agentThreadId);
|
|
2975
|
+
if (meta.lookupStarted || meta.closed) return;
|
|
2976
|
+
meta.lookupStarted = true;
|
|
2977
|
+
void this.rpc.request(
|
|
2978
|
+
"thread/resume",
|
|
2979
|
+
{ threadId: agentThreadId, excludeTurns: true },
|
|
2980
|
+
COLLAB_META_LOOKUP_TIMEOUT_MS
|
|
2981
|
+
).then((response) => {
|
|
2982
|
+
if (this.closed || meta.closed || !isRecord3(response)) return;
|
|
2983
|
+
const thread = response["thread"];
|
|
2984
|
+
if (!isRecord3(thread) || thread["id"] !== agentThreadId) return;
|
|
2985
|
+
this.updateCollabChildMeta(
|
|
2986
|
+
agentThreadId,
|
|
2987
|
+
{ model: metaValue(response["model"]), effort: metaValue(response["reasoningEffort"]) },
|
|
2988
|
+
false
|
|
2989
|
+
);
|
|
2990
|
+
}).catch(() => void 0);
|
|
2991
|
+
}
|
|
2851
2992
|
emitCollab(method, child, extra) {
|
|
2993
|
+
const meta = this.collabChildMeta.get(child.agentThreadId);
|
|
2852
2994
|
const params = {
|
|
2853
2995
|
agentThreadId: child.agentThreadId,
|
|
2854
2996
|
agentPath: child.agentPath,
|
|
2855
2997
|
agentRole: child.role ?? pathLeaf2(child.agentPath) ?? "general-purpose",
|
|
2856
2998
|
agentNickname: child.nickname,
|
|
2999
|
+
...meta?.model ? { model: meta.model } : {},
|
|
3000
|
+
...meta?.effort ? { effort: meta.effort } : {},
|
|
2857
3001
|
...isRecord3(extra) ? extra : {}
|
|
2858
3002
|
};
|
|
2859
3003
|
for (const event of mapNotificationToEvents({
|
|
@@ -2892,6 +3036,16 @@ var CodexSessionRuntime = class {
|
|
|
2892
3036
|
await this.handleApproval(id, method, params, "mcp-elicitation", described.identity);
|
|
2893
3037
|
return;
|
|
2894
3038
|
}
|
|
3039
|
+
if (method === "item/permissions/requestApproval") {
|
|
3040
|
+
await this.handleApproval(
|
|
3041
|
+
id,
|
|
3042
|
+
method,
|
|
3043
|
+
params,
|
|
3044
|
+
"permission",
|
|
3045
|
+
isRecord3(params) ? asString(params["itemId"]) ?? "permission" : "permission"
|
|
3046
|
+
);
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
2895
3049
|
if (method === "item/tool/requestUserInput") {
|
|
2896
3050
|
const requestId = this.requestIdFor(id);
|
|
2897
3051
|
const events = mapServerRequestToEvents({
|
|
@@ -2920,7 +3074,7 @@ var CodexSessionRuntime = class {
|
|
|
2920
3074
|
await this.rpc.respondError(id, -32601, `Method not found: ${method}`);
|
|
2921
3075
|
}
|
|
2922
3076
|
async handleApproval(id, method, params, kind, identity) {
|
|
2923
|
-
const grant = this.grants.lookup(codexApprovalGrantKey(kind, identity));
|
|
3077
|
+
const grant = kind === "permission" ? void 0 : this.grants.lookup(codexApprovalGrantKey(kind, identity));
|
|
2924
3078
|
if (grant) {
|
|
2925
3079
|
const decision = wireDecisionFromPersist(kind, grant);
|
|
2926
3080
|
await this.rpc.respond(id, { decision });
|
|
@@ -2962,7 +3116,9 @@ var CodexSessionRuntime = class {
|
|
|
2962
3116
|
if (decision === "allow" && pending.kind === "mcp-elicitation") {
|
|
2963
3117
|
wire = toMcpElicitationResponse("allow", pending.params);
|
|
2964
3118
|
}
|
|
2965
|
-
if (
|
|
3119
|
+
if (pending.kind === "permission") {
|
|
3120
|
+
wire = toPermissionsResponse(decision, pending.params, persist !== void 0);
|
|
3121
|
+
} else if (decision === "allow" && persist) {
|
|
2966
3122
|
this.grants.remember(codexApprovalGrantKey(pending.kind, pending.identity), persist);
|
|
2967
3123
|
if (pending.kind !== "mcp-elicitation") {
|
|
2968
3124
|
wire = { decision: wireDecisionFromPersist(pending.kind, persist) };
|
|
@@ -3095,10 +3251,13 @@ var CodexSessionRuntime = class {
|
|
|
3095
3251
|
});
|
|
3096
3252
|
return this.session;
|
|
3097
3253
|
}
|
|
3098
|
-
|
|
3099
|
-
|
|
3254
|
+
/** 宿主没给模式时沿用上一轮的模式;从没给过按 default。指令每轮都要带上。 */
|
|
3255
|
+
turnInteractionMode(input) {
|
|
3256
|
+
const mode = typeof input.interactionMode === "string" ? input.interactionMode : this.interactionMode ?? "default";
|
|
3100
3257
|
this.interactionMode = mode;
|
|
3101
|
-
|
|
3258
|
+
return mode;
|
|
3259
|
+
}
|
|
3260
|
+
developerInstructions(input, mode) {
|
|
3102
3261
|
const tools = hasConfiguredMcpServer(this.appServerArgs);
|
|
3103
3262
|
const model = this.model ?? DEFAULT_MODEL;
|
|
3104
3263
|
const effort = modelSelectionStringOption(input.modelSelection, "reasoningEffort") ?? DEFAULT_TEXT_GENERATION_REASONING_EFFORT;
|
|
@@ -3146,7 +3305,8 @@ var CodexSessionRuntime = class {
|
|
|
3146
3305
|
}
|
|
3147
3306
|
const sandboxPolicy = this.#turnSandboxPolicy();
|
|
3148
3307
|
const config = this.#threadConfig();
|
|
3149
|
-
const
|
|
3308
|
+
const interactionMode = this.turnInteractionMode(input);
|
|
3309
|
+
const developerInstructions = this.developerInstructions(input, interactionMode);
|
|
3150
3310
|
const requestedModel = modelIdFromSelection(input.modelSelection) ?? this.model;
|
|
3151
3311
|
const serviceTier = modelSelectionStringOption(input.modelSelection, "serviceTier");
|
|
3152
3312
|
const params = {
|
|
@@ -3157,16 +3317,14 @@ var CodexSessionRuntime = class {
|
|
|
3157
3317
|
sandboxPolicy,
|
|
3158
3318
|
...requestedModel ? { model: requestedModel } : {},
|
|
3159
3319
|
...serviceTier ? { serviceTier } : {},
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
const interactionMode = typeof input.interactionMode === "string" ? input.interactionMode : void 0;
|
|
3163
|
-
if (interactionMode !== void 0) {
|
|
3164
|
-
params["collaborationMode"] = codexCollaborationMode({
|
|
3320
|
+
// 指令只能走这里:turn 顶层的 developerInstructions 会被 CLI 静默丢掉(见 codexCollaborationMode)。
|
|
3321
|
+
collaborationMode: codexCollaborationMode({
|
|
3165
3322
|
interactionMode,
|
|
3166
3323
|
model: requestedModel ?? DEFAULT_MODEL,
|
|
3167
|
-
reasoningEffort: modelSelectionStringOption(input.modelSelection, "reasoningEffort") ?? void 0
|
|
3168
|
-
|
|
3169
|
-
|
|
3324
|
+
reasoningEffort: modelSelectionStringOption(input.modelSelection, "reasoningEffort") ?? void 0,
|
|
3325
|
+
developerInstructions
|
|
3326
|
+
})
|
|
3327
|
+
};
|
|
3170
3328
|
const isSteer = input.expectedTurnId !== void 0;
|
|
3171
3329
|
const result = await markProviderRejection(
|
|
3172
3330
|
() => isSteer ? this.rpc.request(
|
|
@@ -3265,9 +3423,10 @@ var CodexSessionRuntime = class {
|
|
|
3265
3423
|
}
|
|
3266
3424
|
return { threadId: this.threadId, turns: this.turns };
|
|
3267
3425
|
}
|
|
3268
|
-
|
|
3426
|
+
/** 会话收口时把还挂着的审批答成「取消」:应答形状按审批种类,权限审批不认 decision。 */
|
|
3427
|
+
settlePendingApprovals() {
|
|
3269
3428
|
for (const [requestId, pending] of this.pendingApprovals) {
|
|
3270
|
-
pending.settle(
|
|
3429
|
+
pending.settle(cancelWireFor(pending));
|
|
3271
3430
|
this.pendingApprovals.delete(requestId);
|
|
3272
3431
|
}
|
|
3273
3432
|
}
|
|
@@ -3282,7 +3441,7 @@ var CodexSessionRuntime = class {
|
|
|
3282
3441
|
this.closed = true;
|
|
3283
3442
|
this.requestKinds.clear();
|
|
3284
3443
|
this.failPendingNativeWrites("session closed before write confirmation");
|
|
3285
|
-
this.settlePendingApprovals(
|
|
3444
|
+
this.settlePendingApprovals();
|
|
3286
3445
|
this.settlePendingUserInputs({});
|
|
3287
3446
|
this.declineRelay.clear(this.threadId);
|
|
3288
3447
|
this.grants.clear();
|
|
@@ -3871,7 +4030,7 @@ async function verifyCodexSignIn(input) {
|
|
|
3871
4030
|
return {
|
|
3872
4031
|
installed: false,
|
|
3873
4032
|
version: null,
|
|
3874
|
-
readiness: "
|
|
4033
|
+
readiness: "not-installed",
|
|
3875
4034
|
auth: { status: "unknown" },
|
|
3876
4035
|
detail: "Codex program path is not configured"
|
|
3877
4036
|
};
|
|
@@ -4381,6 +4540,10 @@ ${extra}` : ""}`;
|
|
|
4381
4540
|
}
|
|
4382
4541
|
|
|
4383
4542
|
// src/codexInstance.ts
|
|
4543
|
+
function missingBinaryDetail(binaryPath) {
|
|
4544
|
+
const relyOnPath = !/[\\/]/.test(binaryPath);
|
|
4545
|
+
return `Could not start Codex (${binaryPath}). Check the "Program path" setting of this provider on this machine.` + (relyOnPath ? " The Codex desktop app may not add codex to PATH; enter the full path to the codex executable there." : " Make sure the configured file exists and can be run.");
|
|
4546
|
+
}
|
|
4384
4547
|
var yieldTick = () => new Promise((resolve2) => {
|
|
4385
4548
|
setImmediate(resolve2);
|
|
4386
4549
|
});
|
|
@@ -4462,12 +4625,26 @@ var createCodexInstance = (config, host, attachments) => {
|
|
|
4462
4625
|
let rpc;
|
|
4463
4626
|
let version = null;
|
|
4464
4627
|
try {
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4628
|
+
try {
|
|
4629
|
+
handle = await host.process.spawn({
|
|
4630
|
+
program: recipe.binaryPath,
|
|
4631
|
+
args: [...codexSpawnArgs(recipe, layout)],
|
|
4632
|
+
owner: { bindingId: host.bindingId },
|
|
4633
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
4634
|
+
});
|
|
4635
|
+
} catch (error) {
|
|
4636
|
+
if (error instanceof ExecutorSpawnRefusedError) throw error;
|
|
4637
|
+
host.log.warn("codex binary could not be started", {
|
|
4638
|
+
program: recipe.binaryPath,
|
|
4639
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4640
|
+
});
|
|
4641
|
+
return {
|
|
4642
|
+
version: null,
|
|
4643
|
+
models: void 0,
|
|
4644
|
+
skills: void 0,
|
|
4645
|
+
spawnFailed: describeExecutorSpawnFailure(error)
|
|
4646
|
+
};
|
|
4647
|
+
}
|
|
4471
4648
|
trackHandle(handle, `${recipe.binaryPath} (probe)`);
|
|
4472
4649
|
rpc = await createCodexRpcClient(handle, {
|
|
4473
4650
|
onNotification: () => void 0,
|
|
@@ -4479,10 +4656,10 @@ var createCodexInstance = (config, host, attachments) => {
|
|
|
4479
4656
|
);
|
|
4480
4657
|
await rpc.notify("initialized");
|
|
4481
4658
|
const models = input.listModels ? await listCodexModels(rpc) : void 0;
|
|
4482
|
-
return { version, models, skills: await listCodexSkills(rpc) };
|
|
4659
|
+
return { version, models, skills: await listCodexSkills(rpc), spawnFailed: null };
|
|
4483
4660
|
} catch (error) {
|
|
4484
4661
|
if (error instanceof ExecutorSpawnRefusedError) throw error;
|
|
4485
|
-
return { version, models: void 0, skills: void 0 };
|
|
4662
|
+
return { version, models: void 0, skills: void 0, spawnFailed: null };
|
|
4486
4663
|
} finally {
|
|
4487
4664
|
await rpc?.close().catch(() => void 0);
|
|
4488
4665
|
await handle?.kill("SIGTERM").catch(() => void 0);
|
|
@@ -4503,15 +4680,24 @@ var createCodexInstance = (config, host, attachments) => {
|
|
|
4503
4680
|
return {
|
|
4504
4681
|
installed: false,
|
|
4505
4682
|
version: null,
|
|
4506
|
-
readiness: "
|
|
4683
|
+
readiness: "not-installed",
|
|
4507
4684
|
auth: { status: "unknown" },
|
|
4508
4685
|
detail: "Codex program path is not configured"
|
|
4509
4686
|
};
|
|
4510
4687
|
}
|
|
4511
4688
|
const connectionError = codexApiConnectionError(recipe, recipe.environment);
|
|
4512
|
-
const { version, models, skills } = await probeAppServer({
|
|
4689
|
+
const { version, models, skills, spawnFailed } = await probeAppServer({
|
|
4513
4690
|
listModels: connectionError === null
|
|
4514
4691
|
});
|
|
4692
|
+
if (spawnFailed !== null) {
|
|
4693
|
+
return {
|
|
4694
|
+
installed: false,
|
|
4695
|
+
version: null,
|
|
4696
|
+
readiness: spawnFailed.readiness,
|
|
4697
|
+
auth: { status: "unknown" },
|
|
4698
|
+
detail: spawnFailed.readiness === "not-installed" ? missingBinaryDetail(recipe.binaryPath) : spawnFailed.detail
|
|
4699
|
+
};
|
|
4700
|
+
}
|
|
4515
4701
|
if (connectionError) {
|
|
4516
4702
|
return {
|
|
4517
4703
|
installed: true,
|
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.2664",
|
|
4
4
|
"description": "Codex executor: Codex CLI over the app-server JSON-RPC protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"tailwindcss": "^4.0.0",
|
|
30
30
|
"typescript": "~6.0.3",
|
|
31
31
|
"vite-plus": "0.2.2",
|
|
32
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
32
|
+
"@ycodium-ai/plugin-api": "0.2.2664",
|
|
33
33
|
"ycodium-executor-testing": "0.0.0"
|
|
34
34
|
},
|
|
35
35
|
"ycodium": {
|