@ycodium-ai/agent-codex 0.2.3799 → 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 +130 -14
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4650,6 +4650,112 @@ function mapServerRequestToEvents(input) {
|
|
|
4650
4650
|
];
|
|
4651
4651
|
}
|
|
4652
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
|
+
|
|
4653
4759
|
// src/openCommands.ts
|
|
4654
4760
|
import {
|
|
4655
4761
|
isPosixShellCommandFlag,
|
|
@@ -4804,6 +4910,21 @@ function readSubAgentActivity(method, params) {
|
|
|
4804
4910
|
agentPath: asString(item["agentPath"]) ?? void 0
|
|
4805
4911
|
};
|
|
4806
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
|
+
}
|
|
4807
4928
|
var CodexSessionCollab = class {
|
|
4808
4929
|
runtime;
|
|
4809
4930
|
constructor(runtime) {
|
|
@@ -5299,6 +5420,7 @@ var CodexSessionRuntime = class {
|
|
|
5299
5420
|
closeOptions;
|
|
5300
5421
|
#collab = new CodexSessionCollab(this);
|
|
5301
5422
|
#requests = new CodexSessionRequests(this);
|
|
5423
|
+
#background;
|
|
5302
5424
|
/**
|
|
5303
5425
|
* 对外 requestId 的前缀,每个会话(即每个 app-server 进程)一份。JSON-RPC id 每个进程
|
|
5304
5426
|
* 都从 0 数起,宿主按 requestId 记「已接受」,不加前缀的话重启后的新请求会撞上旧请求。
|
|
@@ -5333,6 +5455,7 @@ var CodexSessionRuntime = class {
|
|
|
5333
5455
|
});
|
|
5334
5456
|
});
|
|
5335
5457
|
this.emit = (event) => this.#lifecycle.emit(event);
|
|
5458
|
+
this.#background = new CodexBackgroundCommands(input.threadId, host.instanceId);
|
|
5336
5459
|
this.threadId = input.threadId;
|
|
5337
5460
|
this.cwd = cwd;
|
|
5338
5461
|
this.runtimeMode = input.runtimeMode;
|
|
@@ -5483,6 +5606,7 @@ var CodexSessionRuntime = class {
|
|
|
5483
5606
|
})) {
|
|
5484
5607
|
this.emit(event);
|
|
5485
5608
|
}
|
|
5609
|
+
for (const event of this.#background.observe(method, params)) this.emit(event);
|
|
5486
5610
|
if (method === "turn/started" && this.#lifecycle.acceptsLifecycle) {
|
|
5487
5611
|
const turnId = turnIdOf(params);
|
|
5488
5612
|
if (turnId) this.activeTurnId = turnId;
|
|
@@ -5678,21 +5802,13 @@ var CodexSessionRuntime = class {
|
|
|
5678
5802
|
};
|
|
5679
5803
|
}
|
|
5680
5804
|
async interruptTurn(turnId) {
|
|
5681
|
-
|
|
5682
|
-
const started = Date.now();
|
|
5683
|
-
await Promise.all(
|
|
5684
|
-
childTurns.slice(0, 8).map(async ([thread, childTurn]) => {
|
|
5685
|
-
if (Date.now() - started > 1e4) return;
|
|
5686
|
-
try {
|
|
5687
|
-
await Promise.race([
|
|
5688
|
-
this.rpc.request("turn/interrupt", { threadId: thread, turnId: childTurn }, 0),
|
|
5689
|
-
sleep(3e3)
|
|
5690
|
-
]);
|
|
5691
|
-
} catch {
|
|
5692
|
-
}
|
|
5693
|
-
})
|
|
5694
|
-
);
|
|
5805
|
+
await interruptForeignTurns(this.rpc, this.liveForeignTurns);
|
|
5695
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
|
+
}
|
|
5696
5812
|
const target = turnId ?? this.activeTurnId;
|
|
5697
5813
|
if (target) {
|
|
5698
5814
|
await this.rpc.request("turn/interrupt", { threadId: this.nativeThreadId, turnId: target }, 0).catch(() => void 0);
|
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",
|
|
@@ -29,9 +29,9 @@
|
|
|
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.3799",
|
|
33
32
|
"ycodium-executor-testing": "0.0.0",
|
|
34
|
-
"ycodium-jsonl-stream": "0.0.0"
|
|
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",
|