doer-agent 0.7.4 → 0.7.6
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-app-rpc.js +5 -1
- package/dist/agent-fs-rpc.js +2 -49
- package/dist/agent-http-proxy-rpc.js +231 -0
- package/dist/agent-runtime-utils.js +3 -0
- package/dist/agent.js +9 -1
- package/dist/codex-app-server-client.js +4 -4
- package/dist/codex-app-server-manager.js +2 -2
- package/package.json +1 -1
|
@@ -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-fs-rpc.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
import { StringCodec } from "nats";
|
|
5
|
-
import {
|
|
5
|
+
import { extract as extractTar } from "tar";
|
|
6
6
|
import { validateImageBytes } from "./agent-runtime-utils.js";
|
|
7
7
|
const fsRpcCodec = StringCodec();
|
|
8
8
|
function normalizeFsRpcPath(workspaceRoot, rawPath) {
|
|
@@ -11,13 +11,10 @@ function normalizeFsRpcPath(workspaceRoot, rawPath) {
|
|
|
11
11
|
const useAbsolute = path.isAbsolute(normalizedRaw);
|
|
12
12
|
const rel = normalizedRaw.replace(/^\/+/, "") || ".";
|
|
13
13
|
const abs = useAbsolute ? path.resolve(normalizedRaw) : path.resolve(workspaceRoot, rel);
|
|
14
|
-
if (
|
|
14
|
+
if (abs !== workspaceRoot && !abs.startsWith(workspaceRoot + path.sep)) {
|
|
15
15
|
throw new Error("path escapes workspace root");
|
|
16
16
|
}
|
|
17
17
|
const formatPath = (target) => {
|
|
18
|
-
if (useAbsolute) {
|
|
19
|
-
return target.split(path.sep).join("/") || "/";
|
|
20
|
-
}
|
|
21
18
|
return path.relative(workspaceRoot, target).split(path.sep).join("/") || ".";
|
|
22
19
|
};
|
|
23
20
|
return { abs, formatPath };
|
|
@@ -30,7 +27,6 @@ function parseFsRpcAction(value) {
|
|
|
30
27
|
value === "write_text" ||
|
|
31
28
|
value === "download_file" ||
|
|
32
29
|
value === "delete_path" ||
|
|
33
|
-
value === "archive_dir" ||
|
|
34
30
|
value === "extract_archive") {
|
|
35
31
|
return value;
|
|
36
32
|
}
|
|
@@ -92,18 +88,6 @@ function inferMimeType(filePath) {
|
|
|
92
88
|
function sha256Hex(bytes) {
|
|
93
89
|
return crypto.createHash("sha256").update(bytes).digest("hex");
|
|
94
90
|
}
|
|
95
|
-
async function createTarGzipBuffer(cwd, entries) {
|
|
96
|
-
const stream = createTar({
|
|
97
|
-
cwd,
|
|
98
|
-
gzip: true,
|
|
99
|
-
portable: true,
|
|
100
|
-
}, entries);
|
|
101
|
-
const chunks = [];
|
|
102
|
-
for await (const chunk of stream) {
|
|
103
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
104
|
-
}
|
|
105
|
-
return Buffer.concat(chunks);
|
|
106
|
-
}
|
|
107
91
|
async function executeFsRpc(args) {
|
|
108
92
|
const action = parseFsRpcAction(args.request.action);
|
|
109
93
|
const { abs, formatPath } = normalizeFsRpcPath(args.workspaceRoot, args.request.path);
|
|
@@ -146,37 +130,6 @@ async function executeFsRpc(args) {
|
|
|
146
130
|
total: items.length,
|
|
147
131
|
};
|
|
148
132
|
}
|
|
149
|
-
if (action === "archive_dir") {
|
|
150
|
-
const entry = await stat(abs);
|
|
151
|
-
if (!entry.isDirectory()) {
|
|
152
|
-
throw new Error("path is not a directory");
|
|
153
|
-
}
|
|
154
|
-
const rawArchivePath = typeof args.request.archivePath === "string" ? args.request.archivePath : "";
|
|
155
|
-
if (!rawArchivePath) {
|
|
156
|
-
throw new Error("archivePath is required");
|
|
157
|
-
}
|
|
158
|
-
const archiveTarget = normalizeFsRpcPath(args.workspaceRoot, rawArchivePath);
|
|
159
|
-
try {
|
|
160
|
-
const manifestEntry = await stat(path.join(abs, "SKILL.md"));
|
|
161
|
-
if (!manifestEntry.isFile()) {
|
|
162
|
-
throw new Error("Selected skill directory must contain SKILL.md");
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
throw new Error("Selected skill directory must contain SKILL.md");
|
|
167
|
-
}
|
|
168
|
-
await mkdir(path.dirname(archiveTarget.abs), { recursive: true });
|
|
169
|
-
const archiveBytes = await createTarGzipBuffer(abs, ["."]);
|
|
170
|
-
await writeFile(archiveTarget.abs, archiveBytes);
|
|
171
|
-
const archiveStat = await stat(archiveTarget.abs);
|
|
172
|
-
return {
|
|
173
|
-
ok: true,
|
|
174
|
-
action,
|
|
175
|
-
path: formatPath(abs),
|
|
176
|
-
archivePath: archiveTarget.formatPath(archiveTarget.abs),
|
|
177
|
-
size: archiveStat.size,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
133
|
if (action === "upload_file") {
|
|
181
134
|
const entry = await stat(abs);
|
|
182
135
|
if (!entry.isFile()) {
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { StringCodec } from "nats";
|
|
4
|
+
const proxyRpcCodec = StringCodec();
|
|
5
|
+
const PROXY_ID_PATTERN = /^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$/;
|
|
6
|
+
const MAX_PROXY_BODY_BYTES = 5 * 1024 * 1024;
|
|
7
|
+
function getProxyRegistryPath(workspaceRoot) {
|
|
8
|
+
return path.join(workspaceRoot, ".doer-agent", "http-proxies.json");
|
|
9
|
+
}
|
|
10
|
+
function slugify(value) {
|
|
11
|
+
const slug = value
|
|
12
|
+
.trim()
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
15
|
+
.replace(/^-+|-+$/g, "")
|
|
16
|
+
.replace(/-{2,}/g, "-")
|
|
17
|
+
.slice(0, 32);
|
|
18
|
+
return PROXY_ID_PATTERN.test(slug) ? slug : `p${Date.now().toString(36)}`;
|
|
19
|
+
}
|
|
20
|
+
function normalizeProxyId(value) {
|
|
21
|
+
const id = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
22
|
+
if (!PROXY_ID_PATTERN.test(id)) {
|
|
23
|
+
throw new Error("invalid proxyId");
|
|
24
|
+
}
|
|
25
|
+
return id;
|
|
26
|
+
}
|
|
27
|
+
function normalizeName(value) {
|
|
28
|
+
if (typeof value !== "string") {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const name = value.trim();
|
|
32
|
+
return name ? name.slice(0, 120) : null;
|
|
33
|
+
}
|
|
34
|
+
function normalizeHost(value) {
|
|
35
|
+
const host = typeof value === "string" && value.trim() ? value.trim() : "127.0.0.1";
|
|
36
|
+
if (host !== "127.0.0.1" && host !== "localhost") {
|
|
37
|
+
throw new Error("proxy host must be localhost or 127.0.0.1");
|
|
38
|
+
}
|
|
39
|
+
return host;
|
|
40
|
+
}
|
|
41
|
+
function normalizePort(value) {
|
|
42
|
+
const port = Number(value);
|
|
43
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
44
|
+
throw new Error("port must be between 1 and 65535");
|
|
45
|
+
}
|
|
46
|
+
return port;
|
|
47
|
+
}
|
|
48
|
+
function normalizeMethod(value) {
|
|
49
|
+
const method = typeof value === "string" ? value.trim().toUpperCase() : "GET";
|
|
50
|
+
if (!/^[A-Z]+$/.test(method)) {
|
|
51
|
+
throw new Error("invalid method");
|
|
52
|
+
}
|
|
53
|
+
return method;
|
|
54
|
+
}
|
|
55
|
+
function normalizePath(value) {
|
|
56
|
+
const raw = typeof value === "string" && value ? value : "/";
|
|
57
|
+
return raw.startsWith("/") ? raw : `/${raw}`;
|
|
58
|
+
}
|
|
59
|
+
function normalizeHeaders(value) {
|
|
60
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
const out = {};
|
|
64
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
65
|
+
if (typeof raw !== "string") {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const normalizedKey = key.trim().toLowerCase();
|
|
69
|
+
if (!normalizedKey || normalizedKey === "host" || normalizedKey === "connection") {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
out[normalizedKey] = raw;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
function normalizeProxyRecord(value) {
|
|
77
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const row = value;
|
|
81
|
+
const id = typeof row.id === "string" ? row.id.trim().toLowerCase() : "";
|
|
82
|
+
const host = normalizeHost(row.host);
|
|
83
|
+
const port = Number(row.port);
|
|
84
|
+
const createdAt = typeof row.createdAt === "string" ? row.createdAt : new Date().toISOString();
|
|
85
|
+
const updatedAt = typeof row.updatedAt === "string" ? row.updatedAt : createdAt;
|
|
86
|
+
if (!PROXY_ID_PATTERN.test(id) || !Number.isInteger(port) || port < 1 || port > 65535) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
id,
|
|
91
|
+
name: normalizeName(row.name),
|
|
92
|
+
host,
|
|
93
|
+
port,
|
|
94
|
+
createdAt,
|
|
95
|
+
updatedAt,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async function readProxyRegistry(workspaceRoot) {
|
|
99
|
+
const raw = await readFile(getProxyRegistryPath(workspaceRoot), "utf8").catch(() => "");
|
|
100
|
+
if (!raw) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
const parsed = JSON.parse(raw);
|
|
104
|
+
const rows = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.proxies) ? parsed.proxies : [];
|
|
105
|
+
return rows
|
|
106
|
+
.map((row) => {
|
|
107
|
+
try {
|
|
108
|
+
return normalizeProxyRecord(row);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
.filter((row) => Boolean(row));
|
|
115
|
+
}
|
|
116
|
+
async function writeProxyRegistry(workspaceRoot, proxies) {
|
|
117
|
+
const registryPath = getProxyRegistryPath(workspaceRoot);
|
|
118
|
+
await mkdir(path.dirname(registryPath), { recursive: true });
|
|
119
|
+
await writeFile(registryPath, `${JSON.stringify({ proxies }, null, 2)}\n`, "utf8");
|
|
120
|
+
}
|
|
121
|
+
async function createProxy(workspaceRoot, request) {
|
|
122
|
+
const proxies = await readProxyRegistry(workspaceRoot);
|
|
123
|
+
const name = normalizeName(request.name);
|
|
124
|
+
const port = normalizePort(request.port);
|
|
125
|
+
const host = normalizeHost(request.host);
|
|
126
|
+
const requestedId = typeof request.proxyId === "string" && request.proxyId.trim()
|
|
127
|
+
? normalizeProxyId(request.proxyId)
|
|
128
|
+
: slugify(name || `p-${port}`);
|
|
129
|
+
let id = requestedId;
|
|
130
|
+
for (let index = 2; proxies.some((proxy) => proxy.id === id); index += 1) {
|
|
131
|
+
id = `${requestedId.slice(0, 26)}-${index}`;
|
|
132
|
+
}
|
|
133
|
+
const now = new Date().toISOString();
|
|
134
|
+
const proxy = {
|
|
135
|
+
id,
|
|
136
|
+
name,
|
|
137
|
+
host,
|
|
138
|
+
port,
|
|
139
|
+
createdAt: now,
|
|
140
|
+
updatedAt: now,
|
|
141
|
+
};
|
|
142
|
+
await writeProxyRegistry(workspaceRoot, [...proxies, proxy].sort((a, b) => b.createdAt.localeCompare(a.createdAt)));
|
|
143
|
+
return proxy;
|
|
144
|
+
}
|
|
145
|
+
async function deleteProxy(workspaceRoot, proxyId) {
|
|
146
|
+
const proxies = await readProxyRegistry(workspaceRoot);
|
|
147
|
+
await writeProxyRegistry(workspaceRoot, proxies.filter((proxy) => proxy.id !== proxyId));
|
|
148
|
+
}
|
|
149
|
+
async function handleProxyFetch(workspaceRoot, request) {
|
|
150
|
+
const proxyId = normalizeProxyId(request.proxyId);
|
|
151
|
+
const proxy = (await readProxyRegistry(workspaceRoot)).find((item) => item.id === proxyId);
|
|
152
|
+
if (!proxy) {
|
|
153
|
+
throw new Error("proxy not found");
|
|
154
|
+
}
|
|
155
|
+
const method = normalizeMethod(request.method);
|
|
156
|
+
const requestPath = normalizePath(request.path);
|
|
157
|
+
const headers = normalizeHeaders(request.headers);
|
|
158
|
+
const bodyBase64 = typeof request.bodyBase64 === "string" ? request.bodyBase64 : "";
|
|
159
|
+
const body = bodyBase64 ? Buffer.from(bodyBase64, "base64") : undefined;
|
|
160
|
+
if ((body?.byteLength ?? 0) > MAX_PROXY_BODY_BYTES) {
|
|
161
|
+
throw new Error("proxy request body too large");
|
|
162
|
+
}
|
|
163
|
+
const url = new URL(requestPath, `http://${proxy.host}:${proxy.port}`);
|
|
164
|
+
const response = await fetch(url, {
|
|
165
|
+
method,
|
|
166
|
+
headers,
|
|
167
|
+
body: method === "GET" || method === "HEAD" ? undefined : body,
|
|
168
|
+
redirect: "manual",
|
|
169
|
+
});
|
|
170
|
+
const responseBuffer = Buffer.from(await response.arrayBuffer());
|
|
171
|
+
if (responseBuffer.byteLength > MAX_PROXY_BODY_BYTES) {
|
|
172
|
+
throw new Error("proxy response body too large");
|
|
173
|
+
}
|
|
174
|
+
const responseHeaders = {};
|
|
175
|
+
response.headers.forEach((value, key) => {
|
|
176
|
+
responseHeaders[key] = value;
|
|
177
|
+
});
|
|
178
|
+
return {
|
|
179
|
+
status: response.status,
|
|
180
|
+
statusText: response.statusText,
|
|
181
|
+
headers: responseHeaders,
|
|
182
|
+
bodyBase64: responseBuffer.toString("base64"),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async function executeProxyRpc(args) {
|
|
186
|
+
const action = args.request.action === "create" || args.request.action === "delete" || args.request.action === "handle"
|
|
187
|
+
? args.request.action
|
|
188
|
+
: "list";
|
|
189
|
+
if (action === "list") {
|
|
190
|
+
return { ok: true, action, proxies: await readProxyRegistry(args.workspaceRoot) };
|
|
191
|
+
}
|
|
192
|
+
if (action === "create") {
|
|
193
|
+
return { ok: true, action, proxy: await createProxy(args.workspaceRoot, args.request) };
|
|
194
|
+
}
|
|
195
|
+
if (action === "delete") {
|
|
196
|
+
await deleteProxy(args.workspaceRoot, normalizeProxyId(args.request.proxyId));
|
|
197
|
+
return { ok: true, action };
|
|
198
|
+
}
|
|
199
|
+
return { ok: true, action, response: await handleProxyFetch(args.workspaceRoot, args.request) };
|
|
200
|
+
}
|
|
201
|
+
export async function handleHttpProxyRpcMessage(args) {
|
|
202
|
+
let requestId = "unknown";
|
|
203
|
+
try {
|
|
204
|
+
const request = JSON.parse(proxyRpcCodec.decode(args.msg.data));
|
|
205
|
+
requestId = typeof request.requestId === "string" ? request.requestId : "unknown";
|
|
206
|
+
const payload = await executeProxyRpc({ workspaceRoot: args.workspaceRoot, request });
|
|
207
|
+
args.msg.respond(proxyRpcCodec.encode(JSON.stringify({ requestId, ...payload })));
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
211
|
+
args.onError?.(`http proxy rpc failed requestId=${requestId} error=${message}`);
|
|
212
|
+
args.msg.respond(proxyRpcCodec.encode(JSON.stringify({ requestId, ok: false, error: message })));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export function subscribeToHttpProxyRpc(args) {
|
|
216
|
+
args.nc.subscribe(args.subject, {
|
|
217
|
+
callback: (error, msg) => {
|
|
218
|
+
if (error) {
|
|
219
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
220
|
+
args.onError(`http proxy rpc subscription error: ${message}`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
void handleHttpProxyRpcMessage({
|
|
224
|
+
msg,
|
|
225
|
+
workspaceRoot: args.workspaceRoot,
|
|
226
|
+
onError: args.onError,
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
args.onInfo(`http proxy rpc subscribed subject=${args.subject}`);
|
|
231
|
+
}
|
|
@@ -25,6 +25,9 @@ export function buildAgentFsRpcSubject(userId, agentId) {
|
|
|
25
25
|
export function buildAgentDaemonRpcSubject(userId, agentId) {
|
|
26
26
|
return `doer.agent.daemon.rpc.${sanitizeUserId(userId)}.${agentId.trim()}`;
|
|
27
27
|
}
|
|
28
|
+
export function buildAgentHttpProxyRpcSubject(userId, agentId) {
|
|
29
|
+
return `doer.agent.http.proxy.rpc.${sanitizeUserId(userId)}.${agentId.trim()}`;
|
|
30
|
+
}
|
|
28
31
|
export function buildAgentMaintenanceRpcSubject(userId, agentId) {
|
|
29
32
|
return `doer.agent.maintenance.rpc.${sanitizeUserId(userId)}.${agentId.trim()}`;
|
|
30
33
|
}
|
package/dist/agent.js
CHANGED
|
@@ -13,8 +13,9 @@ import { connectBootstrapWithRetry } from "./agent-jetstream.js";
|
|
|
13
13
|
import { runConnectedAgentSession } from "./agent-session-loop.js";
|
|
14
14
|
import { subscribeToSkillRpc } from "./agent-skill-rpc.js";
|
|
15
15
|
import { subscribeToMaintenanceRpc } from "./agent-maintenance-rpc.js";
|
|
16
|
+
import { subscribeToHttpProxyRpc } from "./agent-http-proxy-rpc.js";
|
|
16
17
|
import { sendSignalToTaskProcess } from "./agent-task-execution.js";
|
|
17
|
-
import { buildAgentCodexAppEventsSubject, buildAgentCodexAppRpcSubject, buildAgentDaemonRpcSubject, buildAgentFsRpcSubject, buildAgentGitRpcSubject, buildAgentMaintenanceRpcSubject, buildAgentSettingsRpcSubject, buildAgentSkillRpcSubject, formatLocalTimestamp, parseArgs, resolveAgentVersion, resolveArgOrEnv, resolveContainerReachableServerBaseUrl, sanitizeUserId, sleep, } from "./agent-runtime-utils.js";
|
|
18
|
+
import { buildAgentCodexAppEventsSubject, buildAgentCodexAppRpcSubject, buildAgentDaemonRpcSubject, buildAgentFsRpcSubject, buildAgentGitRpcSubject, buildAgentHttpProxyRpcSubject, buildAgentMaintenanceRpcSubject, buildAgentSettingsRpcSubject, buildAgentSkillRpcSubject, formatLocalTimestamp, parseArgs, resolveAgentVersion, resolveArgOrEnv, resolveContainerReachableServerBaseUrl, sanitizeUserId, sleep, } from "./agent-runtime-utils.js";
|
|
18
19
|
import { createRuntimeEnvHelpers } from "./agent-runtime-env.js";
|
|
19
20
|
import { createEventPersistenceHelpers, heartbeatAgentSession, postJson, } from "./agent-runtime-io.js";
|
|
20
21
|
import { handleSettingsRpcMessage } from "./agent-settings-rpc.js";
|
|
@@ -306,6 +307,13 @@ async function main() {
|
|
|
306
307
|
onInfo: writeAgentInfo,
|
|
307
308
|
onError: writeAgentError,
|
|
308
309
|
});
|
|
310
|
+
subscribeToHttpProxyRpc({
|
|
311
|
+
nc: jetstream.nc,
|
|
312
|
+
subject: buildAgentHttpProxyRpcSubject(userId, initialAgentId),
|
|
313
|
+
workspaceRoot: resolveWorkspaceRoot(),
|
|
314
|
+
onInfo: writeAgentInfo,
|
|
315
|
+
onError: writeAgentError,
|
|
316
|
+
});
|
|
309
317
|
},
|
|
310
318
|
onInfraError: writeAgentInfraError,
|
|
311
319
|
sleep,
|
|
@@ -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);
|
|
@@ -117,9 +117,9 @@ export function createCodexAppServerManager(args) {
|
|
|
117
117
|
}
|
|
118
118
|
};
|
|
119
119
|
return {
|
|
120
|
-
async request(method, params) {
|
|
120
|
+
async request(method, params, timeoutMs) {
|
|
121
121
|
const activeClient = await getClient();
|
|
122
|
-
return await activeClient.request(method, params);
|
|
122
|
+
return await activeClient.request(method, params, timeoutMs);
|
|
123
123
|
},
|
|
124
124
|
async restart(reason) {
|
|
125
125
|
generation += 1;
|