linkshell-cli 0.10.7 → 0.10.9
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/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/gateway/src/main.js +4 -0
- package/dist/gateway/src/main.js.map +1 -1
- package/dist/gateway/src/serve.d.ts +3 -1
- package/dist/gateway/src/serve.js +5 -1
- package/dist/gateway/src/serve.js.map +1 -1
- package/dist/gateway/src/web.d.ts +12 -0
- package/dist/gateway/src/web.js +53 -0
- package/dist/gateway/src/web.js.map +1 -0
- package/dist/host/src/computer-preview-capture.d.ts +11 -0
- package/dist/host/src/computer-preview-capture.js +87 -0
- package/dist/host/src/computer-preview-capture.js.map +1 -0
- package/dist/host/src/computer-preview.d.ts +73 -0
- package/dist/host/src/computer-preview.js +335 -0
- package/dist/host/src/computer-preview.js.map +1 -0
- package/dist/host/src/drivers/acp/connection.d.ts +2 -0
- package/dist/host/src/drivers/acp/connection.js +14 -1
- package/dist/host/src/drivers/acp/connection.js.map +1 -1
- package/dist/host/src/drivers/acp/driver.d.ts +4 -0
- package/dist/host/src/drivers/acp/driver.js +45 -1
- package/dist/host/src/drivers/acp/driver.js.map +1 -1
- package/dist/host/src/drivers/acp/mapper.js +11 -1
- package/dist/host/src/drivers/acp/mapper.js.map +1 -1
- package/dist/host/src/drivers/claude/activity.d.ts +1 -0
- package/dist/host/src/drivers/claude/activity.js +1 -0
- package/dist/host/src/drivers/claude/activity.js.map +1 -1
- package/dist/host/src/drivers/claude/driver.d.ts +6 -0
- package/dist/host/src/drivers/claude/driver.js +30 -2
- package/dist/host/src/drivers/claude/driver.js.map +1 -1
- package/dist/host/src/drivers/claude/tasks.d.ts +33 -0
- package/dist/host/src/drivers/claude/tasks.js +138 -0
- package/dist/host/src/drivers/claude/tasks.js.map +1 -0
- package/dist/host/src/drivers/claude/transcript.d.ts +31 -3
- package/dist/host/src/drivers/claude/transcript.js +20 -1
- package/dist/host/src/drivers/claude/transcript.js.map +1 -1
- package/dist/host/src/drivers/codex/app-server.js +0 -3
- package/dist/host/src/drivers/codex/app-server.js.map +1 -1
- package/dist/host/src/drivers/codex/commands.js +7 -1
- package/dist/host/src/drivers/codex/commands.js.map +1 -1
- package/dist/host/src/drivers/codex/computer-preview.d.ts +3 -0
- package/dist/host/src/drivers/codex/computer-preview.js +44 -0
- package/dist/host/src/drivers/codex/computer-preview.js.map +1 -0
- package/dist/host/src/drivers/codex/driver.d.ts +16 -1
- package/dist/host/src/drivers/codex/driver.js +262 -6
- package/dist/host/src/drivers/codex/driver.js.map +1 -1
- package/dist/host/src/drivers/codex/mapper.js +38 -3
- package/dist/host/src/drivers/codex/mapper.js.map +1 -1
- package/dist/host/src/drivers/registry.js +1 -1
- package/dist/host/src/drivers/registry.js.map +1 -1
- package/dist/host/src/drivers/types.d.ts +23 -1
- package/dist/host/src/hub.d.ts +18 -1
- package/dist/host/src/hub.js +102 -1
- package/dist/host/src/hub.js.map +1 -1
- package/dist/host/src/input.d.ts +9 -0
- package/dist/host/src/input.js +15 -0
- package/dist/host/src/input.js.map +1 -1
- package/dist/host/src/rpc/server.d.ts +1 -0
- package/dist/host/src/rpc/server.js +20 -2
- package/dist/host/src/rpc/server.js.map +1 -1
- package/dist/host/src/screen-viewer.js +641 -109
- package/dist/host/src/screen-viewer.js.map +1 -1
- package/dist/host/src/store.d.ts +10 -0
- package/dist/host/src/store.js +29 -0
- package/dist/host/src/store.js.map +1 -1
- package/dist/host/src/task-output.d.ts +6 -0
- package/dist/host/src/task-output.js +22 -0
- package/dist/host/src/task-output.js.map +1 -0
- package/dist/host/src/terminals.d.ts +37 -2
- package/dist/host/src/terminals.js +54 -14
- package/dist/host/src/terminals.js.map +1 -1
- package/dist/wire/src/computer-preview.d.ts +35 -0
- package/dist/wire/src/computer-preview.js +51 -0
- package/dist/wire/src/computer-preview.js.map +1 -0
- package/dist/wire/src/goal.d.ts +66 -0
- package/dist/wire/src/goal.js +19 -0
- package/dist/wire/src/goal.js.map +1 -0
- package/dist/wire/src/index.d.ts +2 -0
- package/dist/wire/src/index.js +2 -0
- package/dist/wire/src/index.js.map +1 -1
- package/dist/wire/src/model.d.ts +78 -0
- package/dist/wire/src/model.js +31 -0
- package/dist/wire/src/model.js.map +1 -1
- package/dist/wire/src/rpc.d.ts +1289 -60
- package/dist/wire/src/rpc.js +53 -3
- package/dist/wire/src/rpc.js.map +1 -1
- package/dist/wire/src/updates.d.ts +334 -22
- package/dist/wire/src/updates.js +11 -1
- package/dist/wire/src/updates.js.map +1 -1
- package/package.json +5 -5
|
@@ -18,9 +18,6 @@ const OPT_OUT_NOTIFICATIONS = [
|
|
|
18
18
|
"rawResponse/completed",
|
|
19
19
|
"rawResponseItem/completed",
|
|
20
20
|
"remoteControl/status/changed",
|
|
21
|
-
"skills/changed",
|
|
22
|
-
"thread/goal/cleared",
|
|
23
|
-
"thread/goal/updated",
|
|
24
21
|
];
|
|
25
22
|
/**
|
|
26
23
|
* Where Codex's own background server listens: the one a plain `codex` in a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-server.js","sourceRoot":"","sources":["../../../../../../host/src/drivers/codex/app-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAqB,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAc,MAAM,iBAAiB,CAAC;AAE/D,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,4EAA4E;AAC5E,MAAM,qBAAqB,GAAG;IAC5B,4BAA4B;IAC5B,iBAAiB;IACjB,kBAAkB;IAClB,YAAY;IACZ,cAAc;IACd,gBAAgB;IAChB,iCAAiC;IACjC,uBAAuB;IACvB,2BAA2B;IAC3B,8BAA8B;
|
|
1
|
+
{"version":3,"file":"app-server.js","sourceRoot":"","sources":["../../../../../../host/src/drivers/codex/app-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,12 @@ export const COMMANDS = [
|
|
|
2
2
|
{ name: "compact", description: "压缩上下文:把之前的对话总结一下,腾出空间继续" },
|
|
3
3
|
{ name: "review", description: "审查还没提交的改动", hint: "也可以写上要审查什么" },
|
|
4
4
|
{ name: "init", description: "为这个项目生成 AGENTS.md" },
|
|
5
|
+
{ name: "reload-skills", description: "重新加载项目可用的技能" },
|
|
6
|
+
{ name: "status", description: "查看当前会话状态与模型" },
|
|
7
|
+
{ name: "mcp", description: "查看当前会话的 MCP 服务" },
|
|
8
|
+
{ name: "apps", description: "查看可用的应用与连接器" },
|
|
9
|
+
{ name: "ps", description: "查看当前会话的后台终端" },
|
|
10
|
+
{ name: "stop", description: "停止当前会话的所有后台终端" },
|
|
5
11
|
];
|
|
6
12
|
export const INIT_PROMPT = [
|
|
7
13
|
"Generate a file named AGENTS.md that serves as a contributor guide for this repository.",
|
|
@@ -17,7 +23,7 @@ export function commandOf(content) {
|
|
|
17
23
|
.map((block) => (block.type === "text" ? block.text : ""))
|
|
18
24
|
.join("")
|
|
19
25
|
.trim();
|
|
20
|
-
const match =
|
|
26
|
+
const match = /^[//]([^\s//]+)(?:\s+([\s\S]*))?$/.exec(text);
|
|
21
27
|
return match ? { name: match[1], args: match[2]?.trim() ?? "", text } : undefined;
|
|
22
28
|
}
|
|
23
29
|
//# sourceMappingURL=commands.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../../../host/src/drivers/codex/commands.ts"],"names":[],"mappings":"AAeA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAC3D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE;IAChE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE;
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../../../../host/src/drivers/codex/commands.ts"],"names":[],"mappings":"AAeA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,yBAAyB,EAAE;IAC3D,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE;IAChE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAClD,EAAE,IAAI,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE;IACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;IAC9C,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE;IAC9C,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE;IAC5C,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE;IAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE;CAC/C,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,yFAAyF;IACzF,mIAAmI;IACnI,+KAA+K;IAC/K,uIAAuI;CACxI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,2DAA2D;AAC3D,MAAM,UAAU,SAAS,CAAC,OAAuB;IAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7F,MAAM,IAAI,GAAG,OAAO;SACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACzD,IAAI,CAAC,EAAE,CAAC;SACR,IAAI,EAAE,CAAC;IACV,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { previewCaptureSchema } from "../../computer-preview.js";
|
|
2
|
+
const object = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : undefined;
|
|
3
|
+
/** The desktop's preview surface, deliberately independent of chat result.content. */
|
|
4
|
+
export function codexPreview(raw, capturedAt = Date.now()) {
|
|
5
|
+
const item = object(raw);
|
|
6
|
+
if (item?.type !== "mcpToolCall" || typeof item.server !== "string" || !["cua_repl", "computer-use", "computer_use"].includes(item.server))
|
|
7
|
+
return;
|
|
8
|
+
if (!Number.isFinite(capturedAt) || capturedAt < 0)
|
|
9
|
+
return;
|
|
10
|
+
const surface = object(object(object(item.result)?._meta)?.["codex/toolSurface"]);
|
|
11
|
+
if (surface?.kind === "computerUse") {
|
|
12
|
+
const app = object(surface.app);
|
|
13
|
+
if (app?.kind !== "appId" || typeof item.id !== "string")
|
|
14
|
+
return;
|
|
15
|
+
const content = object(item.result)?.content;
|
|
16
|
+
// Only the provider's anchored window header identifies a native window.
|
|
17
|
+
const texts = Array.isArray(content) ? content.map(object).filter(v => v?.type === "text" && typeof v.text === "string") : [];
|
|
18
|
+
const title = texts.map(v => v.text.match(/^(?:The following is a diff from the previous accessibility tree for )?Window: "([^"\n]+)"(?:, App:| with )/)?.[1]).find(Boolean);
|
|
19
|
+
const capture = previewCaptureSchema.safeParse({ bundleId: app.appId, title, app: true });
|
|
20
|
+
if (!capture.success)
|
|
21
|
+
return;
|
|
22
|
+
return { sourceId: item.id, target: JSON.stringify(["app", app.appId]), capturedAt, capture: capture.data };
|
|
23
|
+
}
|
|
24
|
+
if (surface?.kind !== "browserUse")
|
|
25
|
+
return;
|
|
26
|
+
const shot = object(surface.screenshot);
|
|
27
|
+
if (typeof shot?.url !== "string" || typeof item.id !== "string")
|
|
28
|
+
return;
|
|
29
|
+
const tab = shot.tabId;
|
|
30
|
+
if (typeof tab !== "string" && typeof tab !== "number")
|
|
31
|
+
return;
|
|
32
|
+
if (!/^data:image\/(?:jpeg|png|webp);base64,[A-Za-z0-9+/]+=*$/.test(shot.url) || shot.url.length > 4 * 1024 * 1024)
|
|
33
|
+
return;
|
|
34
|
+
const target = JSON.stringify([surface.backend, surface.browserId, tab]);
|
|
35
|
+
if (target.length > 1024)
|
|
36
|
+
return;
|
|
37
|
+
const tabs = Array.isArray(surface.openTabs) ? surface.openTabs : [];
|
|
38
|
+
const entry = tabs.map(object).find(entry => entry && (typeof entry.id === "string" || typeof entry.id === "number") && String(entry.id) === String(tab));
|
|
39
|
+
const bundleId = surface.backend === "chrome" && surface.browserFamily === "chrome" ? "com.google.Chrome"
|
|
40
|
+
: (surface.backend === "chrome" || surface.backend === "edge") && surface.browserFamily === "edge" ? "com.microsoft.edgemac" : undefined;
|
|
41
|
+
const capture = previewCaptureSchema.safeParse({ bundleId, title: entry?.title });
|
|
42
|
+
return { sourceId: item.id, target, capturedAt, dataUrl: shot.url, capture: capture.success ? capture.data : undefined };
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=computer-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computer-preview.js","sourceRoot":"","sources":["../../../../../../host/src/drivers/codex/computer-preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ContentBlock, type QuestionAnswer } from "@linkshell/wire";
|
|
1
|
+
import { type GoalChange, type SessionGoal, type ContentBlock, type QuestionAnswer } from "@linkshell/wire";
|
|
2
2
|
import type { AgentAuth } from "@linkshell/wire";
|
|
3
3
|
import type { AgentDriver, DiscoveredSession, DriverHost, DriverStatus, ForkOptions, HistoryItem, LaunchSpec } from "../types.js";
|
|
4
4
|
export interface CodexDriverOptions {
|
|
@@ -71,6 +71,9 @@ export declare class CodexDriver implements AgentDriver {
|
|
|
71
71
|
/** Each thread's working directory: where its skills are looked up. */
|
|
72
72
|
private readonly cwds;
|
|
73
73
|
private readonly skills;
|
|
74
|
+
private readonly goalAvailable;
|
|
75
|
+
private readonly goalRevision;
|
|
76
|
+
private skillsRevision;
|
|
74
77
|
private models?;
|
|
75
78
|
private restartTimer?;
|
|
76
79
|
private restartDelay;
|
|
@@ -85,6 +88,11 @@ export declare class CodexDriver implements AgentDriver {
|
|
|
85
88
|
/** Notifications for a thread being joined, held until its history has been read. */
|
|
86
89
|
private readonly joining;
|
|
87
90
|
/** Threads a device has open. */
|
|
91
|
+
private readonly taskProcesses;
|
|
92
|
+
private readonly taskPolls;
|
|
93
|
+
private readonly taskSyncs;
|
|
94
|
+
private readonly stoppingTasks;
|
|
95
|
+
private readonly taskRevisions;
|
|
88
96
|
private readonly watching;
|
|
89
97
|
/** Threads another client of this host's app-server opened (`linkshell codex`): followed for as long as the host runs. */
|
|
90
98
|
private readonly kept;
|
|
@@ -170,6 +178,11 @@ export declare class CodexDriver implements AgentDriver {
|
|
|
170
178
|
private reportHeld;
|
|
171
179
|
/** Whether a device has the session open. */
|
|
172
180
|
watched(nativeId: string, open: boolean): void;
|
|
181
|
+
private publishTask;
|
|
182
|
+
private loseTasks;
|
|
183
|
+
private syncTasks;
|
|
184
|
+
private readTasks;
|
|
185
|
+
stopTask(nativeId: string, taskId: string): Promise<void>;
|
|
173
186
|
private cancelRelease;
|
|
174
187
|
/**
|
|
175
188
|
* A thread stays loaded, and closed to every other Codex program, for as
|
|
@@ -190,6 +203,8 @@ export declare class CodexDriver implements AgentDriver {
|
|
|
190
203
|
*/
|
|
191
204
|
private runCommand;
|
|
192
205
|
private send;
|
|
206
|
+
goal(nativeId: string, change: GoalChange): Promise<SessionGoal | null>;
|
|
207
|
+
private announceGoal;
|
|
193
208
|
/** Model, reasoning effort and permissions apply from the next turn on. */
|
|
194
209
|
setConfig(nativeId: string, optionId: string, value: string): Promise<void>;
|
|
195
210
|
private loadModels;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
|
-
import {
|
|
2
|
+
import { codexPreview } from "./computer-preview.js";
|
|
3
|
+
import { ABANDON, RpcError, sessionGoalSchema } from "@linkshell/wire";
|
|
3
4
|
import { parseCodexLoginStatus, runStatusCommand } from "../auth.js";
|
|
4
5
|
import { CodexAppServer, CodexSharedServer, detectCodex, sharedServerSocket } from "./app-server.js";
|
|
5
6
|
import { APPROVAL_METHODS, QUESTION_METHODS, mapApprovalRequest, mapQuestionRequest, mapNotification, threadStateOf, threadToDiscovered, spawnedThreads, subagentHistory, threadToHistory, toCodexInput, toolStart, turnUnderWay, } from "./mapper.js";
|
|
@@ -79,6 +80,9 @@ export class CodexDriver {
|
|
|
79
80
|
/** Each thread's working directory: where its skills are looked up. */
|
|
80
81
|
cwds = new Map();
|
|
81
82
|
skills = new Map();
|
|
83
|
+
goalAvailable = new Set();
|
|
84
|
+
goalRevision = new Map();
|
|
85
|
+
skillsRevision = 0;
|
|
82
86
|
models;
|
|
83
87
|
restartTimer;
|
|
84
88
|
restartDelay;
|
|
@@ -93,6 +97,11 @@ export class CodexDriver {
|
|
|
93
97
|
/** Notifications for a thread being joined, held until its history has been read. */
|
|
94
98
|
joining = new Map();
|
|
95
99
|
/** Threads a device has open. */
|
|
100
|
+
taskProcesses = new Map();
|
|
101
|
+
taskPolls = new Map();
|
|
102
|
+
taskSyncs = new Map();
|
|
103
|
+
stoppingTasks = new Set();
|
|
104
|
+
taskRevisions = new Map();
|
|
96
105
|
watching = new Set();
|
|
97
106
|
/** Threads another client of this host's app-server opened (`linkshell codex`): followed for as long as the host runs. */
|
|
98
107
|
kept = new Set();
|
|
@@ -134,6 +143,9 @@ export class CodexDriver {
|
|
|
134
143
|
return parseCodexLoginStatus(await runStatusCommand(this.options.command ?? "codex", ["login", "status"], this.options.env));
|
|
135
144
|
}
|
|
136
145
|
async stop() {
|
|
146
|
+
for (const timer of this.taskPolls.values())
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
this.taskPolls.clear();
|
|
137
149
|
this.stopped = true;
|
|
138
150
|
if (this.restartTimer)
|
|
139
151
|
clearTimeout(this.restartTimer);
|
|
@@ -226,6 +238,7 @@ export class CodexDriver {
|
|
|
226
238
|
// rollout yet, so thread/resume would fail. Nothing to import either.
|
|
227
239
|
void this.announceConfig(nativeId);
|
|
228
240
|
void this.announceCommands(nativeId);
|
|
241
|
+
void this.announceGoal(nativeId);
|
|
229
242
|
return [];
|
|
230
243
|
}
|
|
231
244
|
let joined;
|
|
@@ -250,6 +263,7 @@ export class CodexDriver {
|
|
|
250
263
|
this.reportHeld(nativeId, false);
|
|
251
264
|
void this.announceConfig(nativeId);
|
|
252
265
|
void this.announceCommands(nativeId);
|
|
266
|
+
void this.announceGoal(nativeId);
|
|
253
267
|
if (this.waiting.has(nativeId))
|
|
254
268
|
void this.syncWaiting(nativeId);
|
|
255
269
|
this.considerRelease(nativeId);
|
|
@@ -317,6 +331,7 @@ export class CodexDriver {
|
|
|
317
331
|
}
|
|
318
332
|
/** Says where the joined thread stands, then lets through what arrived while it was being read. */
|
|
319
333
|
goLive(threadId, { thread, underWay }) {
|
|
334
|
+
void this.syncTasks(threadId);
|
|
320
335
|
const state = this.stateOf(threadId);
|
|
321
336
|
const active = thread.turns?.find((turn) => turn.status === "inProgress");
|
|
322
337
|
state.activeTurnId = active?.id;
|
|
@@ -370,6 +385,8 @@ export class CodexDriver {
|
|
|
370
385
|
this.cwds.set(threadId, thread.cwd);
|
|
371
386
|
this.host?.update(this.id, threadId, { sessionUpdate: "ls_status", state: running ? "running" : "idle" });
|
|
372
387
|
this.reportHeld(threadId, true);
|
|
388
|
+
void this.announceCommands(threadId);
|
|
389
|
+
void this.announceGoal(threadId);
|
|
373
390
|
// What was queued for it before this host last started is still waiting.
|
|
374
391
|
void this.syncWaiting(threadId);
|
|
375
392
|
this.considerRelease(threadId);
|
|
@@ -380,6 +397,12 @@ export class CodexDriver {
|
|
|
380
397
|
const watch = this.observed.get(threadId);
|
|
381
398
|
if (!watch || watch.reading)
|
|
382
399
|
return;
|
|
400
|
+
if (!watch.goalReading && this.goalAvailable.has(threadId) && Date.now() - (watch.goalCheckedAt ?? 0) >= 5000) {
|
|
401
|
+
watch.goalCheckedAt = Date.now();
|
|
402
|
+
watch.goalReading = true;
|
|
403
|
+
// Goal changes live in SQLite and need not change the rollout file.
|
|
404
|
+
void this.goal(threadId, { action: "get" }).catch(() => { }).finally(() => { watch.goalReading = false; });
|
|
405
|
+
}
|
|
383
406
|
if (this.waiting.has(threadId))
|
|
384
407
|
void this.syncWaiting(threadId);
|
|
385
408
|
const stamp = watch.path ? fileStamp(watch.path) : undefined;
|
|
@@ -465,6 +488,7 @@ export class CodexDriver {
|
|
|
465
488
|
this.reportHeld(threadId, false);
|
|
466
489
|
void this.announceConfig(threadId);
|
|
467
490
|
void this.announceCommands(threadId);
|
|
491
|
+
void this.announceGoal(threadId);
|
|
468
492
|
// What still waits in Codex's queue is started by this host's app-server now.
|
|
469
493
|
void this.syncWaiting(threadId);
|
|
470
494
|
})().finally(() => this.takingUp.delete(threadId));
|
|
@@ -643,6 +667,7 @@ export class CodexDriver {
|
|
|
643
667
|
watched(nativeId, open) {
|
|
644
668
|
if (open) {
|
|
645
669
|
this.watching.add(nativeId);
|
|
670
|
+
void this.syncTasks(nativeId);
|
|
646
671
|
this.cancelRelease(nativeId);
|
|
647
672
|
}
|
|
648
673
|
else {
|
|
@@ -650,6 +675,84 @@ export class CodexDriver {
|
|
|
650
675
|
this.considerRelease(nativeId);
|
|
651
676
|
}
|
|
652
677
|
}
|
|
678
|
+
publishTask(threadId, task) {
|
|
679
|
+
const { lastSeq: _, ...record } = task;
|
|
680
|
+
this.host?.update(this.id, threadId, { sessionUpdate: "ls_task", task: record });
|
|
681
|
+
}
|
|
682
|
+
loseTasks(threadId) {
|
|
683
|
+
clearTimeout(this.taskPolls.get(threadId));
|
|
684
|
+
this.taskPolls.delete(threadId);
|
|
685
|
+
this.taskProcesses.delete(threadId);
|
|
686
|
+
this.taskRevisions.set(threadId, (this.taskRevisions.get(threadId) ?? 0) + 1);
|
|
687
|
+
for (const task of this.host?.tasks(this.id, threadId) ?? []) {
|
|
688
|
+
if (task.state === "running")
|
|
689
|
+
this.publishTask(threadId, { ...task, state: "unknown", endedAt: Date.now(), canStop: false });
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
syncTasks(threadId) {
|
|
693
|
+
const pending = this.taskSyncs.get(threadId);
|
|
694
|
+
if (pending)
|
|
695
|
+
return pending;
|
|
696
|
+
if (!this.attached.has(threadId) || this.observed.has(threadId))
|
|
697
|
+
return Promise.resolve();
|
|
698
|
+
const sync = this.readTasks(threadId).catch(() => { }).finally(() => {
|
|
699
|
+
this.taskSyncs.delete(threadId);
|
|
700
|
+
clearTimeout(this.taskPolls.get(threadId));
|
|
701
|
+
this.taskPolls.delete(threadId);
|
|
702
|
+
if (this.attached.has(threadId) && this.watching.has(threadId) && this.host?.tasks(this.id, threadId).some((task) => task.state === "running")) {
|
|
703
|
+
const timer = setTimeout(() => void this.syncTasks(threadId), 5000);
|
|
704
|
+
timer.unref?.();
|
|
705
|
+
this.taskPolls.set(threadId, timer);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
this.taskSyncs.set(threadId, sync);
|
|
709
|
+
return sync;
|
|
710
|
+
}
|
|
711
|
+
async readTasks(threadId) {
|
|
712
|
+
const revision = this.taskRevisions.get(threadId) ?? 0;
|
|
713
|
+
const entries = [];
|
|
714
|
+
let cursor;
|
|
715
|
+
do {
|
|
716
|
+
const page = await this.rpcFor(threadId, "thread/backgroundTerminals/list", { threadId, limit: 100, ...(cursor ? { cursor } : {}) });
|
|
717
|
+
entries.push(...page.data);
|
|
718
|
+
cursor = page.nextCursor ?? undefined;
|
|
719
|
+
} while (cursor);
|
|
720
|
+
if (!this.attached.has(threadId) || revision !== (this.taskRevisions.get(threadId) ?? 0))
|
|
721
|
+
return;
|
|
722
|
+
const previous = new Map((this.host?.tasks(this.id, threadId) ?? []).map((task) => [task.id, task]));
|
|
723
|
+
const processes = new Map();
|
|
724
|
+
for (const entry of entries) {
|
|
725
|
+
processes.set(entry.itemId, entry.processId);
|
|
726
|
+
const old = previous.get(entry.itemId);
|
|
727
|
+
if (old?.state === "running")
|
|
728
|
+
continue;
|
|
729
|
+
this.publishTask(threadId, { id: entry.itemId, kind: "shell", toolCallId: entry.itemId, title: this.toolTitles.get(entry.itemId) ?? entry.command, command: entry.command, state: "running", startedAt: old?.startedAt ?? Date.now(), output: true, canStop: true });
|
|
730
|
+
}
|
|
731
|
+
this.taskProcesses.set(threadId, processes);
|
|
732
|
+
for (const task of previous.values()) {
|
|
733
|
+
if (task.state === "running" && !processes.has(task.id))
|
|
734
|
+
this.publishTask(threadId, { ...task, state: "unknown", endedAt: Date.now(), canStop: false });
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
async stopTask(nativeId, taskId) {
|
|
738
|
+
await this.syncTasks(nativeId);
|
|
739
|
+
const processId = this.taskProcesses.get(nativeId)?.get(taskId);
|
|
740
|
+
if (!processId)
|
|
741
|
+
throw RpcError.app("not_found", "这个后台任务已经不在运行列表里");
|
|
742
|
+
const key = `${nativeId}:${taskId}`;
|
|
743
|
+
this.stoppingTasks.add(key);
|
|
744
|
+
try {
|
|
745
|
+
const result = await this.rpcFor(nativeId, "thread/backgroundTerminals/terminate", { threadId: nativeId, processId });
|
|
746
|
+
if (!result.terminated)
|
|
747
|
+
throw RpcError.app("busy", "没能停止这个后台任务");
|
|
748
|
+
const task = this.host?.tasks(this.id, nativeId).find((task) => task.id === taskId);
|
|
749
|
+
if (task?.state === "running")
|
|
750
|
+
this.publishTask(nativeId, { ...task, state: "stopped", endedAt: Date.now(), canStop: false });
|
|
751
|
+
}
|
|
752
|
+
finally {
|
|
753
|
+
this.stoppingTasks.delete(key);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
653
756
|
cancelRelease(threadId) {
|
|
654
757
|
clearTimeout(this.releases.get(threadId));
|
|
655
758
|
this.releases.delete(threadId);
|
|
@@ -710,6 +813,17 @@ export class CodexDriver {
|
|
|
710
813
|
}
|
|
711
814
|
/** Nests each sub-agent's own history right after the call that spawned it. */
|
|
712
815
|
async withSubAgents(threadId, thread, history) {
|
|
816
|
+
// Restore the last surface across idle turns and history windows.
|
|
817
|
+
outer: for (const turn of [...(thread.turns ?? [])].reverse()) {
|
|
818
|
+
for (const item of [...turn.items].reverse()) {
|
|
819
|
+
const stamp = turn.completedAt ?? turn.startedAt ?? thread.updatedAt;
|
|
820
|
+
const frame = codexPreview(item, stamp < 1e12 ? stamp * 1000 : stamp);
|
|
821
|
+
if (frame) {
|
|
822
|
+
this.host?.preview?.(this.id, threadId, frame);
|
|
823
|
+
break outer;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
713
827
|
const spawns = new Map();
|
|
714
828
|
for (const turn of thread.turns ?? []) {
|
|
715
829
|
for (const item of turn.items) {
|
|
@@ -752,6 +866,9 @@ export class CodexDriver {
|
|
|
752
866
|
});
|
|
753
867
|
}
|
|
754
868
|
async detach(nativeId) {
|
|
869
|
+
clearTimeout(this.taskPolls.get(nativeId));
|
|
870
|
+
this.taskPolls.delete(nativeId);
|
|
871
|
+
this.taskProcesses.delete(nativeId);
|
|
755
872
|
this.cancelRelease(nativeId);
|
|
756
873
|
this.stopObserving(nativeId);
|
|
757
874
|
if (!this.attached.delete(nativeId))
|
|
@@ -774,6 +891,61 @@ export class CodexDriver {
|
|
|
774
891
|
*/
|
|
775
892
|
async runCommand(nativeId, command, clientMessageId) {
|
|
776
893
|
const echo = () => this.host?.update(this.id, nativeId, { sessionUpdate: "user_message_chunk", messageId: `local-${clientMessageId}`, content: { type: "text", text: command.text } }, `command:${clientMessageId}`);
|
|
894
|
+
if (command.name === "goal") {
|
|
895
|
+
const args = command.args;
|
|
896
|
+
const change = !args ? { action: "get" }
|
|
897
|
+
: args === "pause" || args === "resume" || args === "clear" ? { action: args }
|
|
898
|
+
: { action: "set", objective: args.replace(/^edit\s+/, "") };
|
|
899
|
+
if (args === "edit")
|
|
900
|
+
throw RpcError.app("invalid_params", "请在 /goal edit 后写上新的目标,或打开目标面板编辑");
|
|
901
|
+
const goal = await this.goal(nativeId, change);
|
|
902
|
+
echo();
|
|
903
|
+
this.host?.update(this.id, nativeId, { sessionUpdate: "ls_notice", level: "info", title: goal ? `目标:${goal.objective}` : "当前没有目标" });
|
|
904
|
+
return "started";
|
|
905
|
+
}
|
|
906
|
+
if (command.name === "reload-skills") {
|
|
907
|
+
this.skillsRevision++;
|
|
908
|
+
this.skills.delete(this.cwds.get(nativeId) ?? "");
|
|
909
|
+
await this.loadSkills(this.cwds.get(nativeId), true);
|
|
910
|
+
await this.announceCommands(nativeId);
|
|
911
|
+
echo();
|
|
912
|
+
this.host?.update(this.id, nativeId, { sessionUpdate: "ls_notice", level: "info", title: "已刷新可用技能" });
|
|
913
|
+
return "started";
|
|
914
|
+
}
|
|
915
|
+
if (["status", "mcp", "apps", "ps", "stop"].includes(command.name)) {
|
|
916
|
+
if (command.args)
|
|
917
|
+
throw RpcError.app("invalid_params", `/${command.name} 暂不接受参数`);
|
|
918
|
+
const lines = [];
|
|
919
|
+
if (command.name === "status") {
|
|
920
|
+
const { thread } = await this.rpcFor(nativeId, "thread/read", { threadId: nativeId, includeTurns: false });
|
|
921
|
+
const current = effective(this.settings.get(nativeId) ?? {}, this.overrides.get(nativeId) ?? {}, await this.loadModels());
|
|
922
|
+
const running = this.observed.get(nativeId)?.running ?? Boolean(this.stateOf(nativeId).activeTurnId);
|
|
923
|
+
lines.push(`目录:${thread.cwd}`, `模型:${current.model ?? "默认"}`, `推理强度:${current.effort ?? "默认"}`, `状态:${running ? "运行中" : "空闲"}`);
|
|
924
|
+
}
|
|
925
|
+
else if (command.name === "stop") {
|
|
926
|
+
await this.rpcFor(nativeId, "thread/backgroundTerminals/clean", { threadId: nativeId });
|
|
927
|
+
lines.push("已停止当前会话的后台终端");
|
|
928
|
+
}
|
|
929
|
+
else {
|
|
930
|
+
const method = command.name === "mcp" ? "mcpServerStatus/list" : command.name === "apps" ? "app/list" : "thread/backgroundTerminals/list";
|
|
931
|
+
let cursor;
|
|
932
|
+
const seen = new Set();
|
|
933
|
+
do {
|
|
934
|
+
const page = await this.rpcFor(nativeId, method, { threadId: nativeId, limit: 100, ...(cursor ? { cursor } : {}) });
|
|
935
|
+
for (const entry of page.data) {
|
|
936
|
+
lines.push(command.name === "ps" ? `${entry.processId ?? ""} · ${entry.command ?? "后台终端"}` : command.name === "mcp" ? `${entry.name ?? "MCP"} · ${Object.keys(entry.tools ?? {}).length} 个工具 · ${entry.authStatus ?? ""}` : `${entry.name ?? "应用"} · ${entry.isEnabled ? "已启用" : "未启用"}`);
|
|
937
|
+
}
|
|
938
|
+
cursor = page.nextCursor ?? undefined;
|
|
939
|
+
if (cursor && seen.has(cursor))
|
|
940
|
+
throw RpcError.app("invalid_params", "Agent 返回了重复的分页游标,请重试");
|
|
941
|
+
if (cursor)
|
|
942
|
+
seen.add(cursor);
|
|
943
|
+
} while (cursor);
|
|
944
|
+
}
|
|
945
|
+
echo();
|
|
946
|
+
this.host?.update(this.id, nativeId, { sessionUpdate: "ls_notice", level: "info", title: `/${command.name}`, detail: lines.join("\n") || "当前没有记录" });
|
|
947
|
+
return "started";
|
|
948
|
+
}
|
|
777
949
|
if (command.name === "compact" || command.name === "review") {
|
|
778
950
|
// Not something a queue can carry: they run in the app-server that has the thread.
|
|
779
951
|
if (this.observed.has(nativeId))
|
|
@@ -800,7 +972,7 @@ export class CodexDriver {
|
|
|
800
972
|
}
|
|
801
973
|
const skill = (await this.loadSkills(this.cwds.get(nativeId))).find((entry) => entry.name === command.name);
|
|
802
974
|
if (!skill)
|
|
803
|
-
|
|
975
|
+
throw RpcError.app("not_supported", `当前 Codex 未提供 /${command.name}。请从命令面板选择可用命令。`);
|
|
804
976
|
// The way the TUI sends a skill: the skill itself, and `$name` in the text.
|
|
805
977
|
return this.send(nativeId, [
|
|
806
978
|
{ type: "skill", name: skill.name, path: skill.path },
|
|
@@ -837,6 +1009,41 @@ export class CodexDriver {
|
|
|
837
1009
|
});
|
|
838
1010
|
return "started";
|
|
839
1011
|
}
|
|
1012
|
+
async goal(nativeId, change) {
|
|
1013
|
+
if (this.observed.has(nativeId) && change.action !== "get")
|
|
1014
|
+
throw this.refused(nativeId, "会话开在电脑的另一个 Codex 里 · 暂时只能查看目标", HELD_COMMAND);
|
|
1015
|
+
const method = change.action === "get" ? "thread/goal/get" : change.action === "clear" ? "thread/goal/clear" : "thread/goal/set";
|
|
1016
|
+
let status = "active";
|
|
1017
|
+
if (change.action === "set") {
|
|
1018
|
+
const current = await this.rpcFor(nativeId, "thread/goal/get", { threadId: nativeId });
|
|
1019
|
+
// Editing a paused goal must not silently restart work. This matches the
|
|
1020
|
+
// native editor; finished or exhausted goals start afresh when edited.
|
|
1021
|
+
if (current.goal && ["paused", "blocked", "usageLimited"].includes(current.goal.status))
|
|
1022
|
+
status = current.goal.status;
|
|
1023
|
+
}
|
|
1024
|
+
const params = change.action === "set"
|
|
1025
|
+
? { threadId: nativeId, objective: change.objective, status, ...(change.tokenBudget === undefined ? {} : { tokenBudget: change.tokenBudget }) }
|
|
1026
|
+
: { threadId: nativeId, ...(change.action === "pause" ? { status: "paused" } : change.action === "resume" ? { status: "active" } : {}) };
|
|
1027
|
+
const revision = this.goalRevision.get(nativeId) ?? 0;
|
|
1028
|
+
const result = await this.rpcFor(nativeId, method, params);
|
|
1029
|
+
const goal = change.action === "clear" || result.goal == null ? null : sessionGoalSchema.parse(result.goal);
|
|
1030
|
+
this.goalAvailable.add(nativeId);
|
|
1031
|
+
// A live update can overtake a snapshot request. Never overwrite it with
|
|
1032
|
+
// the older response (especially a null read from just before /goal set).
|
|
1033
|
+
if ((this.goalRevision.get(nativeId) ?? 0) === revision && this.isNews(`goal:${nativeId}`, goal))
|
|
1034
|
+
this.host?.update(this.id, nativeId, { sessionUpdate: "ls_goal", goal });
|
|
1035
|
+
return goal;
|
|
1036
|
+
}
|
|
1037
|
+
async announceGoal(nativeId) {
|
|
1038
|
+
try {
|
|
1039
|
+
await this.goal(nativeId, { action: "get" });
|
|
1040
|
+
await this.announceCommands(nativeId);
|
|
1041
|
+
}
|
|
1042
|
+
catch (error) {
|
|
1043
|
+
// Older Codex builds do not implement Goals; ordinary sessions still work.
|
|
1044
|
+
this.host?.log(`[codex] goal unavailable: ${error instanceof Error ? error.message : String(error)}`);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
840
1047
|
/** Model, reasoning effort and permissions apply from the next turn on. */
|
|
841
1048
|
async setConfig(nativeId, optionId, value) {
|
|
842
1049
|
const models = await this.loadModels();
|
|
@@ -897,15 +1104,18 @@ export class CodexDriver {
|
|
|
897
1104
|
this.announced.set(key, text);
|
|
898
1105
|
return true;
|
|
899
1106
|
}
|
|
900
|
-
loadSkills(cwd) {
|
|
1107
|
+
loadSkills(cwd, forceReload = false) {
|
|
901
1108
|
const key = cwd ?? "";
|
|
902
1109
|
let loading = this.skills.get(key);
|
|
903
1110
|
if (!loading) {
|
|
904
|
-
loading = this.rpc("skills/list", cwd ? { cwds: [cwd] } : {})
|
|
1111
|
+
loading = this.rpc("skills/list", { ...(cwd ? { cwds: [cwd] } : {}), ...(forceReload ? { forceReload } : {}) })
|
|
905
1112
|
.then((result) => result.data.flatMap((entry) => entry.skills ?? []).filter((skill) => skill.enabled !== false && skill.name && skill.path))
|
|
906
1113
|
.catch((error) => {
|
|
907
|
-
this.skills.
|
|
1114
|
+
if (this.skills.get(key) === loading)
|
|
1115
|
+
this.skills.delete(key);
|
|
908
1116
|
this.host?.log(`[codex] skills/list failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1117
|
+
if (forceReload)
|
|
1118
|
+
throw error;
|
|
909
1119
|
return [];
|
|
910
1120
|
});
|
|
911
1121
|
this.skills.set(key, loading);
|
|
@@ -914,10 +1124,19 @@ export class CodexDriver {
|
|
|
914
1124
|
}
|
|
915
1125
|
/** What `/` offers on a device: the commands above, then the skills this project can use. */
|
|
916
1126
|
async announceCommands(nativeId) {
|
|
1127
|
+
// Built-ins must be usable even while skill discovery is slow or unavailable.
|
|
1128
|
+
if (!this.announced.has(`commands:${nativeId}`)) {
|
|
1129
|
+
this.isNews(`commands:${nativeId}`, COMMANDS);
|
|
1130
|
+
this.host?.update(this.id, nativeId, { sessionUpdate: "available_commands_update", availableCommands: COMMANDS });
|
|
1131
|
+
}
|
|
1132
|
+
const revision = this.skillsRevision;
|
|
917
1133
|
const skills = await this.loadSkills(this.cwds.get(nativeId));
|
|
1134
|
+
if (revision !== this.skillsRevision)
|
|
1135
|
+
return;
|
|
918
1136
|
const taken = new Set(COMMANDS.map((command) => command.name));
|
|
919
1137
|
const availableCommands = [
|
|
920
1138
|
...COMMANDS,
|
|
1139
|
+
...(this.goalAvailable.has(nativeId) ? [{ name: "goal", description: "设置、查看、暂停、继续或清除持续目标", hint: "目标 / pause / resume / clear" }] : []),
|
|
921
1140
|
...skills
|
|
922
1141
|
.filter((skill) => !taken.has(skill.name))
|
|
923
1142
|
.map((skill) => ({
|
|
@@ -1061,6 +1280,7 @@ export class CodexDriver {
|
|
|
1061
1280
|
// (What is joined in Codex's background server is still there.)
|
|
1062
1281
|
if (this.inShared.has(threadId))
|
|
1063
1282
|
continue;
|
|
1283
|
+
this.loseTasks(threadId);
|
|
1064
1284
|
this.attached.delete(threadId);
|
|
1065
1285
|
this.threads.delete(threadId);
|
|
1066
1286
|
this.host?.update(this.id, threadId, { sessionUpdate: "ls_status", state: "offline" });
|
|
@@ -1099,6 +1319,23 @@ export class CodexDriver {
|
|
|
1099
1319
|
return state;
|
|
1100
1320
|
}
|
|
1101
1321
|
onNotification(method, params, from) {
|
|
1322
|
+
if (method === "skills/changed") {
|
|
1323
|
+
this.skillsRevision++;
|
|
1324
|
+
this.skills.clear();
|
|
1325
|
+
for (const id of this.attached)
|
|
1326
|
+
void this.announceCommands(id);
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
if (method === "thread/goal/updated" || method === "thread/goal/cleared") {
|
|
1330
|
+
const id = params?.threadId;
|
|
1331
|
+
if (id) {
|
|
1332
|
+
this.goalRevision.set(id, (this.goalRevision.get(id) ?? 0) + 1);
|
|
1333
|
+
if (this.attached.has(id) && !this.goalAvailable.has(id)) {
|
|
1334
|
+
this.goalAvailable.add(id);
|
|
1335
|
+
void this.announceCommands(id);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1102
1339
|
if (method === "thread/deleted") {
|
|
1103
1340
|
// Deleted in the TUI or another client.
|
|
1104
1341
|
const threadId = params?.threadId;
|
|
@@ -1139,10 +1376,26 @@ export class CodexDriver {
|
|
|
1139
1376
|
return;
|
|
1140
1377
|
}
|
|
1141
1378
|
this.noteSpawns(params);
|
|
1379
|
+
if (method === "item/completed" && typeof threadId === "string") {
|
|
1380
|
+
const item = params.item;
|
|
1381
|
+
const task = this.host?.tasks(this.id, threadId).find((task) => task.id === item?.id);
|
|
1382
|
+
if (task && task.state === "running") {
|
|
1383
|
+
this.taskRevisions.set(threadId, (this.taskRevisions.get(threadId) ?? 0) + 1);
|
|
1384
|
+
const stopped = this.stoppingTasks.delete(`${threadId}:${task.id}`);
|
|
1385
|
+
this.publishTask(threadId, { ...task, state: stopped ? "stopped" : item?.exitCode === 0 ? "completed" : item?.exitCode != null || item?.status === "failed" ? "failed" : "unknown", endedAt: Date.now(), exitCode: item?.exitCode ?? undefined, canStop: false });
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
if (method === "item/completed" && typeof threadId === "string") {
|
|
1389
|
+
const frame = codexPreview(params.item);
|
|
1390
|
+
if (frame)
|
|
1391
|
+
this.host?.preview?.(this.id, threadId, frame);
|
|
1392
|
+
}
|
|
1142
1393
|
for (const mapped of mapNotification(method, params, (id) => this.stateOf(id))) {
|
|
1143
1394
|
const update = from === "shared" && mapped.update.sessionUpdate === "ls_permission_resolved"
|
|
1144
1395
|
? { ...mapped.update, requestId: sharedRequestId(mapped.update.requestId) }
|
|
1145
1396
|
: mapped.update;
|
|
1397
|
+
if (update.sessionUpdate === "ls_goal" && !this.isNews(`goal:${mapped.threadId}`, update.goal))
|
|
1398
|
+
continue;
|
|
1146
1399
|
if (update.sessionUpdate === "tool_call")
|
|
1147
1400
|
this.rememberTitle(update.toolCallId, update.title);
|
|
1148
1401
|
if (update.sessionUpdate === "ls_permission_resolved") {
|
|
@@ -1171,8 +1424,10 @@ export class CodexDriver {
|
|
|
1171
1424
|
continue;
|
|
1172
1425
|
if (update.state === "started")
|
|
1173
1426
|
this.fresh.delete(mapped.threadId);
|
|
1174
|
-
else
|
|
1427
|
+
else {
|
|
1428
|
+
void this.syncTasks(mapped.threadId);
|
|
1175
1429
|
this.considerRelease(mapped.threadId);
|
|
1430
|
+
}
|
|
1176
1431
|
}
|
|
1177
1432
|
}
|
|
1178
1433
|
/** Remembers which spawnAgent call each new sub-agent thread belongs to. */
|
|
@@ -1247,6 +1502,7 @@ export class CodexDriver {
|
|
|
1247
1502
|
const joined = [...this.inShared].filter((threadId) => this.attached.delete(threadId));
|
|
1248
1503
|
this.inShared.clear();
|
|
1249
1504
|
for (const threadId of joined) {
|
|
1505
|
+
this.loseTasks(threadId);
|
|
1250
1506
|
const turnId = this.stateOf(threadId).activeTurnId;
|
|
1251
1507
|
this.threads.delete(threadId);
|
|
1252
1508
|
// Whether the turn goes on is told again when the thread is joined again.
|