/* oxlint-disable executor/no-try-catch-or-throw, executor/no-double-cast, executor/no-instanceof-tagged-error, executor/no-error-constructor -- boundary: Worker Loader RPC adapter converts worker envelopes into typed AppExecutorError */import { Effect } from "effect"; import { stableStringify } from "../pipeline/descriptor";import { AppExecutorError, type AppToolBridge, type AppToolExecutor, type CollectedModule, type InvokeOutcome,} from "./app-tool-executor"; type DynamicWorkerDefinition = { readonly compatibilityDate: string; readonly compatibilityFlags?: string[]; readonly mainModule: string; readonly modules: Readonly<Record<string, string>>; readonly globalOutbound?: null;}; type DynamicWorkerLoader = { readonly get: ( name: string, factory: () => DynamicWorkerDefinition, ) => { readonly getEntrypoint: () => unknown };}; type DynamicAppEntrypoint = { readonly collect: (input: { readonly fileSlug: string; readonly sourcePath: string; }) => Promise<WorkerEnvelope<CollectedModule>>; readonly invoke: ( input: { readonly toolName: string; readonly input: unknown; readonly timeoutMs: number; }, bridge: AppToolBridge, ) => Promise<WorkerEnvelope<InvokeOutcome>>;}; type WorkerSuccess<T> = { readonly ok: true; readonly value: T;}; type WorkerFailure = { readonly ok: false; readonly kind: AppExecutorError["kind"]; readonly message: string; readonly diagnostics?: readonly { readonly path: string; readonly message: string }[]; readonly cause?: unknown;}; type WorkerEnvelope<T> = WorkerSuccess<T> | WorkerFailure; export interface DynamicWorkerAppToolExecutorOptions { readonly loader: DynamicWorkerLoader;} const toAppExecutorError = (failure: WorkerFailure, fallbackKind: AppExecutorError["kind"]) => new AppExecutorError({ kind: failure.kind ?? fallbackKind, message: failure.message, ...(failure.diagnostics ? { diagnostics: failure.diagnostics } : {}), ...(failure.cause === undefined ? {} : { cause: failure.cause }), }); const mapCause = (cause: unknown, kind: AppExecutorError["kind"], message: string) => cause instanceof AppExecutorError ? cause : new AppExecutorError({ kind, message, cause, }); const appWorkerModule = (): string => `import { WorkerEntrypoint } from "cloudflare:workers";import artifact from "./app.js"; const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);const validToolKey = (value) => /^[a-z][a-z0-9-]*(?:_[a-z0-9-]+)*$/.test(value);const stableStringify = (value) => { const seen = new WeakSet(); const walk = (v) => { if (v === null || typeof v !== "object") return v; if (seen.has(v)) return "[Circular]"; seen.add(v); if (Array.isArray(v)) return v.map(walk); const out = {}; for (const key of Object.keys(v).sort()) { const inner = v[key]; if (inner !== undefined) out[key] = walk(inner); } return out; }; return JSON.stringify(walk(value));};const issue = (path, message) => ({ path, message });const fail = (kind, message, diagnostics, cause) => ({ __appExecutorFailure: true, kind, message, diagnostics, cause });const isDefinedTool = (value) => isRecord(value) && value["~executorAppTool"] === true && typeof value.description === "string" && "input" in value && typeof value.handler === "function";const resolveDefault = async () => typeof artifact === "function" ? await artifact() : artifact;const integrationDeclaration = (value) => { if (!isRecord(value) || value.kind !== "integration") return null; if (typeof value.slug !== "string" || (value.mode !== "one" && value.mode !== "many")) return null; return { slug: value.slug, mode: value.mode, ...(typeof value.description === "string" ? { description: value.description } : {}) };};const jsonSchemaFor = (schema, side, toolName, sourcePath) => { if (schema === undefined) return undefined; if (!isRecord(schema) || !isRecord(schema["~standard"])) return schema; const jsonSchema = schema["~standard"].jsonSchema; if (!isRecord(jsonSchema) || typeof jsonSchema[side] !== "function") { throw fail("collect", 'tool "' + toolName + '" ' + side + ' schema library does not expose the Standard Schema jsonSchema extension', [issue(sourcePath, side + " schema library does not expose the Standard Schema jsonSchema extension")]); } try { const converted = jsonSchema[side]({ target: "draft-2020-12" }); if (!isRecord(converted)) return converted; const { $schema: _metaSchema, ...withoutMetaSchema } = converted; return withoutMetaSchema; } catch (cause) { throw fail("collect", 'tool "' + toolName + '" ' + side + ' schema conversion failed', [issue(sourcePath, side + " schema conversion failed")], cause); }};const collectIntegrations = (toolName, sourcePath, declarations, inputJsonSchema) => { if (declarations === undefined) return {}; if (!isRecord(declarations)) throw fail("collect", 'tool "' + toolName + '" integrations must be a record', [issue(sourcePath, "integrations must be a record")]); const inputProperties = isRecord(inputJsonSchema) && isRecord(inputJsonSchema.properties) ? inputJsonSchema.properties : {}; const out = {}; for (const [field, raw] of Object.entries(declarations)) { if (Object.prototype.hasOwnProperty.call(inputProperties, field)) throw fail("collect", 'tool "' + toolName + '" integration key "' + field + '" collides with input field', [issue(sourcePath, "integration key collides with input: " + field)]); const decl = integrationDeclaration(raw); if (!decl) throw fail("collect", 'tool "' + toolName + '" integration "' + field + '" is not a valid declaration', [issue(sourcePath, "invalid integration declaration: " + field)]); out[field] = decl; } return out;};const projectInputSchema = (inputJsonSchema, integrations) => { const base = isRecord(inputJsonSchema) ? inputJsonSchema : {}; const properties = isRecord(base.properties) ? { ...base.properties } : {}; const required = Array.isArray(base.required) ? [...base.required] : []; for (const [field, decl] of Object.entries(integrations)) { properties[field] = decl.mode === "one" ? { type: "string", description: decl.description ?? "Connection for " + decl.slug } : { type: "array", items: { type: "string" }, description: decl.description ?? "Connections for " + decl.slug }; required.push(field); } return { ...base, type: "object", properties, ...(required.length > 0 ? { required: [...new Set(required)] } : {}) };};const collectFromExport = (exported, fileSlug, sourcePath) => { if (isDefinedTool(exported)) { const inputJsonSchema = jsonSchemaFor(exported.input, "input", fileSlug, sourcePath); const integrations = collectIntegrations(fileSlug, sourcePath, exported.integrations, inputJsonSchema); return { tools: [{ toolName: fileSlug, description: exported.description, integrations, inputSchema: projectInputSchema(inputJsonSchema, integrations), outputSchema: jsonSchemaFor(exported.output, "output", fileSlug, sourcePath), annotations: exported.annotations }] }; } if (!isRecord(exported)) throw fail("collect", "default export in " + sourcePath + " must be a tool, record, or factory", [issue(sourcePath, "unsupported default export")]); const tools = []; const seen = new Set(); if (isDefinedTool(exported[fileSlug])) throw fail("collect", 'record export key "' + fileSlug + '" collides with single tool name', [issue(sourcePath, 'record key "' + fileSlug + '" is reserved')]); for (const [key, value] of Object.entries(exported)) { if (!isDefinedTool(value)) continue; if (!validToolKey(key)) throw fail("collect", 'record export key "' + key + '" is not a valid tool slug', [issue(sourcePath, "invalid record key " + key)]); const toolName = fileSlug + "__" + key; if (seen.has(toolName)) throw fail("collect", 'duplicate tool name "' + toolName + '"', [issue(sourcePath, "duplicate tool name " + toolName)]); const inputJsonSchema = jsonSchemaFor(value.input, "input", toolName, sourcePath); const integrations = collectIntegrations(toolName, sourcePath, value.integrations, inputJsonSchema); seen.add(toolName); tools.push({ toolName, exportKey: key, description: value.description, integrations, inputSchema: projectInputSchema(inputJsonSchema, integrations), outputSchema: jsonSchemaFor(value.output, "output", toolName, sourcePath), annotations: value.annotations }); } if (tools.length === 0) throw fail("collect", "record export in " + sourcePath + " contains no defineTool entries", [issue(sourcePath, "no tools found")]); return { tools };};const selectTool = (exported, entry) => { if (isDefinedTool(exported)) return exported; if (!isRecord(exported)) return null; const index = entry.indexOf("__"); return index === -1 ? null : exported[entry.slice(index + 2)];};const validateStandard = async (schema, value, field) => { if (!isRecord(schema) || !isRecord(schema["~standard"]) || typeof schema["~standard"].validate !== "function") return value; const result = await schema["~standard"].validate(value); if (isRecord(result) && "issues" in result && Array.isArray(result.issues)) throw fail(field === "input" ? "input_validation" : "output_validation", field + " validation failed", undefined, result.issues); return isRecord(result) && "value" in result ? result.value : value;};const makeClient = (bridge, root, prefix = []) => new Proxy(() => undefined, { get(_target, prop) { if (prop === "then" || typeof prop === "symbol") return undefined; return makeClient(bridge, root, [...prefix, String(prop)]); }, async apply(_target, _thisArg, args) { return await bridge.call(root + "." + prefix.join("."), args[0] ?? {}); },});const splitInvokeInput = (bridge, toolName, input, integrations) => { const payload = isRecord(input) ? input : {}; const dataInput = { ...payload }; const handles = {}; for (const [field, decl] of Object.entries(integrations)) { const raw = payload[field]; delete dataInput[field]; if (decl.mode === "one") { if (typeof raw !== "string" || raw.length === 0) throw fail("input_validation", 'tool "' + toolName + '" integration "' + field + '" must be a connection address'); handles[field] = makeClient(bridge, field); } else { if (!Array.isArray(raw) || raw.some((item) => typeof item !== "string" || item.length === 0)) throw fail("input_validation", 'tool "' + toolName + '" integration "' + field + '" must be connection addresses'); handles[field] = raw.map((_address, index) => makeClient(bridge, field + "#" + index)); } } return { input: dataInput, integrations: handles };};const serializeFailure = (error, fallbackKind) => { if (isRecord(error) && error.__appExecutorFailure === true) return { ok: false, kind: error.kind, message: error.message, diagnostics: error.diagnostics, cause: error.cause }; return { ok: false, kind: fallbackKind, message: error && error.message ? error.message : String(error) };}; export default class AppExecutor extends WorkerEntrypoint { async collect(input) { try { const first = collectFromExport(await resolveDefault(), input.fileSlug, input.sourcePath); const second = collectFromExport(await resolveDefault(), input.fileSlug, input.sourcePath); if (stableStringify(first) !== stableStringify(second)) throw fail("nondeterministic", "collect for " + input.sourcePath + " is nondeterministic", [issue(input.sourcePath, "factory output changed between runs")]); return { ok: true, value: first }; } catch (error) { return serializeFailure(error, "collect"); } } async invoke(input, bridge) { try { const invoke = async () => { const exported = await resolveDefault(); const tool = selectTool(exported, input.toolName); if (!isDefinedTool(tool)) throw fail("invoke", "tool not found in bundle: " + input.toolName); const inputJsonSchema = jsonSchemaFor(tool.input, "input", input.toolName, input.toolName); const integrations = collectIntegrations(input.toolName, input.toolName, tool.integrations, inputJsonSchema); const split = splitInvokeInput(bridge, input.toolName, input.input, integrations); const decoded = await validateStandard(tool.input, split.input, "input"); const output = await tool.handler(decoded, split.integrations); return { output: await validateStandard(tool.output, output, "output") }; }; const value = await Promise.race([ invoke(), new Promise((_, reject) => setTimeout(() => reject(fail("timeout", "app tool timed out after " + input.timeoutMs + "ms")), input.timeoutMs)), ]); return { ok: true, value }; } catch (error) { return serializeFailure(error, "invoke"); } }}`; const asEntrypoint = (value: unknown): DynamicAppEntrypoint => value as DynamicAppEntrypoint; const startWorker = (loader: DynamicWorkerLoader, bundle: string): DynamicAppEntrypoint => asEntrypoint( loader .get(`app-tool-${crypto.randomUUID()}`, () => ({ compatibilityDate: "2025-06-01", compatibilityFlags: ["nodejs_compat"], mainModule: "driver.js", modules: { "driver.js": appWorkerModule(), "app.js": bundle, }, globalOutbound: null, })) .getEntrypoint(), ); export const makeDynamicWorkerAppToolExecutor = ( options: DynamicWorkerAppToolExecutorOptions,): AppToolExecutor => ({ collect: (bundle, input) => Effect.tryPromise({ try: async () => { const response = await startWorker(options.loader, bundle).collect(input); if (!response.ok) throw toAppExecutorError(response, "collect"); if (!stableStringify(response.value)) throw new Error(`collect failed for ${input.sourcePath}`); return response.value; }, catch: (cause) => mapCause(cause, "collect", `collect failed for ${input.sourcePath}`), }), invoke: (bundle, entry, input, bridge, limits) => Effect.tryPromise({ try: async () => { const response = await startWorker(options.loader, bundle).invoke( { toolName: entry.toolName, input, timeoutMs: limits.timeoutMs }, bridge, ); if (!response.ok) throw toAppExecutorError(response, "invoke"); return response.value; }, catch: (cause) => mapCause(cause, "invoke", "app tool invocation failed"), }),});
/* oxlint-disable executor/no-try-catch-or-throw, executor/no-double-cast, executor/no-instanceof-tagged-error, executor/no-error-constructor -- boundary: Worker Loader RPC adapter converts worker envelopes into typed AppExecutorError */
import { Effect } from "effect";
import { stableStringify } from "../pipeline/descriptor";
import {
AppExecutorError,
type AppToolBridge,
type AppToolExecutor,
type CollectedModule,
type InvokeOutcome,
} from "./app-tool-executor";
type DynamicWorkerDefinition = {
readonly compatibilityDate: string;
readonly compatibilityFlags?: string[];
readonly mainModule: string;
readonly modules: Readonly<Record<string, string>>;
readonly globalOutbound?: null;
};
type DynamicWorkerLoader = {
readonly get: (
name: string,
factory: () => DynamicWorkerDefinition,
) => { readonly getEntrypoint: () => unknown };
};
type DynamicAppEntrypoint = {
readonly collect: (input: {
readonly fileSlug: string;
readonly sourcePath: string;
}) => Promise<WorkerEnvelope<CollectedModule>>;
readonly invoke: (
input: {
readonly toolName: string;
readonly input: unknown;
readonly timeoutMs: number;
},
bridge: AppToolBridge,
) => Promise<WorkerEnvelope<InvokeOutcome>>;
};
type WorkerSuccess<T> = {
readonly ok: true;
readonly value: T;
};
type WorkerFailure = {
readonly ok: false;
readonly kind: AppExecutorError["kind"];
readonly message: string;
readonly diagnostics?: readonly { readonly path: string; readonly message: string }[];
readonly cause?: unknown;
};
type WorkerEnvelope<T> = WorkerSuccess<T> | WorkerFailure;
export interface DynamicWorkerAppToolExecutorOptions {
readonly loader: DynamicWorkerLoader;
}
const toAppExecutorError = (failure: WorkerFailure, fallbackKind: AppExecutorError["kind"]) =>
new AppExecutorError({
kind: failure.kind ?? fallbackKind,
message: failure.message,
...(failure.diagnostics ? { diagnostics: failure.diagnostics } : {}),
...(failure.cause === undefined ? {} : { cause: failure.cause }),
});
const mapCause = (cause: unknown, kind: AppExecutorError["kind"], message: string) =>
cause instanceof AppExecutorError
? cause
: new AppExecutorError({
kind,
message,
cause,
});
const appWorkerModule = (): string => `
import { WorkerEntrypoint } from "cloudflare:workers";
import artifact from "./app.js";
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
const validToolKey = (value) => /^[a-z][a-z0-9-]*(?:_[a-z0-9-]+)*$/.test(value);
const stableStringify = (value) => {
const seen = new WeakSet();
const walk = (v) => {
if (v === null || typeof v !== "object") return v;
if (seen.has(v)) return "[Circular]";
seen.add(v);
if (Array.isArray(v)) return v.map(walk);
const out = {};
for (const key of Object.keys(v).sort()) {
const inner = v[key];
if (inner !== undefined) out[key] = walk(inner);
}
return out;
};
return JSON.stringify(walk(value));
};
const issue = (path, message) => ({ path, message });
const fail = (kind, message, diagnostics, cause) => ({ __appExecutorFailure: true, kind, message, diagnostics, cause });
const isDefinedTool = (value) =>
isRecord(value) &&
value["~executorAppTool"] === true &&
typeof value.description === "string" &&
"input" in value &&
typeof value.handler === "function";
const resolveDefault = async () => typeof artifact === "function" ? await artifact() : artifact;
const integrationDeclaration = (value) => {
if (!isRecord(value) || value.kind !== "integration") return null;
if (typeof value.slug !== "string" || (value.mode !== "one" && value.mode !== "many")) return null;
return { slug: value.slug, mode: value.mode, ...(typeof value.description === "string" ? { description: value.description } : {}) };
};
const jsonSchemaFor = (schema, side, toolName, sourcePath) => {
if (schema === undefined) return undefined;
if (!isRecord(schema) || !isRecord(schema["~standard"])) return schema;
const jsonSchema = schema["~standard"].jsonSchema;
if (!isRecord(jsonSchema) || typeof jsonSchema[side] !== "function") {
throw fail("collect", 'tool "' + toolName + '" ' + side + ' schema library does not expose the Standard Schema jsonSchema extension', [issue(sourcePath, side + " schema library does not expose the Standard Schema jsonSchema extension")]);
}
try {
const converted = jsonSchema[side]({ target: "draft-2020-12" });
if (!isRecord(converted)) return converted;
const { $schema: _metaSchema, ...withoutMetaSchema } = converted;
return withoutMetaSchema;
} catch (cause) {
throw fail("collect", 'tool "' + toolName + '" ' + side + ' schema conversion failed', [issue(sourcePath, side + " schema conversion failed")], cause);
}
};
const collectIntegrations = (toolName, sourcePath, declarations, inputJsonSchema) => {
if (declarations === undefined) return {};
if (!isRecord(declarations)) throw fail("collect", 'tool "' + toolName + '" integrations must be a record', [issue(sourcePath, "integrations must be a record")]);
const inputProperties = isRecord(inputJsonSchema) && isRecord(inputJsonSchema.properties) ? inputJsonSchema.properties : {};
const out = {};
for (const [field, raw] of Object.entries(declarations)) {
if (Object.prototype.hasOwnProperty.call(inputProperties, field)) throw fail("collect", 'tool "' + toolName + '" integration key "' + field + '" collides with input field', [issue(sourcePath, "integration key collides with input: " + field)]);
const decl = integrationDeclaration(raw);
if (!decl) throw fail("collect", 'tool "' + toolName + '" integration "' + field + '" is not a valid declaration', [issue(sourcePath, "invalid integration declaration: " + field)]);
out[field] = decl;
}
return out;
};
const projectInputSchema = (inputJsonSchema, integrations) => {
const base = isRecord(inputJsonSchema) ? inputJsonSchema : {};
const properties = isRecord(base.properties) ? { ...base.properties } : {};
const required = Array.isArray(base.required) ? [...base.required] : [];
for (const [field, decl] of Object.entries(integrations)) {
properties[field] = decl.mode === "one" ? { type: "string", description: decl.description ?? "Connection for " + decl.slug } : { type: "array", items: { type: "string" }, description: decl.description ?? "Connections for " + decl.slug };
required.push(field);
}
return { ...base, type: "object", properties, ...(required.length > 0 ? { required: [...new Set(required)] } : {}) };
};
const collectFromExport = (exported, fileSlug, sourcePath) => {
if (isDefinedTool(exported)) {
const inputJsonSchema = jsonSchemaFor(exported.input, "input", fileSlug, sourcePath);
const integrations = collectIntegrations(fileSlug, sourcePath, exported.integrations, inputJsonSchema);
return { tools: [{ toolName: fileSlug, description: exported.description, integrations, inputSchema: projectInputSchema(inputJsonSchema, integrations), outputSchema: jsonSchemaFor(exported.output, "output", fileSlug, sourcePath), annotations: exported.annotations }] };
}
if (!isRecord(exported)) throw fail("collect", "default export in " + sourcePath + " must be a tool, record, or factory", [issue(sourcePath, "unsupported default export")]);
const tools = [];
const seen = new Set();
if (isDefinedTool(exported[fileSlug])) throw fail("collect", 'record export key "' + fileSlug + '" collides with single tool name', [issue(sourcePath, 'record key "' + fileSlug + '" is reserved')]);
for (const [key, value] of Object.entries(exported)) {
if (!isDefinedTool(value)) continue;
if (!validToolKey(key)) throw fail("collect", 'record export key "' + key + '" is not a valid tool slug', [issue(sourcePath, "invalid record key " + key)]);
const toolName = fileSlug + "__" + key;
if (seen.has(toolName)) throw fail("collect", 'duplicate tool name "' + toolName + '"', [issue(sourcePath, "duplicate tool name " + toolName)]);
const inputJsonSchema = jsonSchemaFor(value.input, "input", toolName, sourcePath);
const integrations = collectIntegrations(toolName, sourcePath, value.integrations, inputJsonSchema);
seen.add(toolName);
tools.push({ toolName, exportKey: key, description: value.description, integrations, inputSchema: projectInputSchema(inputJsonSchema, integrations), outputSchema: jsonSchemaFor(value.output, "output", toolName, sourcePath), annotations: value.annotations });
}
if (tools.length === 0) throw fail("collect", "record export in " + sourcePath + " contains no defineTool entries", [issue(sourcePath, "no tools found")]);
return { tools };
};
const selectTool = (exported, entry) => {
if (isDefinedTool(exported)) return exported;
if (!isRecord(exported)) return null;
const index = entry.indexOf("__");
return index === -1 ? null : exported[entry.slice(index + 2)];
};
const validateStandard = async (schema, value, field) => {
if (!isRecord(schema) || !isRecord(schema["~standard"]) || typeof schema["~standard"].validate !== "function") return value;
const result = await schema["~standard"].validate(value);
if (isRecord(result) && "issues" in result && Array.isArray(result.issues)) throw fail(field === "input" ? "input_validation" : "output_validation", field + " validation failed", undefined, result.issues);
return isRecord(result) && "value" in result ? result.value : value;
};
const makeClient = (bridge, root, prefix = []) => new Proxy(() => undefined, {
get(_target, prop) {
if (prop === "then" || typeof prop === "symbol") return undefined;
return makeClient(bridge, root, [...prefix, String(prop)]);
},
async apply(_target, _thisArg, args) {
return await bridge.call(root + "." + prefix.join("."), args[0] ?? {});
},
});
const splitInvokeInput = (bridge, toolName, input, integrations) => {
const payload = isRecord(input) ? input : {};
const dataInput = { ...payload };
const handles = {};
for (const [field, decl] of Object.entries(integrations)) {
const raw = payload[field];
delete dataInput[field];
if (decl.mode === "one") {
if (typeof raw !== "string" || raw.length === 0) throw fail("input_validation", 'tool "' + toolName + '" integration "' + field + '" must be a connection address');
handles[field] = makeClient(bridge, field);
} else {
if (!Array.isArray(raw) || raw.some((item) => typeof item !== "string" || item.length === 0)) throw fail("input_validation", 'tool "' + toolName + '" integration "' + field + '" must be connection addresses');
handles[field] = raw.map((_address, index) => makeClient(bridge, field + "#" + index));
}
}
return { input: dataInput, integrations: handles };
};
const serializeFailure = (error, fallbackKind) => {
if (isRecord(error) && error.__appExecutorFailure === true) return { ok: false, kind: error.kind, message: error.message, diagnostics: error.diagnostics, cause: error.cause };
return { ok: false, kind: fallbackKind, message: error && error.message ? error.message : String(error) };
};
export default class AppExecutor extends WorkerEntrypoint {
async collect(input) {
try {
const first = collectFromExport(await resolveDefault(), input.fileSlug, input.sourcePath);
const second = collectFromExport(await resolveDefault(), input.fileSlug, input.sourcePath);
if (stableStringify(first) !== stableStringify(second)) throw fail("nondeterministic", "collect for " + input.sourcePath + " is nondeterministic", [issue(input.sourcePath, "factory output changed between runs")]);
return { ok: true, value: first };
} catch (error) {
return serializeFailure(error, "collect");
}
}
async invoke(input, bridge) {
try {
const invoke = async () => {
const exported = await resolveDefault();
const tool = selectTool(exported, input.toolName);
if (!isDefinedTool(tool)) throw fail("invoke", "tool not found in bundle: " + input.toolName);
const inputJsonSchema = jsonSchemaFor(tool.input, "input", input.toolName, input.toolName);
const integrations = collectIntegrations(input.toolName, input.toolName, tool.integrations, inputJsonSchema);
const split = splitInvokeInput(bridge, input.toolName, input.input, integrations);
const decoded = await validateStandard(tool.input, split.input, "input");
const output = await tool.handler(decoded, split.integrations);
return { output: await validateStandard(tool.output, output, "output") };
};
const value = await Promise.race([
invoke(),
new Promise((_, reject) => setTimeout(() => reject(fail("timeout", "app tool timed out after " + input.timeoutMs + "ms")), input.timeoutMs)),
]);
return { ok: true, value };
} catch (error) {
return serializeFailure(error, "invoke");
}
}
}
`;
const asEntrypoint = (value: unknown): DynamicAppEntrypoint => value as DynamicAppEntrypoint;
const startWorker = (loader: DynamicWorkerLoader, bundle: string): DynamicAppEntrypoint =>
asEntrypoint(
loader
.get(`app-tool-${crypto.randomUUID()}`, () => ({
compatibilityDate: "2025-06-01",
compatibilityFlags: ["nodejs_compat"],
mainModule: "driver.js",
modules: {
"driver.js": appWorkerModule(),
"app.js": bundle,
},
globalOutbound: null,
}))
.getEntrypoint(),
);
export const makeDynamicWorkerAppToolExecutor = (
options: DynamicWorkerAppToolExecutorOptions,
): AppToolExecutor => ({
collect: (bundle, input) =>
Effect.tryPromise({
try: async () => {
const response = await startWorker(options.loader, bundle).collect(input);
if (!response.ok) throw toAppExecutorError(response, "collect");
if (!stableStringify(response.value))
throw new Error(`collect failed for ${input.sourcePath}`);
return response.value;
},
catch: (cause) => mapCause(cause, "collect", `collect failed for ${input.sourcePath}`),
}),
invoke: (bundle, entry, input, bridge, limits) =>
Effect.tryPromise({
try: async () => {
const response = await startWorker(options.loader, bundle).invoke(
{ toolName: entry.toolName, input, timeoutMs: limits.timeoutMs },
bridge,
);
if (!response.ok) throw toAppExecutorError(response, "invoke");
return response.value;
},
catch: (cause) => mapCause(cause, "invoke", "app tool invocation failed"),
}),
});