doer-agent 0.2.0 → 0.2.2
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 +101 -13
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -357,6 +357,20 @@ function writeTaskStream(taskId, stream, chunk) {
|
|
|
357
357
|
function writeTaskUpload(taskId, message) {
|
|
358
358
|
process.stdout.write(`[doer-agent][task=${taskId}][upload] ${message}\n`);
|
|
359
359
|
}
|
|
360
|
+
function writeRpcStream(requestId, stream, chunk) {
|
|
361
|
+
const target = stream === "stdout" ? process.stdout : process.stderr;
|
|
362
|
+
const lines = chunk.replace(/\r/g, "\n").split("\n");
|
|
363
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
364
|
+
const line = lines[i];
|
|
365
|
+
if (line.length === 0 && i === lines.length - 1) {
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
target.write(`[doer-agent][rpc=${requestId}][${stream}] ${line}\n`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function writeRpcStatus(requestId, message) {
|
|
372
|
+
process.stdout.write(`[doer-agent][rpc=${requestId}][status] ${message}\n`);
|
|
373
|
+
}
|
|
360
374
|
function isLikelyNatsAuthError(error) {
|
|
361
375
|
const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
|
|
362
376
|
return (message.includes("auth")
|
|
@@ -753,10 +767,15 @@ function normalizeShellRpcRequest(args) {
|
|
|
753
767
|
if (requestAgentId !== args.agentId) {
|
|
754
768
|
throw new Error("agent id mismatch");
|
|
755
769
|
}
|
|
770
|
+
const kind = args.request.kind === "apply_patch" ? "apply_patch" : "shell";
|
|
756
771
|
const command = typeof args.request.command === "string" ? args.request.command.trim() : "";
|
|
757
|
-
|
|
772
|
+
const patch = typeof args.request.patch === "string" ? args.request.patch : "";
|
|
773
|
+
if (kind === "shell" && !command) {
|
|
758
774
|
throw new Error("missing command");
|
|
759
775
|
}
|
|
776
|
+
if (kind === "apply_patch" && !patch.trim()) {
|
|
777
|
+
throw new Error("missing patch");
|
|
778
|
+
}
|
|
760
779
|
const responseSubject = typeof args.request.responseSubject === "string" ? args.request.responseSubject.trim() : "";
|
|
761
780
|
if (!responseSubject) {
|
|
762
781
|
throw new Error("missing responseSubject");
|
|
@@ -764,7 +783,35 @@ function normalizeShellRpcRequest(args) {
|
|
|
764
783
|
const cwd = typeof args.request.cwd === "string" && args.request.cwd.trim() ? args.request.cwd.trim() : null;
|
|
765
784
|
const timeoutRaw = Number(args.request.timeoutMs);
|
|
766
785
|
const timeoutMs = Number.isFinite(timeoutRaw) ? Math.max(1000, Math.min(Math.floor(timeoutRaw), 300000)) : 30000;
|
|
767
|
-
return {
|
|
786
|
+
return {
|
|
787
|
+
kind,
|
|
788
|
+
requestId,
|
|
789
|
+
command: kind === "shell" ? command : null,
|
|
790
|
+
patch: kind === "apply_patch" ? patch : null,
|
|
791
|
+
cwd,
|
|
792
|
+
timeoutMs,
|
|
793
|
+
responseSubject,
|
|
794
|
+
runtimeEnvPatch: normalizeEnvPatch(args.request.runtimeEnvPatch),
|
|
795
|
+
codexAuthBundle: normalizeShellRpcCodexAuthBundle(args.request.codexAuth),
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
function normalizeShellRpcCodexAuthBundle(value) {
|
|
799
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
const row = value;
|
|
803
|
+
const authJson = typeof row.authJson === "string" ? row.authJson : null;
|
|
804
|
+
if (!authJson) {
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
807
|
+
return {
|
|
808
|
+
taskId: typeof row.taskId === "string" ? row.taskId : undefined,
|
|
809
|
+
authMode: row.authMode === "oauth" ? "oauth" : row.authMode === "api_key" ? "api_key" : undefined,
|
|
810
|
+
issuedAt: typeof row.issuedAt === "string" ? row.issuedAt : undefined,
|
|
811
|
+
expiresAt: typeof row.expiresAt === "string" ? row.expiresAt : undefined,
|
|
812
|
+
authJson,
|
|
813
|
+
apiKey: typeof row.apiKey === "string" || row.apiKey === null ? row.apiKey : undefined,
|
|
814
|
+
};
|
|
768
815
|
}
|
|
769
816
|
function publishShellRpcResponse(args) {
|
|
770
817
|
args.nc.publish(args.responseSubject, shellRpcCodec.encode(JSON.stringify(args.payload)));
|
|
@@ -779,28 +826,61 @@ async function handleShellRpcMessage(args) {
|
|
|
779
826
|
const request = normalizeShellRpcRequest({ request: payload, agentId: args.agentId });
|
|
780
827
|
requestId = request.requestId;
|
|
781
828
|
responseSubject = request.responseSubject;
|
|
829
|
+
const startedAtMs = Date.now();
|
|
782
830
|
const shellPath = resolveShellPath();
|
|
783
831
|
const taskWorkspace = resolveTaskWorkspace(request.cwd);
|
|
784
|
-
const
|
|
785
|
-
const
|
|
786
|
-
|
|
832
|
+
const codexAuth = await prepareCodexAuthBundle(request.codexAuthBundle);
|
|
833
|
+
const baseTaskEnvPatch = {
|
|
834
|
+
...request.runtimeEnvPatch,
|
|
835
|
+
...(codexAuth?.envPatch ?? {}),
|
|
836
|
+
WORKSPACE: taskWorkspace,
|
|
837
|
+
};
|
|
838
|
+
const taskGitEnv = await prepareTaskGitEnv({
|
|
787
839
|
cwd: taskWorkspace,
|
|
788
|
-
|
|
789
|
-
detached: process.platform !== "win32",
|
|
790
|
-
env: {
|
|
791
|
-
...process.env,
|
|
792
|
-
WORKSPACE: taskWorkspace,
|
|
793
|
-
PATH: taskPath,
|
|
794
|
-
},
|
|
795
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
840
|
+
baseEnvPatch: baseTaskEnvPatch,
|
|
796
841
|
});
|
|
842
|
+
const runtimeBinPath = path.join(AGENT_PROJECT_DIR, "runtime/bin");
|
|
843
|
+
const taskPath = [runtimeBinPath, process.env.PATH || ""].filter(Boolean).join(path.delimiter);
|
|
844
|
+
const child = request.kind === "apply_patch"
|
|
845
|
+
? spawn("apply_patch", {
|
|
846
|
+
cwd: taskWorkspace,
|
|
847
|
+
detached: process.platform !== "win32",
|
|
848
|
+
env: {
|
|
849
|
+
...process.env,
|
|
850
|
+
...baseTaskEnvPatch,
|
|
851
|
+
...taskGitEnv.envPatch,
|
|
852
|
+
PATH: taskPath,
|
|
853
|
+
DOER_AGENT_TOKEN: args.agentToken,
|
|
854
|
+
},
|
|
855
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
856
|
+
})
|
|
857
|
+
: spawn(request.command ?? "", {
|
|
858
|
+
cwd: taskWorkspace,
|
|
859
|
+
shell: shellPath,
|
|
860
|
+
detached: process.platform !== "win32",
|
|
861
|
+
env: {
|
|
862
|
+
...process.env,
|
|
863
|
+
...baseTaskEnvPatch,
|
|
864
|
+
...taskGitEnv.envPatch,
|
|
865
|
+
PATH: taskPath,
|
|
866
|
+
DOER_AGENT_TOKEN: args.agentToken,
|
|
867
|
+
},
|
|
868
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
869
|
+
});
|
|
870
|
+
if (request.kind === "apply_patch") {
|
|
871
|
+
child.stdin?.write(request.patch ?? "");
|
|
872
|
+
child.stdin?.end();
|
|
873
|
+
}
|
|
874
|
+
writeRpcStatus(requestId, `started kind=${request.kind} cwd=${taskWorkspace} shell=${request.kind === "shell" ? shellPath : "apply_patch"}`);
|
|
797
875
|
child.stdout.setEncoding("utf8");
|
|
798
876
|
child.stderr.setEncoding("utf8");
|
|
799
877
|
child.stdout.on("data", (chunk) => {
|
|
800
878
|
stdout += chunk;
|
|
879
|
+
writeRpcStream(requestId, "stdout", chunk);
|
|
801
880
|
});
|
|
802
881
|
child.stderr.on("data", (chunk) => {
|
|
803
882
|
stderr += chunk;
|
|
883
|
+
writeRpcStream(requestId, "stderr", chunk);
|
|
804
884
|
});
|
|
805
885
|
let timedOut = false;
|
|
806
886
|
const timeout = setTimeout(() => {
|
|
@@ -832,6 +912,7 @@ async function handleShellRpcMessage(args) {
|
|
|
832
912
|
...(timedOut ? { error: `Command timed out after ${request.timeoutMs}ms` } : {}),
|
|
833
913
|
},
|
|
834
914
|
});
|
|
915
|
+
writeRpcStatus(requestId, `${timedOut ? "timed_out" : "completed"} exitCode=${result.exitCode ?? "null"} signal=${result.signal ?? "null"} durationMs=${Date.now() - startedAtMs}`);
|
|
835
916
|
}
|
|
836
917
|
catch (error) {
|
|
837
918
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -850,6 +931,7 @@ async function handleShellRpcMessage(args) {
|
|
|
850
931
|
},
|
|
851
932
|
});
|
|
852
933
|
}
|
|
934
|
+
writeRpcStatus(requestId, `failed error=${message}`);
|
|
853
935
|
writeAgentError(`shell rpc failed requestId=${requestId} error=${message}`);
|
|
854
936
|
}
|
|
855
937
|
}
|
|
@@ -866,6 +948,7 @@ function subscribeToShellRpc(args) {
|
|
|
866
948
|
msg,
|
|
867
949
|
jetstream: args.jetstream,
|
|
868
950
|
agentId: args.agentId,
|
|
951
|
+
agentToken: args.agentToken,
|
|
869
952
|
});
|
|
870
953
|
},
|
|
871
954
|
});
|
|
@@ -1042,6 +1125,9 @@ async function prepareTaskCodexAuth(args) {
|
|
|
1042
1125
|
writeAgentError(`task=${args.taskId} codex auth sync skipped: ${message}`);
|
|
1043
1126
|
return null;
|
|
1044
1127
|
});
|
|
1128
|
+
return await prepareCodexAuthBundle(bundle);
|
|
1129
|
+
}
|
|
1130
|
+
async function prepareCodexAuthBundle(bundle) {
|
|
1045
1131
|
if (!bundle || typeof bundle.authJson !== "string") {
|
|
1046
1132
|
return null;
|
|
1047
1133
|
}
|
|
@@ -1390,6 +1476,7 @@ async function main() {
|
|
|
1390
1476
|
jetstream,
|
|
1391
1477
|
userId,
|
|
1392
1478
|
agentId: initialAgentId,
|
|
1479
|
+
agentToken,
|
|
1393
1480
|
});
|
|
1394
1481
|
for (const pendingTaskId of pendingTaskIds) {
|
|
1395
1482
|
await waitForAvailableSlot();
|
|
@@ -1535,6 +1622,7 @@ async function main() {
|
|
|
1535
1622
|
jetstream,
|
|
1536
1623
|
userId,
|
|
1537
1624
|
agentId: refreshedAgentId,
|
|
1625
|
+
agentToken,
|
|
1538
1626
|
});
|
|
1539
1627
|
for (const pendingTaskId of pendingTaskIds) {
|
|
1540
1628
|
await waitForAvailableSlot();
|