codex@macbookpro
·
2026-03-31
executor.ts
1import { buildArtifactPublicUrl } from "../../../../packages/artifact-db/dist/index.js";
2import {
3 handleConductorHttpRequest,
4 type ConductorLocalApiContext
5} from "../local-api.js";
6import type { ConductorHttpRequest, ConductorHttpResponse } from "../http-types.js";
7import {
8 DEFAULT_BAA_EXEC_INSTRUCTION_TIMEOUT_MS,
9 DEFAULT_BAA_INSTRUCTION_TIMEOUT_MS,
10 withAbortableTimeout
11} from "../execution-timeouts.js";
12import type {
13 BaaInstructionEnvelope,
14 BaaInstructionExecutionResult,
15 BaaInstructionRoute,
16 BaaJsonObject,
17 BaaJsonValue
18} from "./types.js";
19import { isBaaJsonValue } from "./types.js";
20
21export interface ExecuteBaaInstructionOptions {
22 requestHandler?: (
23 request: ConductorHttpRequest,
24 context: ConductorLocalApiContext
25 ) => Promise<ConductorHttpResponse>;
26}
27
28class BaaInstructionExecutionTimeoutError extends Error {
29 readonly timeoutMs: number;
30
31 constructor(timeoutMs: number) {
32 super(`Local instruction execution timed out after ${timeoutMs}ms.`);
33 this.timeoutMs = timeoutMs;
34 }
35}
36
37function toExecutionFailure(
38 instruction: BaaInstructionEnvelope,
39 route: BaaInstructionRoute,
40 message: string,
41 error = "execution_failed",
42 details: BaaJsonValue | null = null,
43 httpStatus = 500
44): BaaInstructionExecutionResult {
45 return {
46 artifact: null,
47 data: null,
48 dedupeKey: instruction.dedupeKey,
49 details,
50 error,
51 httpStatus,
52 instructionId: instruction.instructionId,
53 message,
54 ok: false,
55 requestId: null,
56 route: {
57 key: route.key,
58 method: route.method,
59 path: route.path
60 },
61 target: instruction.target,
62 tool: instruction.tool
63 };
64}
65
66function resolveExecutionTimeoutMs(route: BaaInstructionRoute): number {
67 if (Number.isInteger(route.timeoutMs) && route.timeoutMs > 0) {
68 return route.timeoutMs;
69 }
70
71 return route.key === "local.exec"
72 ? DEFAULT_BAA_EXEC_INSTRUCTION_TIMEOUT_MS
73 : DEFAULT_BAA_INSTRUCTION_TIMEOUT_MS;
74}
75
76function normalizeJsonBodyValue(value: unknown): BaaJsonValue | null {
77 return isBaaJsonValue(value) ? value : null;
78}
79
80function normalizeOptionalString(value: string | null | undefined): string | null {
81 if (typeof value !== "string") {
82 return null;
83 }
84
85 const normalized = value.trim();
86 return normalized === "" ? null : normalized;
87}
88
89function stringifyArtifactValue(value: BaaJsonValue | null): string | null {
90 if (value == null) {
91 return null;
92 }
93
94 if (typeof value === "string") {
95 return value.trim() === "" ? null : value;
96 }
97
98 return JSON.stringify(value, null, 2);
99}
100
101function buildExecutionArtifactPayload(result: BaaInstructionExecutionResult): BaaJsonObject {
102 const payload: BaaJsonObject = {
103 http_status: result.httpStatus,
104 ok: result.ok,
105 route: {
106 key: result.route.key,
107 method: result.route.method,
108 path: result.route.path
109 }
110 };
111
112 if (result.data != null) {
113 payload.data = result.data;
114 }
115
116 if (result.details != null) {
117 payload.details = result.details;
118 }
119
120 if (result.error != null) {
121 payload.error = result.error;
122 }
123
124 if (result.message != null) {
125 payload.message = result.message;
126 }
127
128 if (result.requestId != null) {
129 payload.request_id = result.requestId;
130 }
131
132 return payload;
133}
134
135function buildExecutionArtifactError(result: BaaInstructionExecutionResult): string | null {
136 const values = [normalizeOptionalString(result.message), normalizeOptionalString(result.error)]
137 .filter((value, index, all): value is string => value != null && all.indexOf(value) === index);
138
139 return values.length === 0 ? null : values.join("\n");
140}
141
142function logArtifactPersistenceFailure(instructionId: string, error: unknown): void {
143 const message = error instanceof Error ? error.stack ?? error.message : String(error);
144 console.error(`[artifact] failed to persist execution ${instructionId}: ${message}`);
145}
146
147function logInstructionExecutionTimeout(
148 instruction: BaaInstructionEnvelope,
149 route: BaaInstructionRoute,
150 timeoutMs: number
151): void {
152 console.warn(
153 `[baa-executor] execution_timeout instruction=${instruction.instructionId} route=${route.key} `
154 + `target=${instruction.target} tool=${instruction.tool} timeout_ms=${timeoutMs}`
155 );
156}
157
158async function withExecutionArtifact(
159 result: BaaInstructionExecutionResult,
160 instruction: BaaInstructionEnvelope,
161 context: ConductorLocalApiContext
162): Promise<BaaInstructionExecutionResult> {
163 const resultData = buildExecutionArtifactPayload(result);
164 const resultError = buildExecutionArtifactError(result);
165 const fallbackArtifact = {
166 resultText: stringifyArtifactValue(resultData) ?? resultError,
167 url: null
168 };
169 const artifactStore = context.artifactStore ?? null;
170
171 if (artifactStore == null) {
172 return {
173 ...result,
174 artifact: fallbackArtifact
175 };
176 }
177
178 try {
179 const record = await artifactStore.insertExecution({
180 executedAt: Date.now(),
181 httpStatus: result.httpStatus,
182 instructionId: result.instructionId,
183 messageId: instruction.assistantMessageId,
184 params: instruction.params,
185 paramsKind: instruction.paramsKind,
186 resultData,
187 resultError,
188 resultOk: result.ok,
189 target: instruction.target,
190 tool: instruction.tool
191 });
192
193 return {
194 ...result,
195 artifact: {
196 resultText: record.resultData ?? record.resultError,
197 url: buildArtifactPublicUrl(artifactStore.getPublicBaseUrl(), record.staticPath)
198 }
199 };
200 } catch (error) {
201 logArtifactPersistenceFailure(result.instructionId, error);
202
203 return {
204 ...result,
205 artifact: fallbackArtifact
206 };
207 }
208}
209
210export async function executeBaaInstruction(
211 instruction: BaaInstructionEnvelope,
212 route: BaaInstructionRoute,
213 context: ConductorLocalApiContext,
214 options: ExecuteBaaInstructionOptions = {}
215): Promise<BaaInstructionExecutionResult> {
216 try {
217 const timeoutMs = resolveExecutionTimeoutMs(route);
218 const headers: Record<string, string> = {
219 "content-type": "application/json"
220 };
221
222 if (route.requiresSharedToken && context.sharedToken) {
223 headers.authorization = `Bearer ${context.sharedToken}`;
224 }
225
226 const requestHandler = options.requestHandler ?? handleConductorHttpRequest;
227 const response = await withAbortableTimeout(
228 timeoutMs,
229 () => new BaaInstructionExecutionTimeoutError(timeoutMs),
230 (signal) => requestHandler(
231 {
232 body: route.body == null ? null : JSON.stringify(route.body),
233 headers,
234 method: route.method,
235 path: route.path,
236 signal
237 },
238 context
239 )
240 );
241
242 let parsedBody: unknown = null;
243 const responseText =
244 typeof response.body === "string"
245 ? response.body
246 : new TextDecoder().decode(response.body);
247
248 try {
249 parsedBody = responseText.trim() === "" ? null : JSON.parse(responseText);
250 } catch (error) {
251 const message = error instanceof Error ? error.message : String(error);
252 return withExecutionArtifact(
253 toExecutionFailure(
254 instruction,
255 route,
256 `Failed to parse local API response JSON: ${message}`,
257 "invalid_local_api_response",
258 normalizeJsonBodyValue(responseText)
259 ),
260 instruction,
261 context
262 );
263 }
264
265 const payload =
266 parsedBody != null && typeof parsedBody === "object" && !Array.isArray(parsedBody)
267 ? (parsedBody as Record<string, unknown>)
268 : null;
269
270 return withExecutionArtifact({
271 artifact: null,
272 data: payload?.ok === true ? normalizeJsonBodyValue(payload.data) : null,
273 dedupeKey: instruction.dedupeKey,
274 details: normalizeJsonBodyValue(payload?.details),
275 error: payload?.ok === false && typeof payload.error === "string" ? payload.error : null,
276 httpStatus: response.status,
277 instructionId: instruction.instructionId,
278 message: typeof payload?.message === "string" ? payload.message : null,
279 ok: payload?.ok === true,
280 requestId: typeof payload?.request_id === "string" ? payload.request_id : null,
281 route: {
282 key: route.key,
283 method: route.method,
284 path: route.path
285 },
286 target: instruction.target,
287 tool: instruction.tool
288 }, instruction, context);
289 } catch (error) {
290 if (error instanceof BaaInstructionExecutionTimeoutError) {
291 logInstructionExecutionTimeout(instruction, route, error.timeoutMs);
292 return withExecutionArtifact(
293 toExecutionFailure(
294 instruction,
295 route,
296 error.message,
297 "execution_timeout",
298 {
299 timeout_ms: error.timeoutMs
300 },
301 504
302 ),
303 instruction,
304 context
305 );
306 }
307
308 const message = error instanceof Error ? error.message : String(error);
309 return withExecutionArtifact(toExecutionFailure(instruction, route, message), instruction, context);
310 }
311}