doer-agent 0.7.3 → 0.7.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.
|
@@ -62,6 +62,9 @@ function normalizeCodexAppRpcRequest(args) {
|
|
|
62
62
|
const requestAgentId = typeof args.request.agentId === "string" ? args.request.agentId.trim() : "";
|
|
63
63
|
const actionRaw = typeof args.request.action === "string" ? args.request.action.trim() : "";
|
|
64
64
|
const method = typeof args.request.method === "string" ? args.request.method.trim() : "";
|
|
65
|
+
const timeoutMs = typeof args.request.timeoutMs === "number" && Number.isFinite(args.request.timeoutMs)
|
|
66
|
+
? Math.min(180_000, Math.max(1_000, Math.trunc(args.request.timeoutMs)))
|
|
67
|
+
: undefined;
|
|
65
68
|
if (!requestId || !requestAgentId || requestAgentId !== args.agentId || actionRaw !== "request" || !method) {
|
|
66
69
|
throw new Error("invalid codex app rpc request");
|
|
67
70
|
}
|
|
@@ -70,6 +73,7 @@ function normalizeCodexAppRpcRequest(args) {
|
|
|
70
73
|
action: "request",
|
|
71
74
|
method,
|
|
72
75
|
params: args.request.params,
|
|
76
|
+
timeoutMs,
|
|
73
77
|
};
|
|
74
78
|
}
|
|
75
79
|
async function handleCodexAppRpcMessage(args) {
|
|
@@ -78,7 +82,7 @@ async function handleCodexAppRpcMessage(args) {
|
|
|
78
82
|
const payload = JSON.parse(codexAppRpcCodec.decode(args.msg.data));
|
|
79
83
|
const request = normalizeCodexAppRpcRequest({ request: payload, agentId: args.agentId });
|
|
80
84
|
requestId = request.requestId;
|
|
81
|
-
const result = applyCodexAppRpcOmitRules(request.method, await args.manager.request(request.method, request.params));
|
|
85
|
+
const result = applyCodexAppRpcOmitRules(request.method, await args.manager.request(request.method, request.params, request.timeoutMs));
|
|
82
86
|
args.msg.respond(codexAppRpcCodec.encode(JSON.stringify({
|
|
83
87
|
requestId,
|
|
84
88
|
ok: true,
|
package/dist/agent-codex-cli.js
CHANGED
|
@@ -11,6 +11,21 @@ function toTomlStringLiteral(value) {
|
|
|
11
11
|
function toTomlStringArray(values) {
|
|
12
12
|
return `[${values.map((value) => toTomlStringLiteral(value)).join(", ")}]`;
|
|
13
13
|
}
|
|
14
|
+
function buildMcpServerConfigArgs(args) {
|
|
15
|
+
const serverName = args.serverName.trim();
|
|
16
|
+
const configArgs = [
|
|
17
|
+
"--config",
|
|
18
|
+
`mcp_servers.${serverName}.command=${toTomlStringLiteral(args.command)}`,
|
|
19
|
+
"--config",
|
|
20
|
+
`mcp_servers.${serverName}.args=${toTomlStringArray(args.commandArgs)}`,
|
|
21
|
+
"--config",
|
|
22
|
+
`mcp_servers.${serverName}.enabled=${args.enabled === false ? "false" : "true"}`,
|
|
23
|
+
];
|
|
24
|
+
for (const [key, value] of Object.entries(args.env ?? {})) {
|
|
25
|
+
configArgs.push("--config", `mcp_servers.${serverName}.env.${key}=${toTomlStringLiteral(value)}`);
|
|
26
|
+
}
|
|
27
|
+
return configArgs;
|
|
28
|
+
}
|
|
14
29
|
function hasDirectCodexBinary() {
|
|
15
30
|
const result = spawnSync("bash", ["-lc", "command -v codex >/dev/null 2>&1"], {
|
|
16
31
|
stdio: "ignore",
|
|
@@ -71,6 +86,26 @@ export function buildMobileMcpConfigArgs(args) {
|
|
|
71
86
|
},
|
|
72
87
|
});
|
|
73
88
|
}
|
|
89
|
+
export function buildCustomMcpConfigArgs(servers) {
|
|
90
|
+
const configArgs = [];
|
|
91
|
+
const reservedNames = new Set(["doer_daemon", "doer_mobile"]);
|
|
92
|
+
const seenNames = new Set();
|
|
93
|
+
for (const server of servers) {
|
|
94
|
+
const serverName = server.name.trim();
|
|
95
|
+
if (!server.enabled || !serverName || !server.command.trim() || reservedNames.has(serverName) || seenNames.has(serverName)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
seenNames.add(serverName);
|
|
99
|
+
configArgs.push(...buildMcpServerConfigArgs({
|
|
100
|
+
serverName,
|
|
101
|
+
command: server.command,
|
|
102
|
+
commandArgs: server.args,
|
|
103
|
+
env: Object.fromEntries(server.env.map((variable) => [variable.key, variable.value])),
|
|
104
|
+
enabled: true,
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
return configArgs;
|
|
108
|
+
}
|
|
74
109
|
function buildWorkspaceMcpConfigArgs(args) {
|
|
75
110
|
const serverName = args.serverName.trim();
|
|
76
111
|
const distEntry = path.join(args.agentProjectDir, args.distEntryRelativePath);
|
|
@@ -80,20 +115,16 @@ function buildWorkspaceMcpConfigArgs(args) {
|
|
|
80
115
|
const commandArgs = existsSync(distEntry)
|
|
81
116
|
? [distEntry, "--workspace-root", args.workspaceRoot]
|
|
82
117
|
: ["--import", tsxLoaderPath, srcEntry, "--workspace-root", args.workspaceRoot];
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
for (const [key, value] of Object.entries(args.env ?? {})) {
|
|
94
|
-
configArgs.push("--config", `mcp_servers.${serverName}.env.${key}=${toTomlStringLiteral(value)}`);
|
|
95
|
-
}
|
|
96
|
-
return configArgs;
|
|
118
|
+
return buildMcpServerConfigArgs({
|
|
119
|
+
serverName,
|
|
120
|
+
command,
|
|
121
|
+
commandArgs,
|
|
122
|
+
env: {
|
|
123
|
+
[args.workspaceRootEnvName]: args.workspaceRoot,
|
|
124
|
+
...(args.env ?? {}),
|
|
125
|
+
},
|
|
126
|
+
enabled: true,
|
|
127
|
+
});
|
|
97
128
|
}
|
|
98
129
|
export function buildLocalCodexCliCommand(args) {
|
|
99
130
|
const quotedArgs = args.map(shellSingleQuote).join(" ");
|
package/dist/agent-settings.js
CHANGED
|
@@ -41,6 +41,9 @@ export function createDefaultAgentSettingsConfig() {
|
|
|
41
41
|
env: {
|
|
42
42
|
variables: [],
|
|
43
43
|
},
|
|
44
|
+
mcp: {
|
|
45
|
+
servers: [],
|
|
46
|
+
},
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
function normalizeNullableString(value) {
|
|
@@ -115,6 +118,74 @@ function normalizeAgentEnvironmentSettings(value, fallback) {
|
|
|
115
118
|
}
|
|
116
119
|
return { variables };
|
|
117
120
|
}
|
|
121
|
+
function normalizeMcpServerName(value) {
|
|
122
|
+
if (typeof value !== "string") {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const trimmed = value.trim();
|
|
126
|
+
if (!trimmed || !/^[A-Za-z0-9_-]+$/.test(trimmed)) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
if (trimmed === "doer_daemon" || trimmed === "doer_mobile") {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return trimmed;
|
|
133
|
+
}
|
|
134
|
+
function normalizeStringArray(value) {
|
|
135
|
+
if (!Array.isArray(value)) {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
return value
|
|
139
|
+
.map((item) => (typeof item === "string" ? item.replace(/\r/g, "") : null))
|
|
140
|
+
.filter((item) => item !== null && item.trim().length > 0);
|
|
141
|
+
}
|
|
142
|
+
function normalizeAgentMcpServer(value) {
|
|
143
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const raw = value;
|
|
147
|
+
const name = normalizeMcpServerName(raw.name);
|
|
148
|
+
const command = typeof raw.command === "string" ? raw.command.trim() : "";
|
|
149
|
+
if (!name || !command) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
const env = [];
|
|
153
|
+
const seenKeys = new Set();
|
|
154
|
+
const envRaw = Array.isArray(raw.env) ? raw.env : [];
|
|
155
|
+
for (const item of envRaw) {
|
|
156
|
+
const normalized = normalizeAgentEnvironmentVariable(item);
|
|
157
|
+
if (!normalized || seenKeys.has(normalized.key)) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
seenKeys.add(normalized.key);
|
|
161
|
+
env.push(normalized);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
name,
|
|
165
|
+
command,
|
|
166
|
+
args: normalizeStringArray(raw.args),
|
|
167
|
+
env,
|
|
168
|
+
enabled: raw.enabled !== false,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function normalizeAgentMcpSettings(value, fallback) {
|
|
172
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
173
|
+
return fallback;
|
|
174
|
+
}
|
|
175
|
+
const raw = value;
|
|
176
|
+
const serversRaw = Array.isArray(raw.servers) ? raw.servers : [];
|
|
177
|
+
const servers = [];
|
|
178
|
+
const seenNames = new Set();
|
|
179
|
+
for (const item of serversRaw) {
|
|
180
|
+
const normalized = normalizeAgentMcpServer(item);
|
|
181
|
+
if (!normalized || seenNames.has(normalized.name)) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
seenNames.add(normalized.name);
|
|
185
|
+
servers.push(normalized);
|
|
186
|
+
}
|
|
187
|
+
return { servers };
|
|
188
|
+
}
|
|
118
189
|
export function normalizeAgentSettingsConfig(value, fallback) {
|
|
119
190
|
const base = fallback ?? createDefaultAgentSettingsConfig();
|
|
120
191
|
const raw = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -123,6 +194,7 @@ export function normalizeAgentSettingsConfig(value, fallback) {
|
|
|
123
194
|
const realtime = raw.realtime && typeof raw.realtime === "object" ? raw.realtime : {};
|
|
124
195
|
const git = raw.git && typeof raw.git === "object" ? raw.git : {};
|
|
125
196
|
const env = raw.env && typeof raw.env === "object" ? raw.env : null;
|
|
197
|
+
const mcp = raw.mcp && typeof raw.mcp === "object" ? raw.mcp : null;
|
|
126
198
|
return {
|
|
127
199
|
general: {
|
|
128
200
|
personality: normalizeCodexPersonality(general.personality, base.general.personality),
|
|
@@ -152,6 +224,7 @@ export function normalizeAgentSettingsConfig(value, fallback) {
|
|
|
152
224
|
oauthScope: git.oauthScope === null ? null : normalizeNullableString(git.oauthScope) ?? base.git.oauthScope,
|
|
153
225
|
},
|
|
154
226
|
env: normalizeAgentEnvironmentSettings(env, base.env),
|
|
227
|
+
mcp: normalizeAgentMcpSettings(mcp, base.mcp),
|
|
155
228
|
};
|
|
156
229
|
}
|
|
157
230
|
export async function readAgentSettingsConfig(args) {
|
|
@@ -245,6 +318,18 @@ export async function toAgentSettingsPublic(args) {
|
|
|
245
318
|
value: variable.value,
|
|
246
319
|
})),
|
|
247
320
|
},
|
|
321
|
+
mcp: {
|
|
322
|
+
servers: args.config.mcp.servers.map((server) => ({
|
|
323
|
+
name: server.name,
|
|
324
|
+
command: server.command,
|
|
325
|
+
args: [...server.args],
|
|
326
|
+
env: server.env.map((variable) => ({
|
|
327
|
+
key: variable.key,
|
|
328
|
+
value: variable.value,
|
|
329
|
+
})),
|
|
330
|
+
enabled: server.enabled,
|
|
331
|
+
})),
|
|
332
|
+
},
|
|
248
333
|
};
|
|
249
334
|
}
|
|
250
335
|
export function normalizeAgentSettingsPatch(value) {
|
|
@@ -287,6 +372,7 @@ export function normalizeAgentSettingsPatch(value) {
|
|
|
287
372
|
move("gitOauthLogin", "git", "oauthLogin");
|
|
288
373
|
move("gitOauthScope", "git", "oauthScope");
|
|
289
374
|
move("environmentVariables", "env", "variables");
|
|
375
|
+
move("mcpServers", "mcp", "servers");
|
|
290
376
|
return patch;
|
|
291
377
|
}
|
|
292
378
|
export function buildAgentSettingsEnvPatch(config) {
|
|
@@ -22,9 +22,9 @@ export class CodexAppServerClient {
|
|
|
22
22
|
constructor(options) {
|
|
23
23
|
this.options = options;
|
|
24
24
|
}
|
|
25
|
-
async request(method, params) {
|
|
25
|
+
async request(method, params, timeoutMs) {
|
|
26
26
|
await this.start();
|
|
27
|
-
return await this.requestStarted(method, params);
|
|
27
|
+
return await this.requestStarted(method, params, timeoutMs);
|
|
28
28
|
}
|
|
29
29
|
async notify(method, params) {
|
|
30
30
|
await this.start();
|
|
@@ -92,14 +92,14 @@ export class CodexAppServerClient {
|
|
|
92
92
|
});
|
|
93
93
|
await this.notify("initialized");
|
|
94
94
|
}
|
|
95
|
-
async requestStarted(method, params) {
|
|
95
|
+
async requestStarted(method, params, timeoutMsOverride) {
|
|
96
96
|
const child = this.child;
|
|
97
97
|
if (!child || child.killed) {
|
|
98
98
|
throw new Error("Codex app-server is not running");
|
|
99
99
|
}
|
|
100
100
|
const id = this.nextRequestId++;
|
|
101
101
|
const payload = params === undefined ? { id, method } : { id, method, params };
|
|
102
|
-
const timeoutMs = this.options.requestTimeoutMs ?? 30_000;
|
|
102
|
+
const timeoutMs = timeoutMsOverride ?? this.options.requestTimeoutMs ?? 30_000;
|
|
103
103
|
return await new Promise((resolve, reject) => {
|
|
104
104
|
const timer = setTimeout(() => {
|
|
105
105
|
this.pending.delete(id);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildAgentSettingsEnvPatch, readAgentModelInstructions, resolveAgentModelInstructionsFilePath, } from "./agent-settings.js";
|
|
2
|
-
import { buildDaemonMcpConfigArgs, buildMobileMcpConfigArgs } from "./agent-codex-cli.js";
|
|
2
|
+
import { buildCustomMcpConfigArgs, buildDaemonMcpConfigArgs, buildMobileMcpConfigArgs } from "./agent-codex-cli.js";
|
|
3
3
|
import { CodexAppServerClient } from "./codex-app-server-client.js";
|
|
4
4
|
function toTomlStringLiteral(value) {
|
|
5
5
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -40,6 +40,7 @@ async function buildCodexAppServerArgs(args) {
|
|
|
40
40
|
userId: args.userId,
|
|
41
41
|
workspaceRoot: args.workspaceRoot,
|
|
42
42
|
}),
|
|
43
|
+
...buildCustomMcpConfigArgs(args.settings.mcp.servers),
|
|
43
44
|
...buildFeatureArg(true, "goals"),
|
|
44
45
|
...buildFeatureArg(args.settings.codex.computerUseEnabled, "computer_use"),
|
|
45
46
|
...buildFeatureArg(args.settings.codex.browserUseEnabled, "browser_use"),
|
|
@@ -82,7 +83,7 @@ export function createCodexAppServerManager(args) {
|
|
|
82
83
|
settings,
|
|
83
84
|
userId: args.userId,
|
|
84
85
|
});
|
|
85
|
-
args.onLog?.(`starting codex app-server model=${settings.codex.model} reasoningEffort=${settings.codex.reasoningEffort} personality=${settings.general.personality} computerUse=${settings.codex.computerUseEnabled} browserUse=${settings.codex.browserUseEnabled}`);
|
|
86
|
+
args.onLog?.(`starting codex app-server model=${settings.codex.model} reasoningEffort=${settings.codex.reasoningEffort} personality=${settings.general.personality} computerUse=${settings.codex.computerUseEnabled} browserUse=${settings.codex.browserUseEnabled} mcpServers=${settings.mcp.servers.filter((server) => server.enabled).length}`);
|
|
86
87
|
return new CodexAppServerClient({
|
|
87
88
|
cwd: args.workspaceRoot,
|
|
88
89
|
args: appServerArgs,
|
|
@@ -116,9 +117,9 @@ export function createCodexAppServerManager(args) {
|
|
|
116
117
|
}
|
|
117
118
|
};
|
|
118
119
|
return {
|
|
119
|
-
async request(method, params) {
|
|
120
|
+
async request(method, params, timeoutMs) {
|
|
120
121
|
const activeClient = await getClient();
|
|
121
|
-
return await activeClient.request(method, params);
|
|
122
|
+
return await activeClient.request(method, params, timeoutMs);
|
|
122
123
|
},
|
|
123
124
|
async restart(reason) {
|
|
124
125
|
generation += 1;
|