doer-agent 0.3.4 → 0.3.5
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 +127 -31
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -609,7 +609,6 @@ function createDefaultAgentSettingsConfig() {
|
|
|
609
609
|
codex: {
|
|
610
610
|
model: "gpt-5.4",
|
|
611
611
|
authMode: "api_key",
|
|
612
|
-
apiKey: null,
|
|
613
612
|
},
|
|
614
613
|
realtime: {
|
|
615
614
|
model: process.env.OPENAI_REALTIME_MODEL?.trim() || "gpt-realtime",
|
|
@@ -687,7 +686,6 @@ function normalizeAgentSettingsConfig(value, fallback) {
|
|
|
687
686
|
codex: {
|
|
688
687
|
model: typeof codex.model === "string" && codex.model.trim() ? codex.model.trim() : base.codex.model,
|
|
689
688
|
authMode: codex.authMode === "oauth" ? "oauth" : codex.authMode === "api_key" ? "api_key" : base.codex.authMode,
|
|
690
|
-
apiKey: codex.apiKey === null ? null : normalizeNullableString(codex.apiKey) ?? base.codex.apiKey,
|
|
691
689
|
},
|
|
692
690
|
realtime: {
|
|
693
691
|
model: typeof realtime.model === "string" && realtime.model.trim() ? realtime.model.trim() : base.realtime.model,
|
|
@@ -768,7 +766,6 @@ function toMaskedSecret(value) {
|
|
|
768
766
|
return { has: true, masked: maskSecretPreview(value), length: value.length };
|
|
769
767
|
}
|
|
770
768
|
function toAgentSettingsPublic(config) {
|
|
771
|
-
const codexKey = toMaskedSecret(config.codex.apiKey);
|
|
772
769
|
const realtimeKey = toMaskedSecret(config.realtime.apiKey);
|
|
773
770
|
const gitOauth = toMaskedSecret(config.git.oauthToken);
|
|
774
771
|
const awsSecret = toMaskedSecret(config.aws.secretAccessKey);
|
|
@@ -784,9 +781,9 @@ function toAgentSettingsPublic(config) {
|
|
|
784
781
|
codex: {
|
|
785
782
|
model: config.codex.model,
|
|
786
783
|
authMode: config.codex.authMode,
|
|
787
|
-
hasApiKey:
|
|
788
|
-
apiKeyMasked:
|
|
789
|
-
apiKeyLength:
|
|
784
|
+
hasApiKey: false,
|
|
785
|
+
apiKeyMasked: null,
|
|
786
|
+
apiKeyLength: null,
|
|
790
787
|
},
|
|
791
788
|
realtime: {
|
|
792
789
|
model: config.realtime.model,
|
|
@@ -874,7 +871,6 @@ function normalizeAgentSettingsPatch(value) {
|
|
|
874
871
|
move("firstTurnPrompt", "general", "firstTurnPrompt");
|
|
875
872
|
move("codexModel", "codex", "model");
|
|
876
873
|
move("codexAuthMode", "codex", "authMode");
|
|
877
|
-
move("codexApiKey", "codex", "apiKey");
|
|
878
874
|
move("realtimeModel", "realtime", "model");
|
|
879
875
|
move("realtimeVoice", "realtime", "voice");
|
|
880
876
|
move("realtimeWakeName", "realtime", "wakeName");
|
|
@@ -915,9 +911,6 @@ async function resolveAgentSettingsConfig(args) {
|
|
|
915
911
|
}
|
|
916
912
|
function buildAgentSettingsEnvPatch(config) {
|
|
917
913
|
const envPatch = {};
|
|
918
|
-
if (config.codex.authMode === "api_key" && config.codex.apiKey) {
|
|
919
|
-
envPatch.OPENAI_API_KEY = config.codex.apiKey;
|
|
920
|
-
}
|
|
921
914
|
if (config.git.enabled) {
|
|
922
915
|
if (config.git.name)
|
|
923
916
|
envPatch.GIT_AUTHOR_NAME = config.git.name;
|
|
@@ -1113,6 +1106,7 @@ async function startManagedRun(args) {
|
|
|
1113
1106
|
userId: args.userId,
|
|
1114
1107
|
taskId: args.runId,
|
|
1115
1108
|
codexAuthBundle: args.codexAuthBundle,
|
|
1109
|
+
runtimeEnvPatch: args.runtimeEnvPatch,
|
|
1116
1110
|
});
|
|
1117
1111
|
const child = spawnManagedCodexCommand({
|
|
1118
1112
|
codexArgs: args.codexArgs,
|
|
@@ -1312,6 +1306,62 @@ async function runLocalCodexCli(args, timeoutMs, envPatch) {
|
|
|
1312
1306
|
});
|
|
1313
1307
|
});
|
|
1314
1308
|
}
|
|
1309
|
+
async function runLocalCodexCliWithInput(args, input, timeoutMs, envPatch) {
|
|
1310
|
+
const command = buildLocalCodexCliCommand(args);
|
|
1311
|
+
const workspaceRoot = workspaceRootOverride ?? (process.env.WORKSPACE?.trim() || process.cwd());
|
|
1312
|
+
const env = {
|
|
1313
|
+
...process.env,
|
|
1314
|
+
...(envPatch ?? {}),
|
|
1315
|
+
WORKSPACE: workspaceRoot,
|
|
1316
|
+
CODEX_HOME: resolveCodexHomePath(),
|
|
1317
|
+
};
|
|
1318
|
+
return await new Promise((resolve, reject) => {
|
|
1319
|
+
const child = spawn(command, {
|
|
1320
|
+
cwd: workspaceRoot,
|
|
1321
|
+
shell: resolveShellPath(),
|
|
1322
|
+
env,
|
|
1323
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1324
|
+
});
|
|
1325
|
+
let stdout = "";
|
|
1326
|
+
let stderr = "";
|
|
1327
|
+
let done = false;
|
|
1328
|
+
let timedOut = false;
|
|
1329
|
+
child.stdout.setEncoding("utf8");
|
|
1330
|
+
child.stderr.setEncoding("utf8");
|
|
1331
|
+
child.stdout.on("data", (chunk) => {
|
|
1332
|
+
stdout += chunk;
|
|
1333
|
+
});
|
|
1334
|
+
child.stderr.on("data", (chunk) => {
|
|
1335
|
+
stderr += chunk;
|
|
1336
|
+
});
|
|
1337
|
+
child.stdin?.write(input);
|
|
1338
|
+
if (!input.endsWith("\n")) {
|
|
1339
|
+
child.stdin?.write("\n");
|
|
1340
|
+
}
|
|
1341
|
+
child.stdin?.end();
|
|
1342
|
+
const timer = setTimeout(() => {
|
|
1343
|
+
timedOut = true;
|
|
1344
|
+
sendSignalToTaskProcess(child, "SIGTERM");
|
|
1345
|
+
setTimeout(() => sendSignalToTaskProcess(child, "SIGKILL"), 1000);
|
|
1346
|
+
}, Math.max(500, timeoutMs));
|
|
1347
|
+
child.once("error", (error) => {
|
|
1348
|
+
if (done) {
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
done = true;
|
|
1352
|
+
clearTimeout(timer);
|
|
1353
|
+
reject(error);
|
|
1354
|
+
});
|
|
1355
|
+
child.once("exit", (code) => {
|
|
1356
|
+
if (done) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
done = true;
|
|
1360
|
+
clearTimeout(timer);
|
|
1361
|
+
resolve({ code, stdout, stderr, timedOut });
|
|
1362
|
+
});
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1315
1365
|
function buildSkillGeneratorPrompt(userPrompt) {
|
|
1316
1366
|
return [
|
|
1317
1367
|
"Create a Codex skill from the user's description.",
|
|
@@ -1663,6 +1713,20 @@ async function startLocalCodexLogin() {
|
|
|
1663
1713
|
}
|
|
1664
1714
|
throw new Error(normalized || `Codex login failed with code ${result.code ?? "null"}`);
|
|
1665
1715
|
}
|
|
1716
|
+
async function loginLocalCodexWithApiKey(apiKey) {
|
|
1717
|
+
const result = await runLocalCodexCliWithInput(["login", "--with-api-key"], apiKey, 15000);
|
|
1718
|
+
const normalized = stripAnsi([result.stdout, result.stderr].filter(Boolean).join("\n")).trim();
|
|
1719
|
+
if ((result.code ?? 1) !== 0) {
|
|
1720
|
+
throw new Error(normalized || `Codex API key login failed with code ${result.code ?? "null"}`);
|
|
1721
|
+
}
|
|
1722
|
+
const status = await getLocalCodexLoginStatus().catch(() => null);
|
|
1723
|
+
return {
|
|
1724
|
+
loggedIn: status?.loggedIn === true,
|
|
1725
|
+
output: status?.output || normalized || "Logged in",
|
|
1726
|
+
verificationUri: null,
|
|
1727
|
+
userCode: null,
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1666
1730
|
async function logoutLocalCodexAuth() {
|
|
1667
1731
|
if (pendingCodexDeviceAuth && pendingCodexDeviceAuth.child.exitCode === null) {
|
|
1668
1732
|
sendSignalToTaskProcess(pendingCodexDeviceAuth.child, "SIGTERM");
|
|
@@ -1694,11 +1758,15 @@ function normalizeCodexAuthRpcRequest(args) {
|
|
|
1694
1758
|
const responseSubject = typeof args.request.responseSubject === "string" ? args.request.responseSubject.trim() : "";
|
|
1695
1759
|
const requestAgentId = typeof args.request.agentId === "string" ? args.request.agentId.trim() : "";
|
|
1696
1760
|
const actionRaw = typeof args.request.action === "string" ? args.request.action.trim() : "";
|
|
1697
|
-
const action = actionRaw === "start" || actionRaw === "logout" ? actionRaw : "status";
|
|
1761
|
+
const action = actionRaw === "start" || actionRaw === "logout" || actionRaw === "login_api_key" ? actionRaw : "status";
|
|
1762
|
+
const apiKey = typeof args.request.apiKey === "string" && args.request.apiKey.trim() ? args.request.apiKey.trim() : null;
|
|
1698
1763
|
if (!requestId || !responseSubject || !requestAgentId || requestAgentId !== args.agentId) {
|
|
1699
1764
|
throw new Error("invalid codex auth rpc request");
|
|
1700
1765
|
}
|
|
1701
|
-
|
|
1766
|
+
if (action === "login_api_key" && !apiKey) {
|
|
1767
|
+
throw new Error("api key is required");
|
|
1768
|
+
}
|
|
1769
|
+
return { requestId, responseSubject, action, apiKey };
|
|
1702
1770
|
}
|
|
1703
1771
|
function publishCodexAuthRpcResponse(args) {
|
|
1704
1772
|
args.nc.publish(args.responseSubject, codexAuthRpcCodec.encode(JSON.stringify(args.payload)));
|
|
@@ -1712,7 +1780,10 @@ async function handleCodexAuthRpcMessage(args) {
|
|
|
1712
1780
|
requestId = request.requestId;
|
|
1713
1781
|
responseSubject = request.responseSubject;
|
|
1714
1782
|
let result = null;
|
|
1715
|
-
if (request.action === "
|
|
1783
|
+
if (request.action === "login_api_key") {
|
|
1784
|
+
result = await loginLocalCodexWithApiKey(request.apiKey ?? "");
|
|
1785
|
+
}
|
|
1786
|
+
else if (request.action === "start") {
|
|
1716
1787
|
const status = await getLocalCodexLoginStatus();
|
|
1717
1788
|
if (status.loggedIn) {
|
|
1718
1789
|
result = { loggedIn: true, output: status.output };
|
|
@@ -3560,16 +3631,18 @@ function normalizeShellRpcCodexAuthBundle(value) {
|
|
|
3560
3631
|
}
|
|
3561
3632
|
const row = value;
|
|
3562
3633
|
const authJson = typeof row.authJson === "string" ? row.authJson : null;
|
|
3563
|
-
|
|
3634
|
+
const authMode = row.authMode === "oauth" ? "oauth" : row.authMode === "api_key" ? "api_key" : undefined;
|
|
3635
|
+
const apiKey = typeof row.apiKey === "string" || row.apiKey === null ? row.apiKey : undefined;
|
|
3636
|
+
if (!authJson && authMode !== "api_key" && apiKey === undefined) {
|
|
3564
3637
|
return null;
|
|
3565
3638
|
}
|
|
3566
3639
|
return {
|
|
3567
3640
|
taskId: typeof row.taskId === "string" ? row.taskId : undefined,
|
|
3568
|
-
authMode
|
|
3641
|
+
authMode,
|
|
3569
3642
|
issuedAt: typeof row.issuedAt === "string" ? row.issuedAt : undefined,
|
|
3570
3643
|
expiresAt: typeof row.expiresAt === "string" ? row.expiresAt : undefined,
|
|
3571
|
-
authJson,
|
|
3572
|
-
apiKey
|
|
3644
|
+
authJson: authJson ?? undefined,
|
|
3645
|
+
apiKey,
|
|
3573
3646
|
};
|
|
3574
3647
|
}
|
|
3575
3648
|
async function postJson(url, body) {
|
|
@@ -3734,27 +3807,49 @@ async function checkCancelRequested(args) {
|
|
|
3734
3807
|
const response = await getJson(`${args.serverBaseUrl}/api/agent/tasks/${encodeURIComponent(args.taskId)}/events?${query.toString()}`);
|
|
3735
3808
|
return Boolean(response.task?.cancelRequested);
|
|
3736
3809
|
}
|
|
3737
|
-
async function
|
|
3738
|
-
|
|
3810
|
+
async function syncCodexAuthState(args) {
|
|
3811
|
+
const envPatch = {};
|
|
3812
|
+
const synced = false;
|
|
3813
|
+
if (args.authMode === "api_key") {
|
|
3814
|
+
if (args.apiKey) {
|
|
3815
|
+
envPatch.OPENAI_API_KEY = args.apiKey;
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3739
3818
|
return {
|
|
3740
|
-
envPatch
|
|
3819
|
+
envPatch,
|
|
3741
3820
|
cleanup: async () => { },
|
|
3742
3821
|
meta: {
|
|
3743
|
-
codexAuthSource:
|
|
3744
|
-
|
|
3822
|
+
codexAuthSource: args.source,
|
|
3823
|
+
codexAuthMode: args.authMode ?? null,
|
|
3824
|
+
codexAuthHasApiKey: Boolean(args.apiKey),
|
|
3825
|
+
codexAuthHasAuthJson: Boolean(args.authJson),
|
|
3826
|
+
codexAuthIssuedAt: args.issuedAt ?? null,
|
|
3827
|
+
codexAuthExpiresAt: args.expiresAt ?? null,
|
|
3828
|
+
codexAuthSynced: synced,
|
|
3745
3829
|
},
|
|
3746
3830
|
};
|
|
3747
3831
|
}
|
|
3832
|
+
async function prepareTaskCodexAuth(args) {
|
|
3833
|
+
void args;
|
|
3834
|
+
return await syncCodexAuthState({
|
|
3835
|
+
source: "agent_local",
|
|
3836
|
+
authJson: null,
|
|
3837
|
+
issuedAt: null,
|
|
3838
|
+
expiresAt: null,
|
|
3839
|
+
});
|
|
3840
|
+
}
|
|
3748
3841
|
async function prepareCodexAuthBundle(bundle) {
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3842
|
+
if (!bundle) {
|
|
3843
|
+
return null;
|
|
3844
|
+
}
|
|
3845
|
+
return await syncCodexAuthState({
|
|
3846
|
+
source: "server_bundle",
|
|
3847
|
+
authMode: bundle.authMode,
|
|
3848
|
+
apiKey: bundle.apiKey,
|
|
3849
|
+
authJson: bundle.authJson ?? null,
|
|
3850
|
+
issuedAt: bundle.issuedAt ?? null,
|
|
3851
|
+
expiresAt: bundle.expiresAt ?? null,
|
|
3852
|
+
});
|
|
3758
3853
|
}
|
|
3759
3854
|
async function prepareCommandExecution(args) {
|
|
3760
3855
|
const shellPath = resolveShellPath();
|
|
@@ -3768,6 +3863,7 @@ async function prepareCommandExecution(args) {
|
|
|
3768
3863
|
DOER_USER_ID: args.userId,
|
|
3769
3864
|
DOER_AGENT_TASK_ID: args.taskId,
|
|
3770
3865
|
...buildAgentSettingsEnvPatch(localAgentSettings),
|
|
3866
|
+
...args.runtimeEnvPatch,
|
|
3771
3867
|
...(codexAuth?.envPatch ?? {}),
|
|
3772
3868
|
WORKSPACE: taskWorkspace,
|
|
3773
3869
|
};
|