export type FabricSandboxTerminationReason = "completed" | "runtime_error" | "timed_out" | "aborted"; export interface FabricSandboxResult { value: unknown; logs: string[]; terminationReason: FabricSandboxTerminationReason; error?: string; } export interface FabricSandboxOptions { timeoutMs: number; memoryLimitBytes: number; maxLogChars?: number; strings?: Record; tokenBudget?: number; signal?: AbortSignal; minimumTimeoutMsForHostCall?(ref: string, args: Record): number | undefined; transpiledCode?: string; } export type FabricHostCall = (ref: string, args: Record, signal: AbortSignal) => Promise; export declare const GUEST_SETUP = "\n(() => {\nconst __fabricBridge = globalThis.__fabricHostCall;\ndelete globalThis.__fabricHostCall;\nconst __call = (ref, args) => __fabricBridge(ref, args ?? {});\nconst __piToolNames = [\"read\",\"bash\",\"edit\",\"write\",\"grep\",\"find\",\"ls\"];\nconst __toolsBase = {\n providers: () => __call(\"fabric.$providers\", {}),\n list: (args = {}) => __call(\"fabric.$list\", args),\n search: (args) => __call(\"fabric.$search\", args),\n describe: (args) => __call(\"fabric.$describe\", args),\n call: (args) => __call(\"fabric.$call\", args),\n progress: (args) => __call(\"fabric.$progress\", args),\n models: () => __call(\"fabric.$models\", {}),\n};\n// tools is discovery + generic calls only. The proxy keeps the seven discovery\n// methods and turns a core-tool name (read/bash/edit/...) into an actionable\n// error pointing at pi., so a model that writes tools.read(...) learns\n// the fix in one turn instead of looping on \"tools.read is not a function\".\nglobalThis.tools = new Proxy(__toolsBase, {\n get(target, property) {\n if (property === \"then\" || typeof property === \"symbol\") return undefined;\n const name = String(property);\n if (__piToolNames.indexOf(name) >= 0) {\n return () => {\n throw new Error(\n \"tools.\" + name + \" is not available on the discovery API. tools is discovery + generic calls only (providers/list/search/describe/call/models). For the Pi core tool, call pi.\" + name + \"(args), e.g. pi.\" + name + \"({ ... }).\"\n );\n };\n }\n return target[property];\n },\n set() { return true; },\n deleteProperty() { return true; },\n});\nconst __piStringFields = { bash: \"command\", read: \"path\", ls: \"path\", grep: \"pattern\", find: \"pattern\" };\n// Per-tool key aliases. The runtime normalizes them to the canonical form\n// before the host validates args, so a model that writes { query, regex, ... }\n// or { file } instead of { pattern } / { path } still succeeds on the first\n// call. Keep these in sync with the PiToolsApi overloads in guest-types.ts so\n// the type-checker accepts the same spellings it coercion-handles at runtime.\nconst __piArgAliases = {\n bash: { cmd: \"command\", shell: \"command\", cmdline: \"command\", timeoutMs: \"timeout\" },\n find: { query: \"pattern\", regex: \"pattern\", search: \"pattern\", max: \"limit\" },\n grep: {\n query: \"pattern\", regex: \"pattern\", search: \"pattern\",\n ic: \"ignoreCase\", caseInsensitive: \"ignoreCase\",\n globPattern: \"glob\",\n max: \"limit\", ctx: \"context\",\n },\n read: { file: \"path\", max: \"limit\", start: \"offset\" },\n ls: { dir: \"path\", file: \"path\", max: \"limit\" },\n edit: { file: \"path\", old: \"oldText\", new: \"newText\", replacement: \"newText\" },\n write: { file: \"path\", contents: \"content\", body: \"content\", text: \"content\" },\n};\n// Multi-arg positional order, used only when a call passes >= 2 args. The\n// one-field tools (read/bash/ls) are intentionally absent: their bare-string\n// form already covers the 1-arg case, and a 2-arg call should hit the\n// type-checker's wrong-arity (2554) and be corrected to an options object\n// rather than silently dropping the second argument.\nconst __piPositionalFields = {\n grep: [\"pattern\", \"path\", \"limit\"],\n find: [\"pattern\", \"path\", \"limit\"],\n write: [\"path\", \"content\"],\n edit: [\"path\", \"oldText\", \"newText\"],\n};\nconst __positionalToArgs = (name, rest) => {\n const order = __piPositionalFields[name];\n if (!order) return rest.length > 0 ? rest[0] : {};\n const out = {};\n for (let i = 0; i < rest.length && i < order.length; i++) {\n const v = rest[i];\n if (v !== undefined) out[order[i]] = v;\n }\n return out;\n};\nconst __normalizePiArgs = (name, args) => {\n const field = __piStringFields[name];\n if (typeof args === \"string\" && field) return { [field]: args };\n if (args === null || typeof args !== \"object\" || Array.isArray(args)) return args;\n const aliases = __piArgAliases[name];\n let out = args;\n if (aliases) {\n for (const alias in aliases) {\n const canonical = aliases[alias];\n if (alias in out) {\n if (out === args) out = Object.assign({}, args);\n if (!(canonical in out)) out[canonical] = out[alias];\n delete out[alias];\n }\n }\n }\n if (name === \"edit\" && !Array.isArray(out.edits) && (\"oldText\" in out || \"newText\" in out)) {\n if (out === args) out = Object.assign({}, args);\n const edit = {};\n if (\"oldText\" in out) edit.oldText = out.oldText;\n if (\"newText\" in out) edit.newText = out.newText;\n out.edits = [edit];\n delete out.oldText;\n delete out.newText;\n }\n return out;\n};\n// The pi proxy accepts: a bare string (primary field), an options object, or\n// a positional spread mapped by __piPositionalFields. 0/1 args preserve the\n// legacy (args = {}) default so existing programs are unchanged.\nglobalThis.pi = new Proxy({}, {\n get(_target, property) {\n if (property === \"then\") return undefined;\n const name = String(property);\n return (...rest) => {\n let args;\n if (rest.length <= 1) {\n const first = rest.length === 1 ? rest[0] : undefined;\n args = first === undefined ? {} : first;\n } else {\n args = __positionalToArgs(name, rest);\n }\n return __call(\"pi.\" + name, __normalizePiArgs(name, args));\n };\n },\n});\nconst __piStrings = (typeof globalThis[\"\u03C0\"] === \"object\" && globalThis[\"\u03C0\"] !== null) ? globalThis[\"\u03C0\"] : {};\nglobalThis[\"\u03C0\"] = new Proxy(__piStrings, {\n get(target, property) {\n if (typeof property === \"symbol\") return undefined;\n const name = String(property);\n if (name === \"then\" || name === \"toJSON\" || name === \"constructor\") return undefined;\n if (Object.prototype.hasOwnProperty.call(target, name)) return target[name];\n if (__piToolNames.indexOf(name) >= 0) {\n throw new Error(\n \"\u03C0.\" + name + \" is the strings accessor, not a tool. For the Pi core tool, call pi.\" + name + \"(args).\"\n );\n }\n const provided = Object.keys(target);\n throw new Error(\n \"\u03C0.\" + name + \" is not defined. \u03C0 only exposes keys from the fabric_exec strings parameter\" +\n (provided.length ? \" (provided: \" + provided.join(\", \") + \")\" : \" (none provided)\") +\n \". Pass strings: { \" + name + \": '...' } to use \u03C0.\" + name + \".\"\n );\n },\n ownKeys(target) { return Reflect.ownKeys(target); },\n getOwnPropertyDescriptor(target, prop) { return Reflect.getOwnPropertyDescriptor(target, prop); },\n has(target, prop) { return Object.prototype.hasOwnProperty.call(target, prop); }\n});\n// Stable providers share a lazy dispatch proxy; the guest declarations keep\n// their known actions typed while the registry remains the runtime authority.\nconst __providerProxy = (provider) => new Proxy({}, {\n get(_target, property) {\n if (property === \"then\" || typeof property === \"symbol\") return undefined;\n return (args = {}) => __call(provider + \".\" + String(property), args);\n },\n});\nglobalThis.extensions = __providerProxy(\"extensions\");\nglobalThis.memory = __providerProxy(\"memory\");\nglobalThis.state = __providerProxy(\"state\");\nglobalThis.schema = __providerProxy(\"schema\");\nglobalThis.compact = __providerProxy(\"compact\");\nglobalThis.agents = Object.freeze({\n run: (args) => __call(\"agents.run\", args),\n spawn: (args) => __call(\"agents.spawn\", args),\n wait: (args) => __call(\"agents.wait\", args),\n status: (args) => __call(\"agents.status\", args),\n list: () => __call(\"agents.list\", {}),\n main: () => __call(\"agents.main\", {}),\n peers: () => __call(\"agents.peers\", {}),\n models: (args = {}) => __call(\"agents.models\", args),\n stop: (args) => __call(\"agents.stop\", args),\n cleanup: (args) => __call(\"agents.cleanup\", args),\n create: (args) => __call(\"agents.create\", args),\n ask: (args) => __call(\"agents.ask\", args),\n tell: (args) => __call(\"agents.tell\", args),\n steer: (args) => __call(\"agents.steer\", args),\n followUp: (args) => __call(\"agents.followUp\", args),\n setSteeringMode: (args) => __call(\"agents.setSteeringMode\", args),\n setFollowUpMode: (args) => __call(\"agents.setFollowUpMode\", args),\n actorStatus: (args) => __call(\"agents.actorStatus\", args),\n setEvents: (args) => __call(\"agents.setEvents\", args),\n setInstructions: (args) => __call(\"agents.setInstructions\", args),\n actors: () => __call(\"agents.actors\", {}),\n messages: (args) => __call(\"agents.messages\", args),\n remove: (args) => __call(\"agents.remove\", args),\n log: (args) => __call(\"agents.log\", args),\n});\nglobalThis.mesh = Object.freeze({\n self: () => __call(\"mesh.self\", {}),\n publish: (args) => __call(\"mesh.publish\", args),\n read: (args = {}) => __call(\"mesh.read\", args),\n members: (args = {}) => __call(\"mesh.members\", args),\n get: (args) => __call(\"mesh.get\", args),\n list: (args = {}) => __call(\"mesh.list\", args),\n put: (args) => __call(\"mesh.put\", args),\n delete: (args) => __call(\"mesh.delete\", args),\n});\nglobalThis.mcp = new Proxy({}, {\n get(_target, server) {\n if (server === \"then\") return undefined;\n if (server === \"servers\") return () => __call(\"mcp.$servers\", {});\n if (server === \"reload\") return () => __call(\"mcp.$reload\", {});\n if (server === \"register\") return (args) => __call(\"mcp.$register\", args);\n if (server === \"call\") return (args) => __call(\"mcp.$call\", args);\n return new Proxy({}, {\n get(_serverTarget, tool) {\n if (tool === \"then\") return undefined;\n return (args = {}) => __call(\"mcp.\" + String(server) + \".\" + String(tool), args);\n },\n });\n },\n});\nlet __workflowSpentTokens = 0;\nconst __workflowBudgetTotal = Number.isFinite(globalThis.__fabricTokenBudget)\n ? Math.max(0, globalThis.__fabricTokenBudget)\n : Number.POSITIVE_INFINITY;\nconst __recordAgentUsage = (result) => {\n const usage = result && result.usage;\n if (usage) __workflowSpentTokens += Number(usage.input || 0) + Number(usage.output || 0);\n return result;\n};\nconst __workflowAgent = async (prompt, options = {}) => {\n if (__workflowSpentTokens >= __workflowBudgetTotal) {\n throw new Error(\"Fabric workflow token budget exhausted\");\n }\n const { label, ...agentOptions } = options;\n const workerName = String(label || agentOptions.name || \"Fabric workflow agent\");\n const result = __recordAgentUsage(await agents.run({\n ...agentOptions,\n ...(label && !agentOptions.name ? { name: label } : {}),\n task: prompt,\n }));\n if (!result || result.status !== \"completed\") {\n const reason = result && result.error ? result.error : \"agent did not complete\";\n throw new Error(workerName + \" failed: \" + reason);\n }\n return result.value !== undefined ? result.value : result.text;\n};\n// Budget-aware agents.run used by council.run and rlm.query so their usage is\n// counted in budget.spent() and the tokenBudget guard can preempt them, just\n// like workflow.agent(). Without this, councils bypass the budget entirely.\nconst __budgetedRun = async (args) => {\n if (__workflowSpentTokens >= __workflowBudgetTotal) {\n throw new Error(\"Fabric workflow token budget exhausted\");\n }\n return __recordAgentUsage(await agents.run(args));\n};\nlet __nextWorkflowSpanId = 0;\nconst __workflowSpanMetadata = (kind, items, options, stageCount) => {\n const itemCount = Array.isArray(items) ? items.length : undefined;\n let concurrency;\n if (kind === \"parallel\" && itemCount !== undefined) {\n if (itemCount === 0) concurrency = 0;\n else {\n const concurrencyOpt = typeof options === \"number\" ? { concurrency: options } : options ?? {};\n const requested = Number(concurrencyOpt.concurrency ?? itemCount);\n if (Number.isFinite(requested) && requested >= 1) {\n concurrency = Math.max(1, Math.min(itemCount, Math.floor(requested)));\n }\n }\n }\n return {\n kind,\n ...(itemCount !== undefined ? { itemCount } : {}),\n ...(stageCount !== undefined ? { stageCount } : {}),\n ...(concurrency !== undefined ? { concurrency } : {}),\n };\n};\nconst __withWorkflowSpan = async (metadata, body) => {\n const id = \"span-\" + __nextWorkflowSpanId++;\n await __call(\"fabric.$spanStart\", { id, ...metadata });\n try {\n const value = await body();\n await __call(\"fabric.$spanEnd\", { id, outcome: \"succeeded\" });\n return value;\n } catch (error) {\n try { await __call(\"fabric.$spanEnd\", { id, outcome: \"failed\" }); } catch { /* preserve the workflow error */ }\n throw error;\n }\n};\nconst __runParallel = async (thunks, options) => {\n if (!Array.isArray(thunks) || thunks.some((thunk) => typeof thunk !== \"function\")) {\n throw new TypeError(\"workflow.parallel expects an array of functions or (items, mapper)\");\n }\n if (thunks.length === 0) return [];\n const concurrencyOpt = typeof options === \"number\" ? { concurrency: options } : options ?? {};\n const requestedConcurrency = Number(concurrencyOpt.concurrency ?? thunks.length);\n if (!Number.isFinite(requestedConcurrency) || requestedConcurrency < 1) {\n throw new RangeError(\"workflow.parallel concurrency must be a positive finite number\");\n }\n const concurrency = Math.max(1, Math.min(thunks.length || 1, Math.floor(requestedConcurrency)));\n const results = new Array(thunks.length);\n let cursor = 0;\n await Promise.all(Array.from({ length: concurrency }, async () => {\n while (cursor < thunks.length) {\n const index = cursor++;\n results[index] = await thunks[index]();\n }\n }));\n return results;\n};\nconst __workflowParallel = async (items, arg2, arg3) => {\n const options = typeof arg2 === \"function\" ? arg3 : arg2;\n return __withWorkflowSpan(\n __workflowSpanMetadata(\"parallel\", items, options),\n async () => {\n if (typeof arg2 === \"function\") {\n if (!Array.isArray(items)) throw new TypeError(\"workflow.parallel expects an array as the first argument\");\n return __runParallel(items.map((item, index) => () => arg2(item, index)), arg3);\n }\n return __runParallel(items, arg2);\n },\n );\n};\nconst __workflowPipeline = async (items, ...stages) =>\n __withWorkflowSpan(\n __workflowSpanMetadata(\"pipeline\", items, undefined, stages.length),\n async () => {\n if (!Array.isArray(items) || stages.some((stage) => typeof stage !== \"function\")) {\n throw new TypeError(\"workflow.pipeline expects an array followed by stage functions\");\n }\n return __workflowParallel(items.map((original, index) => async () => {\n let value = original;\n for (const stage of stages) value = await stage(value, original, index);\n return value;\n }));\n },\n );\nglobalThis.workflow = Object.freeze({\n agent: __workflowAgent,\n parallel: __workflowParallel,\n pipeline: __workflowPipeline,\n configure: (args) => __call(\"fabric.$configure\", args),\n phase: (nameOrInput, options = {}) => {\n const input =\n nameOrInput && typeof nameOrInput === \"object\" && !Array.isArray(nameOrInput)\n ? { ...nameOrInput }\n : { ...options, name: nameOrInput };\n return __call(\"fabric.$phase\", input);\n },\n item: (args) => __call(\"fabric.$item\", args),\n event: (args) => __call(\"fabric.$event\", args),\n log: (...values) => print(...values),\n budget: Object.freeze({\n total: __workflowBudgetTotal,\n spent: () => __workflowSpentTokens,\n remaining: () => Math.max(0, __workflowBudgetTotal - __workflowSpentTokens),\n }),\n});\nglobalThis.agent = __workflowAgent;\nglobalThis.parallel = __workflowParallel;\nglobalThis.pipeline = __workflowPipeline;\nglobalThis.phase = workflow.phase;\nglobalThis.log = workflow.log;\nglobalThis.budget = workflow.budget;\nglobalThis.rlm = Object.freeze({\n query: (args) => {\n if (args && args.runner && args.runner !== \"pi\") {\n throw new Error(\"rlm.query requires the Pi runner because recursive Fabric is unavailable in Claude Code\");\n }\n return __budgetedRun({ ...args, runner: \"pi\", recursive: true });\n },\n});\nglobalThis.council = Object.freeze({\n async run(args) {\n const { task, roles, synthesize = true, ...agentOptions } = args;\n const results = await Promise.all(roles.map((role) => __budgetedRun({\n ...agentOptions,\n name: role,\n task: \"Act as the \" + role + \" council member. Independently analyze this task:\\n\\n\" + task,\n })));\n if (!synthesize) return results;\n return __budgetedRun({\n ...agentOptions,\n name: \"council-synthesizer\",\n task: \"Synthesize the council's independent reports into one decision. Preserve disagreements and cite which role raised each concern.\\n\\nTask:\\n\" + task + \"\\n\\nReports:\\n\" + JSON.stringify(results),\n });\n },\n});\nglobalThis.console = Object.freeze({ log: print, info: print, warn: print, error: print });\nconst __timerCallbacks = new Map();\nlet __nextTimerId = 1;\nglobalThis.setTimeout = (callback, ms = 0) => {\n const id = __nextTimerId++;\n __timerCallbacks.set(id, { callback, interval: false });\n __call(\"fabric.$timer\", { ms }).then(() => {\n const entry = __timerCallbacks.get(id);\n if (!entry) return;\n __timerCallbacks.delete(id);\n try { entry.callback(); } catch { /* swallow timer callback errors */ }\n });\n return id;\n};\nglobalThis.setInterval = (callback, ms = 0) => {\n const id = __nextTimerId++;\n __timerCallbacks.set(id, { callback, interval: true });\n const schedule = () => {\n __call(\"fabric.$timer\", { ms }).then(() => {\n const entry = __timerCallbacks.get(id);\n if (!entry) return;\n try { entry.callback(); } catch { /* swallow timer callback errors */ }\n if (__timerCallbacks.has(id)) schedule();\n });\n };\n schedule();\n return id;\n};\nglobalThis.clearTimeout = (id) => { __timerCallbacks.delete(id); };\nglobalThis.clearInterval = (id) => { __timerCallbacks.delete(id); };\n})();\n"; export declare class QuickJsRuntime { execute(code: string, hostCall: FabricHostCall, options: FabricSandboxOptions): Promise; } //# sourceMappingURL=quickjs-runtime.d.ts.map