doer-agent 0.2.6 → 0.2.7
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/agent.js +106 -237
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -9,16 +9,13 @@ const AGENT_MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
|
9
9
|
const AGENT_PROJECT_DIR = path.join(AGENT_MODULE_DIR, "..");
|
|
10
10
|
const AGENT_PACKAGE_JSON_PATH = path.join(AGENT_PROJECT_DIR, "package.json");
|
|
11
11
|
let activeTaskLogContext = null;
|
|
12
|
-
const activeTaskCancelRequests = new Map();
|
|
13
12
|
let workspaceRootOverride = null;
|
|
14
13
|
const fsRpcCodec = StringCodec();
|
|
15
|
-
const shellRpcCodec = StringCodec();
|
|
16
14
|
const runRpcCodec = StringCodec();
|
|
17
15
|
const sessionRpcCodec = StringCodec();
|
|
18
16
|
const codexAuthRpcCodec = StringCodec();
|
|
19
17
|
const settingsRpcCodec = StringCodec();
|
|
20
18
|
const gitRpcCodec = StringCodec();
|
|
21
|
-
const activeRuns = new Map();
|
|
22
19
|
const retainedRuns = new Map();
|
|
23
20
|
const activeSessionWatchers = new Map();
|
|
24
21
|
const sessionLineIndexCache = new Map();
|
|
@@ -466,10 +463,13 @@ async function persistRunTask(task) {
|
|
|
466
463
|
runId: task.id,
|
|
467
464
|
agentId: task.agentId,
|
|
468
465
|
userId: task.userId,
|
|
466
|
+
processPid: task.processPid,
|
|
469
467
|
sessionId: task.sessionId,
|
|
470
468
|
sessionFilePath: task.sessionFilePath,
|
|
471
469
|
status: task.status,
|
|
472
470
|
cancelRequested: task.cancelRequested,
|
|
471
|
+
resultExitCode: task.resultExitCode,
|
|
472
|
+
resultSignal: task.resultSignal,
|
|
473
473
|
createdAt: task.createdAt,
|
|
474
474
|
updatedAt: task.updatedAt,
|
|
475
475
|
startedAt: task.startedAt,
|
|
@@ -1020,10 +1020,71 @@ async function updateRunSessionMetadata(task, metadata) {
|
|
|
1020
1020
|
function persistRetainedRun(task) {
|
|
1021
1021
|
retainedRuns.set(task.id, cloneRunTask(task));
|
|
1022
1022
|
}
|
|
1023
|
-
function
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1023
|
+
function normalizePersistedRunTask(value) {
|
|
1024
|
+
if (!value || typeof value !== "object") {
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
const record = value;
|
|
1028
|
+
const id = typeof record.runId === "string" && record.runId.trim()
|
|
1029
|
+
? record.runId.trim()
|
|
1030
|
+
: typeof record.id === "string" && record.id.trim()
|
|
1031
|
+
? record.id.trim()
|
|
1032
|
+
: "";
|
|
1033
|
+
const userId = typeof record.userId === "string" ? record.userId : "";
|
|
1034
|
+
const agentId = typeof record.agentId === "string" ? record.agentId : "";
|
|
1035
|
+
const status = record.status;
|
|
1036
|
+
if (!id || !userId || !agentId || !["queued", "running", "completed", "failed", "canceled"].includes(String(status))) {
|
|
1037
|
+
return null;
|
|
1038
|
+
}
|
|
1039
|
+
return {
|
|
1040
|
+
id,
|
|
1041
|
+
userId,
|
|
1042
|
+
agentId,
|
|
1043
|
+
processPid: typeof record.processPid === "number" ? record.processPid : null,
|
|
1044
|
+
sessionId: typeof record.sessionId === "string" && record.sessionId.trim() ? record.sessionId.trim() : null,
|
|
1045
|
+
sessionFilePath: typeof record.sessionFilePath === "string" && record.sessionFilePath.trim() ? record.sessionFilePath.trim() : null,
|
|
1046
|
+
status: status,
|
|
1047
|
+
cancelRequested: Boolean(record.cancelRequested),
|
|
1048
|
+
resultExitCode: typeof record.resultExitCode === "number" ? record.resultExitCode : null,
|
|
1049
|
+
resultSignal: typeof record.resultSignal === "string" && record.resultSignal.trim() ? record.resultSignal.trim() : null,
|
|
1050
|
+
error: typeof record.error === "string" && record.error.trim() ? record.error : null,
|
|
1051
|
+
createdAt: typeof record.createdAt === "string" ? record.createdAt : "",
|
|
1052
|
+
updatedAt: typeof record.updatedAt === "string" ? record.updatedAt : "",
|
|
1053
|
+
startedAt: typeof record.startedAt === "string" && record.startedAt.trim() ? record.startedAt : null,
|
|
1054
|
+
finishedAt: typeof record.finishedAt === "string" && record.finishedAt.trim() ? record.finishedAt : null,
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
async function listPersistedRunTasks() {
|
|
1058
|
+
const dir = await resolveRunsDir();
|
|
1059
|
+
const names = await readdir(dir).catch(() => []);
|
|
1060
|
+
const tasks = await Promise.all(names
|
|
1061
|
+
.filter((name) => name.endsWith(".json"))
|
|
1062
|
+
.map(async (name) => {
|
|
1063
|
+
const raw = await readFile(path.join(dir, name), "utf8").catch(() => null);
|
|
1064
|
+
if (!raw) {
|
|
1065
|
+
return null;
|
|
1066
|
+
}
|
|
1067
|
+
try {
|
|
1068
|
+
return normalizePersistedRunTask(JSON.parse(raw));
|
|
1069
|
+
}
|
|
1070
|
+
catch {
|
|
1071
|
+
return null;
|
|
1072
|
+
}
|
|
1073
|
+
}));
|
|
1074
|
+
return tasks.filter((task) => task !== null);
|
|
1075
|
+
}
|
|
1076
|
+
async function getStoredRun(runId) {
|
|
1077
|
+
const persisted = await readFile(path.join(await resolveRunsDir(), `${runId}.json`), "utf8").catch(() => null);
|
|
1078
|
+
if (persisted) {
|
|
1079
|
+
try {
|
|
1080
|
+
const parsed = normalizePersistedRunTask(JSON.parse(persisted));
|
|
1081
|
+
if (parsed) {
|
|
1082
|
+
return parsed;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
catch {
|
|
1086
|
+
// Ignore malformed persisted state and fall back to retained memory.
|
|
1087
|
+
}
|
|
1027
1088
|
}
|
|
1028
1089
|
return retainedRuns.get(runId) ?? null;
|
|
1029
1090
|
}
|
|
@@ -1045,6 +1106,7 @@ async function startManagedRun(args) {
|
|
|
1045
1106
|
id: args.runId,
|
|
1046
1107
|
userId: args.userId,
|
|
1047
1108
|
agentId: args.agentId,
|
|
1109
|
+
processPid: typeof child.pid === "number" ? child.pid : null,
|
|
1048
1110
|
sessionId: typeof args.sessionId === "string" && args.sessionId.trim() ? args.sessionId.trim() : null,
|
|
1049
1111
|
sessionFilePath: null,
|
|
1050
1112
|
status: "running",
|
|
@@ -1057,17 +1119,6 @@ async function startManagedRun(args) {
|
|
|
1057
1119
|
startedAt: now,
|
|
1058
1120
|
finishedAt: null,
|
|
1059
1121
|
};
|
|
1060
|
-
const cancellation = createManagedCancellation(child);
|
|
1061
|
-
const requestCancel = () => {
|
|
1062
|
-
if (task.status === "completed" || task.status === "failed" || task.status === "canceled") {
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1065
|
-
task.cancelRequested = true;
|
|
1066
|
-
task.updatedAt = formatLocalTimestamp();
|
|
1067
|
-
void persistRunTask(task).catch(() => undefined);
|
|
1068
|
-
writeRunStatus(task.id, "cancel requested");
|
|
1069
|
-
cancellation.requestCancel();
|
|
1070
|
-
};
|
|
1071
1122
|
let stdoutBuffer = "";
|
|
1072
1123
|
const recordChunk = (stream, chunk) => {
|
|
1073
1124
|
writeRunStream(task.id, stream, chunk);
|
|
@@ -1096,33 +1147,33 @@ async function startManagedRun(args) {
|
|
|
1096
1147
|
task.error = message;
|
|
1097
1148
|
task.finishedAt = formatLocalTimestamp();
|
|
1098
1149
|
persistRetainedRun(task);
|
|
1099
|
-
activeRuns.delete(task.id);
|
|
1100
1150
|
void removeRunTask(task.id).catch(() => undefined);
|
|
1101
1151
|
void releaseRunStartSlot({ runId: task.id, sessionId: task.sessionId }).catch(() => undefined);
|
|
1102
1152
|
void prepared.codexAuthCleanup().catch(() => undefined);
|
|
1103
1153
|
writeRunStatus(task.id, `failed error=${message}`);
|
|
1104
1154
|
});
|
|
1105
|
-
child.once("close", (code, signal) => {
|
|
1106
|
-
cancellation.clear();
|
|
1155
|
+
child.once("close", async (code, signal) => {
|
|
1107
1156
|
if (stdoutBuffer.trim() && (!task.sessionId || !task.sessionFilePath)) {
|
|
1108
1157
|
const metadata = extractCodexSessionMetadata(stdoutBuffer.trim());
|
|
1109
1158
|
if (metadata.sessionId || metadata.sessionFilePath) {
|
|
1110
1159
|
void updateRunSessionMetadata(task, metadata);
|
|
1111
1160
|
}
|
|
1112
1161
|
}
|
|
1162
|
+
const latest = await getStoredRun(task.id).catch(() => null);
|
|
1163
|
+
if (latest?.cancelRequested) {
|
|
1164
|
+
task.cancelRequested = true;
|
|
1165
|
+
}
|
|
1113
1166
|
task.resultExitCode = typeof code === "number" ? code : null;
|
|
1114
1167
|
task.resultSignal = signal;
|
|
1115
1168
|
task.finishedAt = formatLocalTimestamp();
|
|
1116
1169
|
task.status = task.cancelRequested ? "canceled" : (task.resultExitCode ?? 1) === 0 ? "completed" : "failed";
|
|
1117
1170
|
task.error = task.status === "failed" ? `Command exited with code ${task.resultExitCode ?? "null"}` : null;
|
|
1118
1171
|
persistRetainedRun(task);
|
|
1119
|
-
activeRuns.delete(task.id);
|
|
1120
1172
|
void removeRunTask(task.id).catch(() => undefined);
|
|
1121
1173
|
void releaseRunStartSlot({ runId: task.id, sessionId: task.sessionId }).catch(() => undefined);
|
|
1122
1174
|
void prepared.codexAuthCleanup().catch(() => undefined);
|
|
1123
1175
|
writeRunStatus(task.id, `completed status=${task.status} exitCode=${task.resultExitCode ?? "null"} signal=${task.resultSignal ?? "null"}`);
|
|
1124
1176
|
});
|
|
1125
|
-
activeRuns.set(task.id, { task, child, requestCancel });
|
|
1126
1177
|
persistRetainedRun(task);
|
|
1127
1178
|
void persistRunTask(task).catch(() => undefined);
|
|
1128
1179
|
writeRunStatus(task.id, `started requestId=${args.requestId} cwd=${prepared.taskWorkspace}`);
|
|
@@ -1935,22 +1986,37 @@ async function handleRunRpcMessage(args) {
|
|
|
1935
1986
|
return;
|
|
1936
1987
|
}
|
|
1937
1988
|
if (request.action === "list") {
|
|
1938
|
-
const
|
|
1939
|
-
const
|
|
1940
|
-
const
|
|
1989
|
+
const persisted = await listPersistedRunTasks();
|
|
1990
|
+
const mergedById = new Map();
|
|
1991
|
+
for (const task of persisted) {
|
|
1992
|
+
mergedById.set(task.id, cloneRunTask(task));
|
|
1993
|
+
}
|
|
1994
|
+
for (const task of retainedRuns.values()) {
|
|
1995
|
+
if (!mergedById.has(task.id)) {
|
|
1996
|
+
mergedById.set(task.id, cloneRunTask(task));
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
const merged = [...mergedById.values()]
|
|
1941
2000
|
.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt))
|
|
1942
2001
|
.slice(0, request.limit);
|
|
1943
2002
|
publishRunRpcResponse({ nc: args.jetstream.nc, responseSubject, payload: { requestId, ok: true, tasks: merged } });
|
|
1944
2003
|
return;
|
|
1945
2004
|
}
|
|
1946
|
-
const stored = request.runId ? getStoredRun(request.runId) : null;
|
|
2005
|
+
const stored = request.runId ? await getStoredRun(request.runId) : null;
|
|
1947
2006
|
if (!stored || stored.agentId !== args.agentId || stored.userId !== args.userId) {
|
|
1948
2007
|
throw new Error("Run not found");
|
|
1949
2008
|
}
|
|
1950
2009
|
if (request.action === "cancel") {
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
|
|
2010
|
+
const target = stored;
|
|
2011
|
+
if (target.processPid === null) {
|
|
2012
|
+
throw new Error("Run pid not found");
|
|
2013
|
+
}
|
|
2014
|
+
target.cancelRequested = true;
|
|
2015
|
+
target.updatedAt = formatLocalTimestamp();
|
|
2016
|
+
await persistRunTask(target);
|
|
2017
|
+
writeRunStatus(target.id, `cancel requested pid=${target.processPid}`);
|
|
2018
|
+
sendSignalToPid(target.processPid, "SIGINT");
|
|
2019
|
+
const task = cloneRunTask(target);
|
|
1954
2020
|
publishRunRpcResponse({ nc: args.jetstream.nc, responseSubject, payload: { requestId, ok: true, task } });
|
|
1955
2021
|
return;
|
|
1956
2022
|
}
|
|
@@ -2026,21 +2092,17 @@ function sendSignalToTaskProcess(child, signal) {
|
|
|
2026
2092
|
// noop
|
|
2027
2093
|
}
|
|
2028
2094
|
}
|
|
2029
|
-
function
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
}
|
|
2039
|
-
catch (error) {
|
|
2040
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2041
|
-
writeAgentError(`task cancel request failed taskId=${taskId} via=${reason}: ${message}`);
|
|
2042
|
-
return false;
|
|
2095
|
+
function sendSignalToPid(pid, signal) {
|
|
2096
|
+
if (process.platform !== "win32") {
|
|
2097
|
+
try {
|
|
2098
|
+
process.kill(-pid, signal);
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
catch {
|
|
2102
|
+
// Fall back to direct pid signaling.
|
|
2103
|
+
}
|
|
2043
2104
|
}
|
|
2105
|
+
process.kill(pid, signal);
|
|
2044
2106
|
}
|
|
2045
2107
|
function resolveLogTimeZone() {
|
|
2046
2108
|
const configured = process.env.DOER_AGENT_LOG_TIMEZONE?.trim() || process.env.TZ?.trim();
|
|
@@ -2172,9 +2234,6 @@ function resolveTaskWorkspace(rawCwd) {
|
|
|
2172
2234
|
function buildAgentFsRpcSubject(userId, agentId) {
|
|
2173
2235
|
return `doer.agent.fs.rpc.${sanitizeUserId(userId)}.${agentId.trim()}`;
|
|
2174
2236
|
}
|
|
2175
|
-
function buildAgentShellRpcSubject(userId, agentId) {
|
|
2176
|
-
return `doer.agent.shell.rpc.${sanitizeUserId(userId)}.${agentId.trim()}`;
|
|
2177
|
-
}
|
|
2178
2237
|
function normalizeFsRpcPath(rawPath) {
|
|
2179
2238
|
const root = workspaceRootOverride ?? (process.env.WORKSPACE?.trim() || process.cwd());
|
|
2180
2239
|
const raw = typeof rawPath === "string" && rawPath.trim() ? rawPath.trim() : ".";
|
|
@@ -3188,46 +3247,6 @@ function subscribeToFsRpc(args) {
|
|
|
3188
3247
|
});
|
|
3189
3248
|
writeAgentInfo(`fs rpc subscribed subject=${subject}`);
|
|
3190
3249
|
}
|
|
3191
|
-
function normalizeShellRpcRequest(args) {
|
|
3192
|
-
const requestId = typeof args.request.requestId === "string" ? args.request.requestId.trim() : "";
|
|
3193
|
-
if (!requestId) {
|
|
3194
|
-
throw new Error("missing requestId");
|
|
3195
|
-
}
|
|
3196
|
-
const requestAgentId = typeof args.request.agentId === "string" ? args.request.agentId.trim() : "";
|
|
3197
|
-
if (!requestAgentId) {
|
|
3198
|
-
throw new Error("missing agentId");
|
|
3199
|
-
}
|
|
3200
|
-
if (requestAgentId !== args.agentId) {
|
|
3201
|
-
throw new Error("agent id mismatch");
|
|
3202
|
-
}
|
|
3203
|
-
const kind = args.request.kind === "apply_patch" ? "apply_patch" : "shell";
|
|
3204
|
-
const command = typeof args.request.command === "string" ? args.request.command.trim() : "";
|
|
3205
|
-
const patch = typeof args.request.patch === "string" ? args.request.patch : "";
|
|
3206
|
-
if (kind === "shell" && !command) {
|
|
3207
|
-
throw new Error("missing command");
|
|
3208
|
-
}
|
|
3209
|
-
if (kind === "apply_patch" && !patch.trim()) {
|
|
3210
|
-
throw new Error("missing patch");
|
|
3211
|
-
}
|
|
3212
|
-
const responseSubject = typeof args.request.responseSubject === "string" ? args.request.responseSubject.trim() : "";
|
|
3213
|
-
if (!responseSubject) {
|
|
3214
|
-
throw new Error("missing responseSubject");
|
|
3215
|
-
}
|
|
3216
|
-
const cwd = typeof args.request.cwd === "string" && args.request.cwd.trim() ? args.request.cwd.trim() : null;
|
|
3217
|
-
const timeoutRaw = Number(args.request.timeoutMs);
|
|
3218
|
-
const timeoutMs = Number.isFinite(timeoutRaw) ? Math.max(1000, Math.min(Math.floor(timeoutRaw), 300000)) : 30000;
|
|
3219
|
-
return {
|
|
3220
|
-
kind,
|
|
3221
|
-
requestId,
|
|
3222
|
-
command: kind === "shell" ? command : null,
|
|
3223
|
-
patch: kind === "apply_patch" ? patch : null,
|
|
3224
|
-
cwd,
|
|
3225
|
-
timeoutMs,
|
|
3226
|
-
responseSubject,
|
|
3227
|
-
runtimeEnvPatch: normalizeEnvPatch(args.request.runtimeEnvPatch),
|
|
3228
|
-
codexAuthBundle: normalizeShellRpcCodexAuthBundle(args.request.codexAuth),
|
|
3229
|
-
};
|
|
3230
|
-
}
|
|
3231
3250
|
function normalizeShellRpcCodexAuthBundle(value) {
|
|
3232
3251
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3233
3252
|
return null;
|
|
@@ -3246,118 +3265,6 @@ function normalizeShellRpcCodexAuthBundle(value) {
|
|
|
3246
3265
|
apiKey: typeof row.apiKey === "string" || row.apiKey === null ? row.apiKey : undefined,
|
|
3247
3266
|
};
|
|
3248
3267
|
}
|
|
3249
|
-
function publishShellRpcResponse(args) {
|
|
3250
|
-
args.nc.publish(args.responseSubject, shellRpcCodec.encode(JSON.stringify(args.payload)));
|
|
3251
|
-
}
|
|
3252
|
-
async function handleShellRpcMessage(args) {
|
|
3253
|
-
let requestId = "unknown";
|
|
3254
|
-
let responseSubject = "";
|
|
3255
|
-
let stdout = "";
|
|
3256
|
-
let stderr = "";
|
|
3257
|
-
try {
|
|
3258
|
-
const payload = JSON.parse(shellRpcCodec.decode(args.msg.data));
|
|
3259
|
-
const request = normalizeShellRpcRequest({ request: payload, agentId: args.agentId });
|
|
3260
|
-
requestId = request.requestId;
|
|
3261
|
-
responseSubject = request.responseSubject;
|
|
3262
|
-
const startedAtMs = Date.now();
|
|
3263
|
-
const prepared = await prepareCommandExecution({
|
|
3264
|
-
cwd: request.cwd,
|
|
3265
|
-
userId: args.userId,
|
|
3266
|
-
taskId: request.requestId,
|
|
3267
|
-
codexAuthBundle: request.codexAuthBundle,
|
|
3268
|
-
});
|
|
3269
|
-
const child = spawnPreparedCommand({
|
|
3270
|
-
kind: request.kind,
|
|
3271
|
-
command: request.command,
|
|
3272
|
-
patch: request.patch,
|
|
3273
|
-
shellPath: prepared.shellPath,
|
|
3274
|
-
taskWorkspace: prepared.taskWorkspace,
|
|
3275
|
-
env: prepared.env,
|
|
3276
|
-
agentToken: args.agentToken,
|
|
3277
|
-
});
|
|
3278
|
-
writeRpcStatus(requestId, `started kind=${request.kind} cwd=${prepared.taskWorkspace} shell=${request.kind === "shell" ? prepared.shellPath : "apply_patch"}`);
|
|
3279
|
-
child.stdout.on("data", (chunk) => {
|
|
3280
|
-
stdout += chunk;
|
|
3281
|
-
writeRpcStream(requestId, "stdout", chunk);
|
|
3282
|
-
});
|
|
3283
|
-
child.stderr.on("data", (chunk) => {
|
|
3284
|
-
stderr += chunk;
|
|
3285
|
-
writeRpcStream(requestId, "stderr", chunk);
|
|
3286
|
-
});
|
|
3287
|
-
let timedOut = false;
|
|
3288
|
-
const timeout = setTimeout(() => {
|
|
3289
|
-
timedOut = true;
|
|
3290
|
-
sendSignalToTaskProcess(child, "SIGTERM");
|
|
3291
|
-
setTimeout(() => {
|
|
3292
|
-
sendSignalToTaskProcess(child, "SIGKILL");
|
|
3293
|
-
}, 1000).unref?.();
|
|
3294
|
-
}, request.timeoutMs);
|
|
3295
|
-
timeout.unref?.();
|
|
3296
|
-
const result = await new Promise((resolve, reject) => {
|
|
3297
|
-
child.once("error", reject);
|
|
3298
|
-
child.once("close", (code, signal) => {
|
|
3299
|
-
resolve({ exitCode: typeof code === "number" ? code : null, signal });
|
|
3300
|
-
});
|
|
3301
|
-
}).finally(() => {
|
|
3302
|
-
clearTimeout(timeout);
|
|
3303
|
-
});
|
|
3304
|
-
await prepared.codexAuthCleanup().catch(() => undefined);
|
|
3305
|
-
publishShellRpcResponse({
|
|
3306
|
-
nc: args.jetstream.nc,
|
|
3307
|
-
responseSubject,
|
|
3308
|
-
payload: {
|
|
3309
|
-
requestId,
|
|
3310
|
-
ok: !timedOut,
|
|
3311
|
-
exitCode: result.exitCode,
|
|
3312
|
-
signal: result.signal,
|
|
3313
|
-
stdout,
|
|
3314
|
-
stderr,
|
|
3315
|
-
...(timedOut ? { error: `Command timed out after ${request.timeoutMs}ms` } : {}),
|
|
3316
|
-
},
|
|
3317
|
-
});
|
|
3318
|
-
writeRpcStatus(requestId, `${timedOut ? "timed_out" : "completed"} exitCode=${result.exitCode ?? "null"} signal=${result.signal ?? "null"} durationMs=${Date.now() - startedAtMs}`);
|
|
3319
|
-
}
|
|
3320
|
-
catch (error) {
|
|
3321
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3322
|
-
if (responseSubject) {
|
|
3323
|
-
publishShellRpcResponse({
|
|
3324
|
-
nc: args.jetstream.nc,
|
|
3325
|
-
responseSubject,
|
|
3326
|
-
payload: {
|
|
3327
|
-
requestId,
|
|
3328
|
-
ok: false,
|
|
3329
|
-
exitCode: null,
|
|
3330
|
-
signal: null,
|
|
3331
|
-
stdout,
|
|
3332
|
-
stderr,
|
|
3333
|
-
error: message,
|
|
3334
|
-
},
|
|
3335
|
-
});
|
|
3336
|
-
}
|
|
3337
|
-
writeRpcStatus(requestId, `failed error=${message}`);
|
|
3338
|
-
writeAgentError(`shell rpc failed requestId=${requestId} error=${message}`);
|
|
3339
|
-
}
|
|
3340
|
-
}
|
|
3341
|
-
function subscribeToShellRpc(args) {
|
|
3342
|
-
const subject = buildAgentShellRpcSubject(args.userId, args.agentId);
|
|
3343
|
-
args.jetstream.nc.subscribe(subject, {
|
|
3344
|
-
callback: (error, msg) => {
|
|
3345
|
-
if (error) {
|
|
3346
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3347
|
-
writeAgentError(`shell rpc subscription error: ${message}`);
|
|
3348
|
-
return;
|
|
3349
|
-
}
|
|
3350
|
-
void handleShellRpcMessage({
|
|
3351
|
-
msg,
|
|
3352
|
-
jetstream: args.jetstream,
|
|
3353
|
-
userId: args.userId,
|
|
3354
|
-
agentId: args.agentId,
|
|
3355
|
-
agentToken: args.agentToken,
|
|
3356
|
-
});
|
|
3357
|
-
},
|
|
3358
|
-
});
|
|
3359
|
-
writeAgentInfo(`shell rpc subscribed subject=${subject}`);
|
|
3360
|
-
}
|
|
3361
3268
|
async function postJson(url, body) {
|
|
3362
3269
|
const res = await fetch(url, {
|
|
3363
3270
|
method: "POST",
|
|
@@ -3605,36 +3512,6 @@ function spawnPreparedCommand(args) {
|
|
|
3605
3512
|
child.stderr.setEncoding("utf8");
|
|
3606
3513
|
return child;
|
|
3607
3514
|
}
|
|
3608
|
-
function createManagedCancellation(child) {
|
|
3609
|
-
let cancelStage1Timer = null;
|
|
3610
|
-
let cancelStage2Timer = null;
|
|
3611
|
-
let cancelSignalSent = false;
|
|
3612
|
-
return {
|
|
3613
|
-
requestCancel: () => {
|
|
3614
|
-
if (cancelSignalSent) {
|
|
3615
|
-
return;
|
|
3616
|
-
}
|
|
3617
|
-
cancelSignalSent = true;
|
|
3618
|
-
sendSignalToTaskProcess(child, "SIGINT");
|
|
3619
|
-
cancelStage1Timer = setTimeout(() => {
|
|
3620
|
-
sendSignalToTaskProcess(child, "SIGTERM");
|
|
3621
|
-
}, 1200);
|
|
3622
|
-
cancelStage1Timer.unref?.();
|
|
3623
|
-
cancelStage2Timer = setTimeout(() => {
|
|
3624
|
-
sendSignalToTaskProcess(child, "SIGKILL");
|
|
3625
|
-
}, 3500);
|
|
3626
|
-
cancelStage2Timer.unref?.();
|
|
3627
|
-
},
|
|
3628
|
-
clear: () => {
|
|
3629
|
-
if (cancelStage1Timer) {
|
|
3630
|
-
clearTimeout(cancelStage1Timer);
|
|
3631
|
-
}
|
|
3632
|
-
if (cancelStage2Timer) {
|
|
3633
|
-
clearTimeout(cancelStage2Timer);
|
|
3634
|
-
}
|
|
3635
|
-
},
|
|
3636
|
-
};
|
|
3637
|
-
}
|
|
3638
3515
|
async function runTask(args) {
|
|
3639
3516
|
activeTaskLogContext = {
|
|
3640
3517
|
jetstream: args.jetstream,
|
|
@@ -3728,7 +3605,6 @@ async function runTask(args) {
|
|
|
3728
3605
|
}, 3500);
|
|
3729
3606
|
cancelStage2Timer.unref?.();
|
|
3730
3607
|
};
|
|
3731
|
-
activeTaskCancelRequests.set(args.taskId, requestCancel);
|
|
3732
3608
|
child.stdout.on("data", (chunk) => {
|
|
3733
3609
|
writeTaskStream(args.taskId, "stdout", chunk);
|
|
3734
3610
|
const seq = reserveNextEventSeq(args.taskId);
|
|
@@ -3823,7 +3699,6 @@ async function runTask(args) {
|
|
|
3823
3699
|
writeAgentInfo(`task=${args.taskId} status=${status} exitCode=${typeof result.code === "number" ? result.code : "null"} signal=${result.signal ?? "null"}`);
|
|
3824
3700
|
}
|
|
3825
3701
|
finally {
|
|
3826
|
-
activeTaskCancelRequests.delete(args.taskId);
|
|
3827
3702
|
activeTaskLogContext = null;
|
|
3828
3703
|
await codexAuth?.cleanup().catch(() => undefined);
|
|
3829
3704
|
}
|
|
@@ -3927,12 +3802,6 @@ async function main() {
|
|
|
3927
3802
|
agentId: initialAgentId,
|
|
3928
3803
|
agentToken,
|
|
3929
3804
|
});
|
|
3930
|
-
subscribeToShellRpc({
|
|
3931
|
-
jetstream,
|
|
3932
|
-
userId,
|
|
3933
|
-
agentId: initialAgentId,
|
|
3934
|
-
agentToken,
|
|
3935
|
-
});
|
|
3936
3805
|
subscribeToSessionRpc({
|
|
3937
3806
|
jetstream,
|
|
3938
3807
|
userId,
|