baa-conductor


baa-conductor / apps / conductor-daemon / src / instructions
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}