@ycodium-ai/agent-codex 0.2.3766 → 0.2.3831
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 +138 -17
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2351,9 +2351,12 @@ function codexExecLaunchArgs(launchArgs) {
|
|
|
2351
2351
|
function codexMcpThreadConfig(servers) {
|
|
2352
2352
|
return {
|
|
2353
2353
|
mcp_servers: Object.fromEntries(
|
|
2354
|
-
servers.map(({ name, transport }) => [
|
|
2354
|
+
servers.map(({ name, transport, toolTimeoutSeconds }) => [
|
|
2355
2355
|
name,
|
|
2356
|
-
|
|
2356
|
+
{
|
|
2357
|
+
...transport.type === "stdio" ? { command: transport.command, args: transport.args ?? [], env: transport.env ?? {} } : { url: transport.url, http_headers: transport.headers ?? {} },
|
|
2358
|
+
...toolTimeoutSeconds === void 0 ? {} : { tool_timeout_sec: toolTimeoutSeconds }
|
|
2359
|
+
}
|
|
2357
2360
|
])
|
|
2358
2361
|
)
|
|
2359
2362
|
};
|
|
@@ -4137,6 +4140,8 @@ function mapNotificationToEvents(input) {
|
|
|
4137
4140
|
type: "user-input.requested",
|
|
4138
4141
|
threadId,
|
|
4139
4142
|
turnId,
|
|
4143
|
+
// 带上回复条目:宿主据此不再把这条回复和提问卡重复画一遍。
|
|
4144
|
+
itemId,
|
|
4140
4145
|
requestId: `codex-async:${itemId}`,
|
|
4141
4146
|
payload: { questions: asyncQuestions, responseMode: "message" },
|
|
4142
4147
|
method,
|
|
@@ -4645,6 +4650,112 @@ function mapServerRequestToEvents(input) {
|
|
|
4645
4650
|
];
|
|
4646
4651
|
}
|
|
4647
4652
|
|
|
4653
|
+
// src/backgroundCommands.ts
|
|
4654
|
+
function commandDescription(item) {
|
|
4655
|
+
const actions = Array.isArray(item["commandActions"]) ? item["commandActions"] : [];
|
|
4656
|
+
const first = isRecord2(actions[0]) ? asString(actions[0]["command"]) : null;
|
|
4657
|
+
return first ?? asString(item["command"]) ?? "";
|
|
4658
|
+
}
|
|
4659
|
+
var CodexBackgroundCommands = class {
|
|
4660
|
+
#commands = /* @__PURE__ */ new Map();
|
|
4661
|
+
#threadId;
|
|
4662
|
+
#providerInstanceId;
|
|
4663
|
+
constructor(threadId, providerInstanceId) {
|
|
4664
|
+
this.#threadId = threadId;
|
|
4665
|
+
this.#providerInstanceId = providerInstanceId;
|
|
4666
|
+
}
|
|
4667
|
+
#completed(taskId, turnId, status, method) {
|
|
4668
|
+
return baseEvent({
|
|
4669
|
+
type: "task.completed",
|
|
4670
|
+
threadId: this.#threadId,
|
|
4671
|
+
turnId,
|
|
4672
|
+
payload: { taskId, status },
|
|
4673
|
+
method,
|
|
4674
|
+
providerInstanceId: this.#providerInstanceId
|
|
4675
|
+
});
|
|
4676
|
+
}
|
|
4677
|
+
#settleTurn(method, params) {
|
|
4678
|
+
const turnId = turnIdOf(params);
|
|
4679
|
+
const events = [];
|
|
4680
|
+
for (const [id, command] of this.#commands) {
|
|
4681
|
+
if (command.background || turnId !== void 0 && command.turnId !== turnId) continue;
|
|
4682
|
+
if (turnCompletedControlFlow(params).state !== "completed") {
|
|
4683
|
+
this.#commands.delete(id);
|
|
4684
|
+
continue;
|
|
4685
|
+
}
|
|
4686
|
+
this.#commands.set(id, { ...command, background: true });
|
|
4687
|
+
events.push(
|
|
4688
|
+
baseEvent({
|
|
4689
|
+
type: "task.started",
|
|
4690
|
+
threadId: this.#threadId,
|
|
4691
|
+
turnId: command.turnId,
|
|
4692
|
+
payload: { taskId: id, taskType: "local_bash", description: command.description },
|
|
4693
|
+
method,
|
|
4694
|
+
providerInstanceId: this.#providerInstanceId
|
|
4695
|
+
})
|
|
4696
|
+
);
|
|
4697
|
+
}
|
|
4698
|
+
return events;
|
|
4699
|
+
}
|
|
4700
|
+
/** 跟着通知走,返回要补发的 task 事件;放在该通知本身的事件之后发。 */
|
|
4701
|
+
observe(method, params) {
|
|
4702
|
+
if (method === "turn/completed") return this.#settleTurn(method, params);
|
|
4703
|
+
if (method === "thread/closed") {
|
|
4704
|
+
const closed = [...this.#commands].filter(([, command2]) => command2.background);
|
|
4705
|
+
this.#commands.clear();
|
|
4706
|
+
return closed.map(([id2, command2]) => this.#completed(id2, command2.turnId, "stopped", method));
|
|
4707
|
+
}
|
|
4708
|
+
if (!isRecord2(params) || !isRecord2(params["item"])) return [];
|
|
4709
|
+
const item = params["item"];
|
|
4710
|
+
const id = item["id"];
|
|
4711
|
+
if (item["type"] !== "commandExecution" || typeof id !== "string") return [];
|
|
4712
|
+
if (method === "item/started") {
|
|
4713
|
+
if (item["source"] === "unifiedExecInteraction") return [];
|
|
4714
|
+
this.#commands.set(id, {
|
|
4715
|
+
turnId: turnIdOf(params),
|
|
4716
|
+
description: commandDescription(item),
|
|
4717
|
+
processId: asString(item["processId"]) ?? void 0,
|
|
4718
|
+
background: false
|
|
4719
|
+
});
|
|
4720
|
+
return [];
|
|
4721
|
+
}
|
|
4722
|
+
if (method !== "item/completed") return [];
|
|
4723
|
+
const command = this.#commands.get(id);
|
|
4724
|
+
this.#commands.delete(id);
|
|
4725
|
+
if (command?.background !== true) return [];
|
|
4726
|
+
const status = itemStatusOf(params);
|
|
4727
|
+
return [
|
|
4728
|
+
this.#completed(
|
|
4729
|
+
id,
|
|
4730
|
+
command.turnId,
|
|
4731
|
+
status === "failed" ? "failed" : status === "declined" ? "stopped" : "completed",
|
|
4732
|
+
method
|
|
4733
|
+
)
|
|
4734
|
+
];
|
|
4735
|
+
}
|
|
4736
|
+
/** 用户点停止时结束有进程号的后台任务;请求失败的留着,等它自己的 `item/completed`。 */
|
|
4737
|
+
async stop(rpc, nativeThreadId) {
|
|
4738
|
+
const running = [...this.#commands].filter(
|
|
4739
|
+
(entry) => entry[1].background && entry[1].processId !== void 0
|
|
4740
|
+
);
|
|
4741
|
+
const stopped = await Promise.all(
|
|
4742
|
+
running.map(async ([id, command]) => {
|
|
4743
|
+
try {
|
|
4744
|
+
await rpc.request("thread/backgroundTerminals/terminate", {
|
|
4745
|
+
threadId: nativeThreadId,
|
|
4746
|
+
processId: command.processId
|
|
4747
|
+
});
|
|
4748
|
+
} catch {
|
|
4749
|
+
return [];
|
|
4750
|
+
}
|
|
4751
|
+
this.#commands.delete(id);
|
|
4752
|
+
return [this.#completed(id, command.turnId, "stopped")];
|
|
4753
|
+
})
|
|
4754
|
+
);
|
|
4755
|
+
return stopped.flat();
|
|
4756
|
+
}
|
|
4757
|
+
};
|
|
4758
|
+
|
|
4648
4759
|
// src/openCommands.ts
|
|
4649
4760
|
import {
|
|
4650
4761
|
isPosixShellCommandFlag,
|
|
@@ -4799,6 +4910,21 @@ function readSubAgentActivity(method, params) {
|
|
|
4799
4910
|
agentPath: asString(item["agentPath"]) ?? void 0
|
|
4800
4911
|
};
|
|
4801
4912
|
}
|
|
4913
|
+
async function interruptForeignTurns(rpc, turns) {
|
|
4914
|
+
const started = Date.now();
|
|
4915
|
+
await Promise.all(
|
|
4916
|
+
[...turns.entries()].slice(0, 8).map(async ([thread, childTurn]) => {
|
|
4917
|
+
if (Date.now() - started > 1e4) return;
|
|
4918
|
+
try {
|
|
4919
|
+
await Promise.race([
|
|
4920
|
+
rpc.request("turn/interrupt", { threadId: thread, turnId: childTurn }, 0),
|
|
4921
|
+
new Promise((resolve4) => setTimeout(resolve4, 3e3))
|
|
4922
|
+
]);
|
|
4923
|
+
} catch {
|
|
4924
|
+
}
|
|
4925
|
+
})
|
|
4926
|
+
);
|
|
4927
|
+
}
|
|
4802
4928
|
var CodexSessionCollab = class {
|
|
4803
4929
|
runtime;
|
|
4804
4930
|
constructor(runtime) {
|
|
@@ -5294,6 +5420,7 @@ var CodexSessionRuntime = class {
|
|
|
5294
5420
|
closeOptions;
|
|
5295
5421
|
#collab = new CodexSessionCollab(this);
|
|
5296
5422
|
#requests = new CodexSessionRequests(this);
|
|
5423
|
+
#background;
|
|
5297
5424
|
/**
|
|
5298
5425
|
* 对外 requestId 的前缀,每个会话(即每个 app-server 进程)一份。JSON-RPC id 每个进程
|
|
5299
5426
|
* 都从 0 数起,宿主按 requestId 记「已接受」,不加前缀的话重启后的新请求会撞上旧请求。
|
|
@@ -5328,6 +5455,7 @@ var CodexSessionRuntime = class {
|
|
|
5328
5455
|
});
|
|
5329
5456
|
});
|
|
5330
5457
|
this.emit = (event) => this.#lifecycle.emit(event);
|
|
5458
|
+
this.#background = new CodexBackgroundCommands(input.threadId, host.instanceId);
|
|
5331
5459
|
this.threadId = input.threadId;
|
|
5332
5460
|
this.cwd = cwd;
|
|
5333
5461
|
this.runtimeMode = input.runtimeMode;
|
|
@@ -5478,6 +5606,7 @@ var CodexSessionRuntime = class {
|
|
|
5478
5606
|
})) {
|
|
5479
5607
|
this.emit(event);
|
|
5480
5608
|
}
|
|
5609
|
+
for (const event of this.#background.observe(method, params)) this.emit(event);
|
|
5481
5610
|
if (method === "turn/started" && this.#lifecycle.acceptsLifecycle) {
|
|
5482
5611
|
const turnId = turnIdOf(params);
|
|
5483
5612
|
if (turnId) this.activeTurnId = turnId;
|
|
@@ -5673,21 +5802,13 @@ var CodexSessionRuntime = class {
|
|
|
5673
5802
|
};
|
|
5674
5803
|
}
|
|
5675
5804
|
async interruptTurn(turnId) {
|
|
5676
|
-
|
|
5677
|
-
const started = Date.now();
|
|
5678
|
-
await Promise.all(
|
|
5679
|
-
childTurns.slice(0, 8).map(async ([thread, childTurn]) => {
|
|
5680
|
-
if (Date.now() - started > 1e4) return;
|
|
5681
|
-
try {
|
|
5682
|
-
await Promise.race([
|
|
5683
|
-
this.rpc.request("turn/interrupt", { threadId: thread, turnId: childTurn }, 0),
|
|
5684
|
-
sleep(3e3)
|
|
5685
|
-
]);
|
|
5686
|
-
} catch {
|
|
5687
|
-
}
|
|
5688
|
-
})
|
|
5689
|
-
);
|
|
5805
|
+
await interruptForeignTurns(this.rpc, this.liveForeignTurns);
|
|
5690
5806
|
if (!this.nativeThreadId) return;
|
|
5807
|
+
if (turnId === void 0) {
|
|
5808
|
+
for (const event of await this.#background.stop(this.rpc, this.nativeThreadId)) {
|
|
5809
|
+
this.emit(event);
|
|
5810
|
+
}
|
|
5811
|
+
}
|
|
5691
5812
|
const target = turnId ?? this.activeTurnId;
|
|
5692
5813
|
if (target) {
|
|
5693
5814
|
await this.rpc.request("turn/interrupt", { threadId: this.nativeThreadId, turnId: target }, 0).catch(() => void 0);
|
|
@@ -7903,7 +8024,7 @@ var executors = [
|
|
|
7903
8024
|
];
|
|
7904
8025
|
var index_default = definePlugin({
|
|
7905
8026
|
id: "agent-codex",
|
|
7906
|
-
apiVersion:
|
|
8027
|
+
apiVersion: 60,
|
|
7907
8028
|
executors,
|
|
7908
8029
|
activate(ctx) {
|
|
7909
8030
|
ctx.command({
|
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.3831",
|
|
4
4
|
"description": "Codex executor: Codex CLI over the app-server JSON-RPC protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"typescript": "~6.0.3",
|
|
31
31
|
"vite-plus": "0.2.2",
|
|
32
32
|
"ycodium-executor-testing": "0.0.0",
|
|
33
|
-
"
|
|
34
|
-
"ycodium-
|
|
33
|
+
"ycodium-jsonl-stream": "0.0.0",
|
|
34
|
+
"@ycodium-ai/plugin-api": "0.2.3831"
|
|
35
35
|
},
|
|
36
36
|
"ycodium": {
|
|
37
37
|
"plugin": "./dist/index.js",
|