@ycodium-ai/agent-codex 0.2.3102 → 0.2.3112
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 +215 -98
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -678,7 +678,7 @@ async function spawnCodexAppServer(input) {
|
|
|
678
678
|
}
|
|
679
679
|
|
|
680
680
|
// src/failureCategory.ts
|
|
681
|
-
var codexProcessExitCategory = (session) => session !== void 0 && !session.
|
|
681
|
+
var codexProcessExitCategory = (session) => session !== void 0 && !session.stopRequested && typeof session.nativeThreadId === "string" && session.nativeThreadId.length > 0 ? "transport" : void 0;
|
|
682
682
|
|
|
683
683
|
// src/protocol.ts
|
|
684
684
|
var CODEX_INITIALIZE_PARAMS = {
|
|
@@ -996,7 +996,7 @@ async function createCodexRpcClient(handle, handlers) {
|
|
|
996
996
|
let stderrTail = "";
|
|
997
997
|
let exitReason = null;
|
|
998
998
|
let exitFailureCategory;
|
|
999
|
-
let
|
|
999
|
+
let closeTask;
|
|
1000
1000
|
const attach = (error) => exitFailureCategory === void 0 ? error : Object.assign(error, { failureCategory: exitFailureCategory });
|
|
1001
1001
|
const failAll = (reason, failureCategory) => {
|
|
1002
1002
|
if (exitReason === null) exitFailureCategory = failureCategory;
|
|
@@ -1132,19 +1132,39 @@ async function createCodexRpcClient(handle, handlers) {
|
|
|
1132
1132
|
const respondError = async (id, code, message) => {
|
|
1133
1133
|
await writeLine({ id, error: { code, message } }, id);
|
|
1134
1134
|
};
|
|
1135
|
-
const close =
|
|
1136
|
-
if (
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1135
|
+
const close = (options) => {
|
|
1136
|
+
if (closeTask) return closeTask;
|
|
1137
|
+
closeTask = Promise.resolve().then(async () => {
|
|
1138
|
+
try {
|
|
1139
|
+
await handle.closeStdin();
|
|
1140
|
+
} catch {
|
|
1141
|
+
}
|
|
1142
|
+
try {
|
|
1143
|
+
await handle.kill("SIGTERM");
|
|
1144
|
+
} finally {
|
|
1145
|
+
failAll("the client was closed");
|
|
1146
|
+
}
|
|
1147
|
+
const drained = Promise.all([pumpStdout, pumpStderr]);
|
|
1148
|
+
if (options === void 0) {
|
|
1149
|
+
await drained;
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
let timer;
|
|
1153
|
+
try {
|
|
1154
|
+
await Promise.race([
|
|
1155
|
+
drained,
|
|
1156
|
+
new Promise((resolve2) => {
|
|
1157
|
+
timer = setTimeout(() => {
|
|
1158
|
+
options.onDrainTimeout();
|
|
1159
|
+
resolve2();
|
|
1160
|
+
}, options.drainTimeoutMs);
|
|
1161
|
+
})
|
|
1162
|
+
]);
|
|
1163
|
+
} finally {
|
|
1164
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
return closeTask;
|
|
1148
1168
|
};
|
|
1149
1169
|
return {
|
|
1150
1170
|
request,
|
|
@@ -3064,6 +3084,60 @@ function openCommandsOf(booked) {
|
|
|
3064
3084
|
};
|
|
3065
3085
|
}
|
|
3066
3086
|
|
|
3087
|
+
// src/sessionLifecycle.ts
|
|
3088
|
+
import { isExecutorLifecycleEvent } from "@ycodium-ai/plugin-api/executor";
|
|
3089
|
+
var CodexSessionLifecycle = class {
|
|
3090
|
+
closing = false;
|
|
3091
|
+
closed = false;
|
|
3092
|
+
#stopped = false;
|
|
3093
|
+
#task;
|
|
3094
|
+
#exit;
|
|
3095
|
+
threadId;
|
|
3096
|
+
publish;
|
|
3097
|
+
requestClose;
|
|
3098
|
+
constructor(threadId, publish, requestClose) {
|
|
3099
|
+
this.threadId = threadId;
|
|
3100
|
+
this.publish = publish;
|
|
3101
|
+
this.requestClose = requestClose;
|
|
3102
|
+
}
|
|
3103
|
+
/** 宿主发起的停止(stopSession / dispose)已认领;进程自己退出或协议关闭不算。 */
|
|
3104
|
+
get stopRequested() {
|
|
3105
|
+
return this.#stopped;
|
|
3106
|
+
}
|
|
3107
|
+
get acceptsLifecycle() {
|
|
3108
|
+
return !this.closed && !this.#stopped;
|
|
3109
|
+
}
|
|
3110
|
+
stop() {
|
|
3111
|
+
this.#stopped = true;
|
|
3112
|
+
}
|
|
3113
|
+
emit(event) {
|
|
3114
|
+
if (isExecutorLifecycleEvent(event) && !this.acceptsLifecycle) return;
|
|
3115
|
+
if (event.type === "session.exited") {
|
|
3116
|
+
this.#exit ??= event;
|
|
3117
|
+
this.requestClose();
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
this.publish(event);
|
|
3121
|
+
}
|
|
3122
|
+
/** 停止边界必须同步认领;RPC 的 dispatch 同步发布,认领前的终态已经交给事件流。 */
|
|
3123
|
+
close(reason, cleanup) {
|
|
3124
|
+
if (reason === "stop") this.stop();
|
|
3125
|
+
if (this.#task) return this.#task;
|
|
3126
|
+
this.closing = true;
|
|
3127
|
+
this.#task = (async () => {
|
|
3128
|
+
try {
|
|
3129
|
+
await cleanup();
|
|
3130
|
+
} finally {
|
|
3131
|
+
this.closed = true;
|
|
3132
|
+
}
|
|
3133
|
+
this.publish(
|
|
3134
|
+
this.#exit ?? baseEvent({ type: "session.exited", threadId: this.threadId, payload: {} })
|
|
3135
|
+
);
|
|
3136
|
+
})();
|
|
3137
|
+
return this.#task;
|
|
3138
|
+
}
|
|
3139
|
+
};
|
|
3140
|
+
|
|
3067
3141
|
// src/sessionCollab.ts
|
|
3068
3142
|
var COLLAB_META_LOOKUP_TIMEOUT_MS = 5e3;
|
|
3069
3143
|
function metaValue(value) {
|
|
@@ -3530,8 +3604,18 @@ var CodexSessionRuntime = class {
|
|
|
3530
3604
|
/** 宿主解好的这一轮的档(座位画的就是它)。缺席 = 宿主没给,按 `runtimeMode` 查表。 */
|
|
3531
3605
|
nativeModeId;
|
|
3532
3606
|
interactionMode;
|
|
3533
|
-
closed
|
|
3534
|
-
|
|
3607
|
+
get closed() {
|
|
3608
|
+
return this.#lifecycle.closed;
|
|
3609
|
+
}
|
|
3610
|
+
get closing() {
|
|
3611
|
+
return this.#lifecycle.closing;
|
|
3612
|
+
}
|
|
3613
|
+
get stopRequested() {
|
|
3614
|
+
return this.#lifecycle.stopRequested;
|
|
3615
|
+
}
|
|
3616
|
+
markStopped() {
|
|
3617
|
+
this.#lifecycle.stop();
|
|
3618
|
+
}
|
|
3535
3619
|
turns = [];
|
|
3536
3620
|
pendingApprovals = /* @__PURE__ */ new Map();
|
|
3537
3621
|
pendingUserInputs = /* @__PURE__ */ new Map();
|
|
@@ -3553,6 +3637,8 @@ var CodexSessionRuntime = class {
|
|
|
3553
3637
|
attachments;
|
|
3554
3638
|
rpc;
|
|
3555
3639
|
emit;
|
|
3640
|
+
#lifecycle;
|
|
3641
|
+
closeOptions;
|
|
3556
3642
|
#collab = new CodexSessionCollab(this);
|
|
3557
3643
|
#requests = new CodexSessionRequests(this);
|
|
3558
3644
|
/**
|
|
@@ -3574,11 +3660,20 @@ var CodexSessionRuntime = class {
|
|
|
3574
3660
|
codexNativeModeFor(this.runtimeMode, this.nativeModeId)
|
|
3575
3661
|
);
|
|
3576
3662
|
}
|
|
3577
|
-
constructor(host, rpc, emit, input, cwd, appServerArgs, grants, declineRelay, attachments) {
|
|
3663
|
+
constructor(host, rpc, emit, input, cwd, appServerArgs, grants, declineRelay, attachments, closeOptions = {}) {
|
|
3578
3664
|
this.attachments = attachments;
|
|
3665
|
+
this.closeOptions = closeOptions;
|
|
3579
3666
|
this.host = host;
|
|
3580
3667
|
this.rpc = rpc;
|
|
3581
|
-
this.emit
|
|
3668
|
+
this.#lifecycle = new CodexSessionLifecycle(input.threadId, emit, () => {
|
|
3669
|
+
void (closeOptions.requestClose?.() ?? this.close("process")).catch((error) => {
|
|
3670
|
+
host.log.warn("closing codex session failed", {
|
|
3671
|
+
threadId: input.threadId,
|
|
3672
|
+
error: String(error)
|
|
3673
|
+
});
|
|
3674
|
+
});
|
|
3675
|
+
});
|
|
3676
|
+
this.emit = (event) => this.#lifecycle.emit(event);
|
|
3582
3677
|
this.threadId = input.threadId;
|
|
3583
3678
|
this.cwd = cwd;
|
|
3584
3679
|
this.runtimeMode = input.runtimeMode;
|
|
@@ -3602,6 +3697,7 @@ var CodexSessionRuntime = class {
|
|
|
3602
3697
|
};
|
|
3603
3698
|
}
|
|
3604
3699
|
registerWriteAck(jsonRpcId) {
|
|
3700
|
+
if (this.closing) return Promise.resolve("closed");
|
|
3605
3701
|
return new Promise((resolve2) => {
|
|
3606
3702
|
this.writeAcks.set(jsonRpcId, { resolve: resolve2 });
|
|
3607
3703
|
});
|
|
@@ -3711,17 +3807,18 @@ var CodexSessionRuntime = class {
|
|
|
3711
3807
|
})) {
|
|
3712
3808
|
this.emit(event);
|
|
3713
3809
|
}
|
|
3714
|
-
if (method === "turn/started") {
|
|
3810
|
+
if (method === "turn/started" && this.#lifecycle.acceptsLifecycle) {
|
|
3715
3811
|
const turnId = turnIdOf(params);
|
|
3716
3812
|
if (turnId) this.activeTurnId = turnId;
|
|
3717
3813
|
}
|
|
3718
|
-
if (method === "turn/completed") {
|
|
3814
|
+
if (method === "turn/completed" && this.#lifecycle.acceptsLifecycle) {
|
|
3719
3815
|
this.activeTurnId = void 0;
|
|
3720
3816
|
const { activeTurnId: _completedTurn, ...idleSession } = this.session;
|
|
3721
3817
|
this.session = { ...idleSession, status: "idle", updatedAt: nowIso() };
|
|
3722
3818
|
}
|
|
3723
3819
|
}
|
|
3724
3820
|
async handleServerRequest(id, method, params) {
|
|
3821
|
+
if (this.closing) return;
|
|
3725
3822
|
return this.#requests.handleServerRequest(id, method, params);
|
|
3726
3823
|
}
|
|
3727
3824
|
async respondToRequest(requestId, decision, reason, persist) {
|
|
@@ -3733,6 +3830,7 @@ var CodexSessionRuntime = class {
|
|
|
3733
3830
|
async withActiveWriterRecovery(run, allowUnsubscribe) {
|
|
3734
3831
|
let lastError;
|
|
3735
3832
|
for (let attempt = 0; attempt < ACTIVE_WRITER_ATTEMPTS; attempt += 1) {
|
|
3833
|
+
if (this.closing) throw new Error("codex session is closing");
|
|
3736
3834
|
try {
|
|
3737
3835
|
return await run();
|
|
3738
3836
|
} catch (error) {
|
|
@@ -3840,6 +3938,7 @@ var CodexSessionRuntime = class {
|
|
|
3840
3938
|
return items;
|
|
3841
3939
|
}
|
|
3842
3940
|
async sendTurn(input) {
|
|
3941
|
+
if (this.closing) throw new Error("codex session is closing");
|
|
3843
3942
|
if (!this.nativeThreadId) throw new Error("codex session has no native thread");
|
|
3844
3943
|
if (this.hasConfiguredMcpServer) {
|
|
3845
3944
|
await this.rpc.request("config/mcpServer/reload", void 0, 0).catch((error) => {
|
|
@@ -3872,6 +3971,7 @@ var CodexSessionRuntime = class {
|
|
|
3872
3971
|
})
|
|
3873
3972
|
};
|
|
3874
3973
|
const isSteer = input.expectedTurnId !== void 0;
|
|
3974
|
+
if (this.closing) throw new Error("codex session is closing");
|
|
3875
3975
|
const result = await markProviderRejection(
|
|
3876
3976
|
() => isSteer ? this.rpc.request(
|
|
3877
3977
|
"turn/steer",
|
|
@@ -3961,31 +4061,59 @@ var CodexSessionRuntime = class {
|
|
|
3961
4061
|
settlePendingUserInputs(result) {
|
|
3962
4062
|
return this.#requests.settlePendingUserInputs(result);
|
|
3963
4063
|
}
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
eventId: nextEventId(),
|
|
3980
|
-
provider: CODEX_DRIVER_KIND,
|
|
3981
|
-
threadId: this.threadId,
|
|
3982
|
-
createdAt: nowIso(),
|
|
3983
|
-
type: "session.exited",
|
|
3984
|
-
payload: {}
|
|
4064
|
+
close(reason = "stop") {
|
|
4065
|
+
return this.#lifecycle.close(reason, async () => {
|
|
4066
|
+
this.requestKinds.clear();
|
|
4067
|
+
this.failPendingNativeWrites("session closed before write confirmation");
|
|
4068
|
+
this.settlePendingApprovals();
|
|
4069
|
+
this.settlePendingUserInputs({});
|
|
4070
|
+
this.declineRelay.clear(this.threadId);
|
|
4071
|
+
this.grants.clear();
|
|
4072
|
+
await this.rpc.close({
|
|
4073
|
+
drainTimeoutMs: this.closeOptions.drainTimeoutMs ?? 2e3,
|
|
4074
|
+
onDrainTimeout: () => {
|
|
4075
|
+
this.#lifecycle.closed = true;
|
|
4076
|
+
this.host.log.warn("codex output drain timed out", { threadId: this.threadId });
|
|
4077
|
+
}
|
|
4078
|
+
});
|
|
3985
4079
|
});
|
|
3986
4080
|
}
|
|
3987
4081
|
};
|
|
3988
4082
|
|
|
4083
|
+
// src/eventBus.ts
|
|
4084
|
+
var EventBus = class {
|
|
4085
|
+
#queued = [];
|
|
4086
|
+
#waiters = [];
|
|
4087
|
+
#closed = false;
|
|
4088
|
+
push(event) {
|
|
4089
|
+
const waiter = this.#waiters.shift();
|
|
4090
|
+
if (waiter) {
|
|
4091
|
+
waiter({ done: false, value: event });
|
|
4092
|
+
return;
|
|
4093
|
+
}
|
|
4094
|
+
this.#queued.push(event);
|
|
4095
|
+
}
|
|
4096
|
+
close() {
|
|
4097
|
+
if (this.#closed) return;
|
|
4098
|
+
this.#closed = true;
|
|
4099
|
+
while (this.#waiters.length > 0) {
|
|
4100
|
+
this.#waiters.shift()?.({ done: true, value: void 0 });
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
[Symbol.asyncIterator]() {
|
|
4104
|
+
return {
|
|
4105
|
+
next: () => {
|
|
4106
|
+
const queued = this.#queued.shift();
|
|
4107
|
+
if (queued !== void 0) return Promise.resolve({ done: false, value: queued });
|
|
4108
|
+
if (this.#closed) return Promise.resolve({ done: true, value: void 0 });
|
|
4109
|
+
return new Promise((resolve2) => {
|
|
4110
|
+
this.#waiters.push(resolve2);
|
|
4111
|
+
});
|
|
4112
|
+
}
|
|
4113
|
+
};
|
|
4114
|
+
}
|
|
4115
|
+
};
|
|
4116
|
+
|
|
3989
4117
|
// src/sessions.ts
|
|
3990
4118
|
import * as NodeFS3 from "node:fs";
|
|
3991
4119
|
import * as NodePath4 from "node:path";
|
|
@@ -5714,38 +5842,6 @@ function missingBinaryDetail(binaryPath) {
|
|
|
5714
5842
|
var yieldTick = () => new Promise((resolve2) => {
|
|
5715
5843
|
setImmediate(resolve2);
|
|
5716
5844
|
});
|
|
5717
|
-
var EventBus = class {
|
|
5718
|
-
#queued = [];
|
|
5719
|
-
#waiters = [];
|
|
5720
|
-
#closed = false;
|
|
5721
|
-
push(event) {
|
|
5722
|
-
const waiter = this.#waiters.shift();
|
|
5723
|
-
if (waiter) {
|
|
5724
|
-
waiter({ done: false, value: event });
|
|
5725
|
-
return;
|
|
5726
|
-
}
|
|
5727
|
-
this.#queued.push(event);
|
|
5728
|
-
}
|
|
5729
|
-
close() {
|
|
5730
|
-
if (this.#closed) return;
|
|
5731
|
-
this.#closed = true;
|
|
5732
|
-
while (this.#waiters.length > 0) {
|
|
5733
|
-
this.#waiters.shift()?.({ done: true, value: void 0 });
|
|
5734
|
-
}
|
|
5735
|
-
}
|
|
5736
|
-
[Symbol.asyncIterator]() {
|
|
5737
|
-
return {
|
|
5738
|
-
next: () => {
|
|
5739
|
-
const queued = this.#queued.shift();
|
|
5740
|
-
if (queued !== void 0) return Promise.resolve({ done: false, value: queued });
|
|
5741
|
-
if (this.#closed) return Promise.resolve({ done: true, value: void 0 });
|
|
5742
|
-
return new Promise((resolve2) => {
|
|
5743
|
-
this.#waiters.push(resolve2);
|
|
5744
|
-
});
|
|
5745
|
-
}
|
|
5746
|
-
};
|
|
5747
|
-
}
|
|
5748
|
-
};
|
|
5749
5845
|
function accountToAuth2(account) {
|
|
5750
5846
|
switch (account.state) {
|
|
5751
5847
|
case "signed-in":
|
|
@@ -5775,9 +5871,11 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5775
5871
|
const signInOperations = /* @__PURE__ */ new Map();
|
|
5776
5872
|
const live = /* @__PURE__ */ new Map();
|
|
5777
5873
|
let disposed = false;
|
|
5874
|
+
let disposeTask;
|
|
5778
5875
|
const requireThread = (threadId) => {
|
|
5779
5876
|
const booked = threads.get(threadId);
|
|
5780
5877
|
if (!booked) throw new Error(`unknown thread ${threadId}`);
|
|
5878
|
+
if (booked.closing) throw new Error(`thread ${threadId} is closing`);
|
|
5781
5879
|
return booked;
|
|
5782
5880
|
};
|
|
5783
5881
|
const probeAuth = () => accountToAuth2(readCodexAccount(accountHomeFromLayout(layoutFor(recipe))));
|
|
@@ -5831,7 +5929,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5831
5929
|
({ handle } = await spawnCodexAppServer({ host, recipe, layout }));
|
|
5832
5930
|
} catch (error) {
|
|
5833
5931
|
if (error instanceof ExecutorSpawnRefusedError) {
|
|
5834
|
-
const borrowed = [...threads.values()]
|
|
5932
|
+
const borrowed = [...threads.values()].find((entry) => !entry.closing);
|
|
5835
5933
|
if (borrowed !== void 0) return await run(borrowed.rpc);
|
|
5836
5934
|
}
|
|
5837
5935
|
throw error;
|
|
@@ -5868,8 +5966,12 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5868
5966
|
live.set(handle.pid, { command, ...threadId === void 0 ? {} : { threadId } });
|
|
5869
5967
|
void handle.exited.finally(() => live.delete(handle.pid));
|
|
5870
5968
|
};
|
|
5871
|
-
const stopBooked =
|
|
5872
|
-
|
|
5969
|
+
const stopBooked = (threadId, booked, reason = "stop") => {
|
|
5970
|
+
if (reason === "stop") booked.runtime.markStopped();
|
|
5971
|
+
booked.closing ??= booked.runtime.close(reason).then(() => {
|
|
5972
|
+
if (threads.get(threadId) === booked) threads.delete(threadId);
|
|
5973
|
+
});
|
|
5974
|
+
return booked.closing;
|
|
5873
5975
|
};
|
|
5874
5976
|
const instance = {
|
|
5875
5977
|
probe: async () => {
|
|
@@ -5930,8 +6032,8 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5930
6032
|
if (cwd.trim() === "") throw new Error("workspace path missing");
|
|
5931
6033
|
const existing = threads.get(input.threadId);
|
|
5932
6034
|
if (existing !== void 0) {
|
|
5933
|
-
|
|
5934
|
-
|
|
6035
|
+
if (existing.closing) throw new Error(`thread ${input.threadId} is closing`);
|
|
6036
|
+
await stopBooked(input.threadId, existing);
|
|
5935
6037
|
}
|
|
5936
6038
|
const layout = layoutFor(recipe);
|
|
5937
6039
|
const { handle, args } = await spawnCodexAppServer({
|
|
@@ -5942,6 +6044,7 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5942
6044
|
});
|
|
5943
6045
|
trackHandle(handle, [recipe.binaryPath, ...args].join(" "), input.threadId);
|
|
5944
6046
|
let runtime;
|
|
6047
|
+
let booked;
|
|
5945
6048
|
const rpc = await createCodexRpcClient(handle, {
|
|
5946
6049
|
onNotification: (notification) => {
|
|
5947
6050
|
runtime?.handleNotification(notification.method, notification.params);
|
|
@@ -5962,7 +6065,13 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5962
6065
|
runtime?.settleNativeWrite(id, status);
|
|
5963
6066
|
},
|
|
5964
6067
|
onExit: () => {
|
|
5965
|
-
if (
|
|
6068
|
+
if (booked)
|
|
6069
|
+
void stopBooked(input.threadId, booked, "process").catch((error) => {
|
|
6070
|
+
host.log.warn("closing codex session failed", {
|
|
6071
|
+
threadId: input.threadId,
|
|
6072
|
+
error: String(error)
|
|
6073
|
+
});
|
|
6074
|
+
});
|
|
5966
6075
|
},
|
|
5967
6076
|
failureCategoryForProcessExit: () => codexProcessExitCategory(runtime)
|
|
5968
6077
|
});
|
|
@@ -5975,22 +6084,25 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
5975
6084
|
args,
|
|
5976
6085
|
void 0,
|
|
5977
6086
|
void 0,
|
|
5978
|
-
attachments
|
|
6087
|
+
attachments,
|
|
6088
|
+
{ requestClose: () => stopBooked(input.threadId, booked, "process") }
|
|
5979
6089
|
);
|
|
6090
|
+
booked = { runtime, rpc, handle };
|
|
6091
|
+
threads.set(input.threadId, booked);
|
|
5980
6092
|
try {
|
|
5981
6093
|
await rpc.request("initialize", CODEX_INITIALIZE_PARAMS);
|
|
5982
6094
|
await rpc.notify("initialized");
|
|
5983
6095
|
await setCodexSessionSkillRoots(rpc, input.skills, host.log, input.threadId);
|
|
5984
6096
|
const session = await runtime.openThread(input);
|
|
5985
6097
|
await yieldTick();
|
|
5986
|
-
|
|
6098
|
+
if (booked.closing) throw new Error("codex session closed during startup");
|
|
5987
6099
|
host.log.info("session started", {
|
|
5988
6100
|
threadId: input.threadId,
|
|
5989
6101
|
nativeThreadId: runtime.nativeThreadId
|
|
5990
6102
|
});
|
|
5991
6103
|
return session;
|
|
5992
6104
|
} catch (error) {
|
|
5993
|
-
await
|
|
6105
|
+
await stopBooked(input.threadId, booked).catch(() => void 0);
|
|
5994
6106
|
throw error;
|
|
5995
6107
|
}
|
|
5996
6108
|
},
|
|
@@ -6009,8 +6121,8 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
6009
6121
|
}
|
|
6010
6122
|
},
|
|
6011
6123
|
interruptTurn: async (threadId, turnId) => {
|
|
6012
|
-
|
|
6013
|
-
|
|
6124
|
+
if (!threads.has(threadId)) return;
|
|
6125
|
+
const booked = requireThread(threadId);
|
|
6014
6126
|
host.log.info("interrupt turn", { threadId, turnId });
|
|
6015
6127
|
await booked.runtime.interruptTurn(turnId);
|
|
6016
6128
|
},
|
|
@@ -6038,26 +6150,31 @@ var createCodexInstance = (config, host, attachments, cache) => {
|
|
|
6038
6150
|
stopSession: async (threadId) => {
|
|
6039
6151
|
const booked = threads.get(threadId);
|
|
6040
6152
|
if (booked === void 0) return;
|
|
6041
|
-
|
|
6042
|
-
await stopBooked(booked);
|
|
6153
|
+
await stopBooked(threadId, booked);
|
|
6043
6154
|
},
|
|
6044
6155
|
readThread: async (threadId) => {
|
|
6045
6156
|
const booked = requireThread(threadId);
|
|
6046
6157
|
return await booked.runtime.readThread();
|
|
6047
6158
|
},
|
|
6048
6159
|
events,
|
|
6049
|
-
dispose:
|
|
6050
|
-
if (
|
|
6160
|
+
dispose: () => {
|
|
6161
|
+
if (disposeTask) return disposeTask;
|
|
6051
6162
|
disposed = true;
|
|
6052
|
-
const
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6163
|
+
const closing = Promise.allSettled(
|
|
6164
|
+
[...threads.entries()].map(([threadId, booked]) => stopBooked(threadId, booked))
|
|
6165
|
+
);
|
|
6166
|
+
disposeTask = (async () => {
|
|
6167
|
+
const operations = [...signInOperations.values()];
|
|
6168
|
+
signInOperations.clear();
|
|
6169
|
+
for (const operation of operations) {
|
|
6170
|
+
await operation.close().catch(() => void 0);
|
|
6171
|
+
}
|
|
6172
|
+
for (const result of await closing) {
|
|
6173
|
+
if (result.status === "rejected") throw result.reason;
|
|
6174
|
+
}
|
|
6175
|
+
events.close();
|
|
6176
|
+
})();
|
|
6177
|
+
return disposeTask;
|
|
6061
6178
|
},
|
|
6062
6179
|
// 项目里的 repo 级技能:探测的 app-server 没有工作区,只报得出用户与系统级;这里按目录问
|
|
6063
6180
|
// 一次性 app-server(与读额度同一条进程通道),宿主缓存结果。
|
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.3112",
|
|
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.3112",
|
|
33
33
|
"ycodium-executor-testing": "0.0.0"
|
|
34
34
|
},
|
|
35
35
|
"ycodium": {
|