doer-agent 0.8.9 → 0.9.1
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-codex-cli.js +37 -1
- package/dist/agent-codex-cli.test.js +44 -0
- package/dist/agent-settings.js +36 -2
- package/package.json +3 -3
package/dist/agent-codex-cli.js
CHANGED
|
@@ -13,6 +13,11 @@ function toTomlStringLiteral(value) {
|
|
|
13
13
|
function toTomlStringArray(values) {
|
|
14
14
|
return `[${values.map((value) => toTomlStringLiteral(value)).join(", ")}]`;
|
|
15
15
|
}
|
|
16
|
+
function toTomlStringMap(values) {
|
|
17
|
+
return `{ ${Object.entries(values)
|
|
18
|
+
.map(([key, value]) => `${toTomlStringLiteral(key)} = ${toTomlStringLiteral(value)}`)
|
|
19
|
+
.join(", ")} }`;
|
|
20
|
+
}
|
|
16
21
|
function buildMcpServerConfigArgs(args) {
|
|
17
22
|
const serverName = args.serverName.trim();
|
|
18
23
|
const configArgs = [
|
|
@@ -28,6 +33,25 @@ function buildMcpServerConfigArgs(args) {
|
|
|
28
33
|
}
|
|
29
34
|
return configArgs;
|
|
30
35
|
}
|
|
36
|
+
function buildRemoteMcpServerConfigArgs(args) {
|
|
37
|
+
const prefix = `mcp_servers.${args.serverName.trim()}`;
|
|
38
|
+
const configArgs = [
|
|
39
|
+
"--config",
|
|
40
|
+
`${prefix}.url=${toTomlStringLiteral(args.url)}`,
|
|
41
|
+
"--config",
|
|
42
|
+
`${prefix}.enabled=${args.enabled === false ? "false" : "true"}`,
|
|
43
|
+
];
|
|
44
|
+
if (args.bearerTokenEnvVar?.trim()) {
|
|
45
|
+
configArgs.push("--config", `${prefix}.bearer_token_env_var=${toTomlStringLiteral(args.bearerTokenEnvVar.trim())}`);
|
|
46
|
+
}
|
|
47
|
+
if (Object.keys(args.httpHeaders ?? {}).length > 0) {
|
|
48
|
+
configArgs.push("--config", `${prefix}.http_headers=${toTomlStringMap(args.httpHeaders ?? {})}`);
|
|
49
|
+
}
|
|
50
|
+
if (Object.keys(args.envHttpHeaders ?? {}).length > 0) {
|
|
51
|
+
configArgs.push("--config", `${prefix}.env_http_headers=${toTomlStringMap(args.envHttpHeaders ?? {})}`);
|
|
52
|
+
}
|
|
53
|
+
return configArgs;
|
|
54
|
+
}
|
|
31
55
|
function hasDirectCodexBinary() {
|
|
32
56
|
const result = spawnSync("bash", ["-lc", "command -v codex >/dev/null 2>&1"], {
|
|
33
57
|
stdio: "ignore",
|
|
@@ -124,10 +148,22 @@ export function buildCustomMcpConfigArgs(servers) {
|
|
|
124
148
|
const seenNames = new Set();
|
|
125
149
|
for (const server of servers) {
|
|
126
150
|
const serverName = server.name.trim();
|
|
127
|
-
|
|
151
|
+
const hasEndpoint = server.transport === "streamable_http" ? server.url.trim() : server.command.trim();
|
|
152
|
+
if (!server.enabled || !serverName || !hasEndpoint || reservedNames.has(serverName) || seenNames.has(serverName)) {
|
|
128
153
|
continue;
|
|
129
154
|
}
|
|
130
155
|
seenNames.add(serverName);
|
|
156
|
+
if (server.transport === "streamable_http") {
|
|
157
|
+
configArgs.push(...buildRemoteMcpServerConfigArgs({
|
|
158
|
+
serverName,
|
|
159
|
+
url: server.url,
|
|
160
|
+
bearerTokenEnvVar: server.bearerTokenEnvVar,
|
|
161
|
+
httpHeaders: Object.fromEntries(server.httpHeaders.map((header) => [header.key, header.value])),
|
|
162
|
+
envHttpHeaders: Object.fromEntries(server.envHttpHeaders.map((header) => [header.key, header.value])),
|
|
163
|
+
enabled: true,
|
|
164
|
+
}));
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
131
167
|
configArgs.push(...buildMcpServerConfigArgs({
|
|
132
168
|
serverName,
|
|
133
169
|
command: server.command,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { buildCustomMcpConfigArgs } from "./agent-codex-cli.js";
|
|
4
|
+
test("buildCustomMcpConfigArgs builds streamable HTTP MCP overrides", () => {
|
|
5
|
+
const args = buildCustomMcpConfigArgs([{
|
|
6
|
+
name: "remote_docs",
|
|
7
|
+
transport: "streamable_http",
|
|
8
|
+
command: "",
|
|
9
|
+
args: [],
|
|
10
|
+
env: [],
|
|
11
|
+
url: "https://example.com/mcp",
|
|
12
|
+
bearerTokenEnvVar: "MCP_TOKEN",
|
|
13
|
+
httpHeaders: [{ key: "X-Region", value: "seoul" }],
|
|
14
|
+
envHttpHeaders: [{ key: "X-API-Key", value: "MCP_API_KEY" }],
|
|
15
|
+
enabled: true,
|
|
16
|
+
}]);
|
|
17
|
+
assert.deepEqual(args, [
|
|
18
|
+
"--config", 'mcp_servers.remote_docs.url="https://example.com/mcp"',
|
|
19
|
+
"--config", "mcp_servers.remote_docs.enabled=true",
|
|
20
|
+
"--config", 'mcp_servers.remote_docs.bearer_token_env_var="MCP_TOKEN"',
|
|
21
|
+
"--config", 'mcp_servers.remote_docs.http_headers={ "X-Region" = "seoul" }',
|
|
22
|
+
"--config", 'mcp_servers.remote_docs.env_http_headers={ "X-API-Key" = "MCP_API_KEY" }',
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
test("buildCustomMcpConfigArgs keeps stdio MCP overrides", () => {
|
|
26
|
+
const args = buildCustomMcpConfigArgs([{
|
|
27
|
+
name: "local_tools",
|
|
28
|
+
transport: "stdio",
|
|
29
|
+
command: "npx",
|
|
30
|
+
args: ["-y", "local-mcp"],
|
|
31
|
+
env: [{ key: "LOCAL_TOKEN", value: "secret" }],
|
|
32
|
+
url: "",
|
|
33
|
+
bearerTokenEnvVar: "",
|
|
34
|
+
httpHeaders: [],
|
|
35
|
+
envHttpHeaders: [],
|
|
36
|
+
enabled: true,
|
|
37
|
+
}]);
|
|
38
|
+
assert.deepEqual(args, [
|
|
39
|
+
"--config", 'mcp_servers.local_tools.command="npx"',
|
|
40
|
+
"--config", 'mcp_servers.local_tools.args=["-y", "local-mcp"]',
|
|
41
|
+
"--config", "mcp_servers.local_tools.enabled=true",
|
|
42
|
+
"--config", 'mcp_servers.local_tools.env.LOCAL_TOKEN="secret"',
|
|
43
|
+
]);
|
|
44
|
+
});
|
package/dist/agent-settings.js
CHANGED
|
@@ -172,7 +172,7 @@ function normalizeMcpServerName(value) {
|
|
|
172
172
|
if (!trimmed || !/^[A-Za-z0-9_-]+$/.test(trimmed)) {
|
|
173
173
|
return null;
|
|
174
174
|
}
|
|
175
|
-
if (trimmed === "doer_daemon" || trimmed === "doer_mobile") {
|
|
175
|
+
if (trimmed === "doer_daemon" || trimmed === "doer_mobile" || trimmed === "doer_threads") {
|
|
176
176
|
return null;
|
|
177
177
|
}
|
|
178
178
|
return trimmed;
|
|
@@ -185,14 +185,38 @@ function normalizeStringArray(value) {
|
|
|
185
185
|
.map((item) => (typeof item === "string" ? item.replace(/\r/g, "") : null))
|
|
186
186
|
.filter((item) => item !== null && item.trim().length > 0);
|
|
187
187
|
}
|
|
188
|
+
function normalizeMcpHeaderEntries(value) {
|
|
189
|
+
if (!Array.isArray(value)) {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
const entries = [];
|
|
193
|
+
const seenKeys = new Set();
|
|
194
|
+
for (const item of value) {
|
|
195
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const raw = item;
|
|
199
|
+
const key = typeof raw.key === "string" ? raw.key.trim() : "";
|
|
200
|
+
if (!key || typeof raw.value !== "string" || seenKeys.has(key)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
seenKeys.add(key);
|
|
204
|
+
entries.push({ key, value: raw.value.replace(/\r/g, "") });
|
|
205
|
+
}
|
|
206
|
+
return entries;
|
|
207
|
+
}
|
|
188
208
|
function normalizeAgentMcpServer(value) {
|
|
189
209
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
190
210
|
return null;
|
|
191
211
|
}
|
|
192
212
|
const raw = value;
|
|
193
213
|
const name = normalizeMcpServerName(raw.name);
|
|
214
|
+
const transport = raw.transport === "streamable_http" || (typeof raw.url === "string" && raw.url.trim())
|
|
215
|
+
? "streamable_http"
|
|
216
|
+
: "stdio";
|
|
194
217
|
const command = typeof raw.command === "string" ? raw.command.trim() : "";
|
|
195
|
-
|
|
218
|
+
const url = typeof raw.url === "string" ? raw.url.trim() : "";
|
|
219
|
+
if (!name || (transport === "stdio" ? !command : !url)) {
|
|
196
220
|
return null;
|
|
197
221
|
}
|
|
198
222
|
const env = [];
|
|
@@ -208,9 +232,14 @@ function normalizeAgentMcpServer(value) {
|
|
|
208
232
|
}
|
|
209
233
|
return {
|
|
210
234
|
name,
|
|
235
|
+
transport,
|
|
211
236
|
command,
|
|
212
237
|
args: normalizeStringArray(raw.args),
|
|
213
238
|
env,
|
|
239
|
+
url,
|
|
240
|
+
bearerTokenEnvVar: typeof raw.bearerTokenEnvVar === "string" ? raw.bearerTokenEnvVar.trim() : "",
|
|
241
|
+
httpHeaders: normalizeMcpHeaderEntries(raw.httpHeaders),
|
|
242
|
+
envHttpHeaders: normalizeMcpHeaderEntries(raw.envHttpHeaders),
|
|
214
243
|
enabled: raw.enabled !== false,
|
|
215
244
|
};
|
|
216
245
|
}
|
|
@@ -386,12 +415,17 @@ export async function toAgentSettingsPublic(args) {
|
|
|
386
415
|
mcp: {
|
|
387
416
|
servers: args.config.mcp.servers.map((server) => ({
|
|
388
417
|
name: server.name,
|
|
418
|
+
transport: server.transport,
|
|
389
419
|
command: server.command,
|
|
390
420
|
args: [...server.args],
|
|
391
421
|
env: server.env.map((variable) => ({
|
|
392
422
|
key: variable.key,
|
|
393
423
|
value: variable.value,
|
|
394
424
|
})),
|
|
425
|
+
url: server.url,
|
|
426
|
+
bearerTokenEnvVar: server.bearerTokenEnvVar,
|
|
427
|
+
httpHeaders: server.httpHeaders.map((header) => ({ ...header })),
|
|
428
|
+
envHttpHeaders: server.envHttpHeaders.map((header) => ({ ...header })),
|
|
395
429
|
enabled: server.enabled,
|
|
396
430
|
})),
|
|
397
431
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doer-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Reverse-polling agent runtime for doer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/agent.js",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
-
"@openai/codex": "^0.144.
|
|
30
|
-
"@openai/codex-sdk": "^0.144.
|
|
29
|
+
"@openai/codex": "^0.144.5",
|
|
30
|
+
"@openai/codex-sdk": "^0.144.5",
|
|
31
31
|
"diff": "^9.0.0",
|
|
32
32
|
"nats": "^2.29.3",
|
|
33
33
|
"tar": "^7.5.15"
|