import type { TsNode, TsRaw, TsStatements, TsImport, TsImportKind, TsImportName, TsVarDecl, TsAssign, TsFunctionDecl, TsParam, TsArrowFn, TsCall, TsAwait, TsReturn, TsObjectLiteral, TsObjectEntry, TsArrayLiteral, TsTemplateLit, TsTemplatePart, TsIf, TsElseIf, TsFor, TsWhile, TsSwitch, TsSwitchCase, TsTryCatch, TsBinOp, TsPropertyAccess, TsSpread, TsIdentifier, TsStringLiteral, TsNumericLiteral, TsBooleanLiteral, TsComment, TsExport, TsNewExpr, TsScopedVar, TsRunnerStep, TsRunnerThread, TsRunnerHandle, TsRunnerHookStep, TsRunnerIfElse, TsRunnerExitMatch, TsRunnerLoop, TsRunnerWhileLoop, TsRunnerBranchStep, TsRunnerPipe, TsEmpty, TsBreak, TsContinue, TsPostfixOp, TsTernary, TsRunnerDebugger, TsWithHandler, TsAgencyFunctionWrap } from "./tsIR.js"; export { $, TsChain } from "./fluent.js"; export declare const ts: { raw(code: string): TsRaw; statements(body: TsNode[]): TsStatements; statementsPush(statement: TsStatements, ...stmts: TsNode[]): TsStatements; importDecl(opts: { importKind: TsImportKind; names?: TsImportName[]; defaultName?: string; namespaceName?: string; from: string; }): TsImport; varDecl(declKind: "const" | "let", name: string, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; letDecl(name: string, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; constDecl(name: string, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; constDeclId(name: TsIdentifier, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; /** `const { key: binding, ... } = initializer` — use shorthand when key === binding */ constDestructure(bindings: Record, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; /** `let { key: binding, ... } = initializer` — use shorthand when key === binding */ letDestructure(bindings: Record, initializer?: TsNode, typeAnnotation?: string): TsVarDecl; assign(lhs: TsNode, rhs: TsNode): TsAssign; functionDecl(name: string, params: TsParam[], body: TsNode, opts?: { async?: boolean; export?: boolean; returnType?: string; }): TsFunctionDecl; arrowFn(params: TsParam[], body: TsNode, opts?: { async?: boolean; returnType?: string; }): TsArrowFn; call(callee: TsNode, args?: TsNode[]): TsCall; namedArgs(callee: TsNode, args: Record): TsCall; await(expr: TsNode): TsAwait; /** * `receiver.name(args)` or `receiver?.name(args)`. * Replaces the verbose `$(receiver).prop(name).call(args).done()` chain * for the common "method call on a receiver" shape. */ methodCall(receiver: TsNode, name: string, args?: TsNode[], opts?: { optional?: boolean; }): TsCall; /** `await callee(args)` */ awaitCall(callee: TsNode, args?: TsNode[]): TsAwait; /** `await receiver.name(args)` or `await receiver?.name(args)` */ awaitMethodCall(receiver: TsNode, name: string, args?: TsNode[], opts?: { optional?: boolean; }): TsAwait; /** * Immediately-invoked (arrow) function expression: `(async () => { body })()`. * `body` can be a `TsStatements` body or any single `TsNode`. * The printer adds the wrapping parens around the arrow callee automatically. */ iife(opts: { async?: boolean; params?: TsParam[]; body: TsNode | TsNode[]; }): TsCall; return(expr?: TsNode): TsReturn; obj(entries: TsObjectEntry[] | Record): TsObjectLiteral; setSpread(expr: TsNode): TsObjectEntry; set(key: string, value: TsNode): TsObjectEntry; setComputed(key: TsNode, value: TsNode): TsObjectEntry; arr(items: TsNode[]): TsArrayLiteral; template(parts: TsTemplatePart[]): TsTemplateLit; if(condition: TsNode, body: TsNode, opts?: { elseIfs?: TsElseIf[]; elseBody?: TsNode; }): TsIf; forOf(varName: string, iterable: TsNode, body: TsNode): TsFor; forC(init: TsNode, condition: TsNode, update: TsNode, body: TsNode): TsFor; while(condition: TsNode, body: TsNode): TsWhile; switch(discriminant: TsNode, cases: TsSwitchCase[]): TsSwitch; tryCatch(tryBody: TsNode, catchBody: TsNode, catchParam?: string, finallyBody?: TsNode): TsTryCatch; binOp(left: TsNode, op: string, right: TsNode, opts?: { parenLeft?: boolean; parenRight?: boolean; }): TsBinOp; prop(object: TsNode, property: string, opts?: { optional?: boolean; }): TsPropertyAccess; index(object: TsNode, property: TsNode, opts?: { optional?: boolean; }): TsPropertyAccess; spread(expr: TsNode): TsSpread; id(name: string): TsIdentifier; str(value: string): TsStringLiteral; num(value: number): TsNumericLiteral; bool(value: boolean): TsBooleanLiteral; comment(text: string, block?: boolean): TsComment; export(decl?: TsNode, names?: string[]): TsExport; "new"(callee: TsNode, args?: TsNode[]): TsNewExpr; validateType(value: TsNode, zodSchema: TsNode): TsCall; /** * `await __validateChainRecursive(value, )` — used at * `!` sites whose resolved type carries at least one `@validate(...)` tag * anywhere in the tree. The descriptor is a TS expression built via * `buildValidationDescriptor(...)`. Validators read `ctx` from the * active `agencyStore` ALS frame, so no explicit ctx arg is threaded. */ validateChainRecursive(value: TsNode, descriptor: TsNode): TsAwait; scopedVar(name: string, scope: TsScopedVar["scope"], moduleId?: string, blockFrameVar?: string): TsScopedVar; functionReturn(value: TsNode): TsStatements; runnerStep(opts: { id: number; body: TsNode[]; }): TsRunnerStep; runnerThread(opts: { id: number; method: "create" | "createSubthread"; body: TsNode[]; label?: TsNode | null; summarize?: TsNode | null; continueExpr?: TsNode | null; sessionExpr?: TsNode | null; hidden?: TsNode | null; }): TsRunnerThread; runnerHandle(opts: { id: number; handler: TsNode; body: TsNode[]; }): TsRunnerHandle; /** Emit `await runner.hook(id, async () => { ...body... })` — a * substep-counter-idempotent wrapper for codegen-emitted callback * hook sites. See `Runner.hook`'s JSDoc. */ runnerHookStep(opts: { id: number; body: TsNode[]; }): TsRunnerHookStep; withHandler(handler: TsNode, body: TsNode): TsWithHandler; runnerIfElse(opts: { id: number; branches: { condition: TsNode; body: TsNode[]; }[]; elseBranch?: TsNode[]; matchId?: number; }): TsRunnerIfElse; runnerExitMatch(opts: { matchId: number; value: TsNode; }): TsRunnerExitMatch; runnerLoop(opts: { id: number; items: TsNode; itemVar: string; body: TsNode[]; indexVar?: string; }): TsRunnerLoop; runnerWhileLoop(opts: { id: number; condition: TsNode; body: TsNode[]; }): TsRunnerWhileLoop; runnerBranchStep(opts: { id: number; branchKey: string; body: TsNode[]; }): TsRunnerBranchStep; runnerDebugger(opts: { id: number; label: string; }): TsRunnerDebugger; runnerPipe(opts: { id: number; target: TsNode; input: TsNode; fn: TsNode; }): TsRunnerPipe; empty(): TsEmpty; break(): TsBreak; continue(): TsContinue; postfix(operand: TsNode, op: "++" | "--"): TsPostfixOp; /** Call runner.halt(value) and return from the current callback */ runnerHalt(value: TsNode): TsStatements; /** Halt with { messages: __threads(), data: value } and return from a graph node callback */ nodeResult(value: TsNode): TsStatements; /** * Wrap a list of statements in * `await agencyStore.run({ ctx, stack, threads }, async () => { ... })`. * * Defense-in-depth: every function/node body's try block carries an * ALS frame so stdlib helpers and `__threads()` / `__stateStack()` * reads resolve correctly even for code that runs between Runner * steps. Today the gap is empty (every callback emission uses * `runner.step`/`runner.hook`/etc. which re-seed the frame * themselves), but the wrap makes the contract explicit and * removes the risk that a future refactor silently loses the * per-scope frame. * * NOTE: `return` statements inside the wrapped body escape only the * inner async callback, not the outer function. Validation guards * that return a non-`undefined` value (e.g. `return __vr_x` for a * validation failure) must stay outside the wrap so the outer * function actually returns the value to its caller. The bare * `return;` emitted by `runnerHalt` is fine: after the callback * returns, the outer `if (runner.halted) return runner.haltResult;` * check picks up the halted result. */ withAlsFrame({ ctx, stack, threads, body, }: { ctx: TsNode; stack: TsNode; threads: TsNode; body: TsNode[]; }): TsNode; env(varName: string): TsRaw; /** * Emit `await callHook({ name, data })`. * * `callHook` reads `ctx` from the active `agencyStore` frame, so the * codegen no longer needs to thread `__ctx` through every emission * site. Callback bodies cannot raise interrupts (statically forbidden * by the typechecker — see `checkCallbackBodyInterrupts`). `callHook` * returns `void`; the codegen-emitted hook sites fire-and-forget. */ callHook(hookName: string, data: Record | TsNode): TsNode; setupEnv({ stack, step, self, ctx, }: { stack: TsNode; step: TsNode; self: TsNode; ctx: TsNode; }): TsStatements; time(varName: string): TsNode; stack(varName: string): TsNode; ctx(varName: string): TsNode; self(varName: string): TsNode; throw(code: string): TsNode; and(...conditions: TsNode[]): TsNode; or(...conditions: TsNode[]): TsNode; not(condition: TsNode): TsNode; unaryOp(op: string, operand: TsNode, opts?: { paren?: boolean; }): TsNode; functionCallConfig({ ctx, threads, stateStack, moduleId, scopeName, stepPath, }: { ctx: TsNode; threads?: TsNode; stateStack?: TsNode; moduleId?: TsNode; scopeName?: TsNode; stepPath?: TsNode; }): TsNode; newThreadStore(): TsNode; smoltalkSystemMessage(args: TsNode[]): TsNode; smoltalkUserMessage(args: TsNode[]): TsNode; smoltalkAssistantMessage(args: TsNode[]): TsNode; goToNode(nodeName: string, args: TsNode): TsNode; nodeReturn({ messages, data }: { messages: TsNode; data: TsNode; }): TsStatements; jsonStringify(value: TsNode): TsNode; consoleLog(...args: TsNode[]): TsNode; consoleWarn(...args: TsNode[]): TsNode; consoleError(...args: TsNode[]): TsNode; /** GlobalStore operations. * * Receiver defaults to `ts.runtime.globals` (the `__globals()!` * accessor — see its docstring). Pass `globalsRef` explicitly when * the emission site has a different lexical handle on the store — * most notably inside `__initializeGlobals(__ctx)` in * sectionAssembler.ts, where the function's `__ctx` parameter * exposes the canonical store directly; pass * `ts.prop(ts.id("__ctx"), "globals")` there. Routing through the * accessor by default ensures every user-visible read/write * participates in per-branch isolation without further codegen * changes. */ globalGet(moduleId: string, varName: string, globalsRef?: TsNode): TsCall; globalSet(moduleId: string, varName: string, value: TsNode, globalsRef?: TsNode): TsCall; ternary(condition: TsNode, trueExpr: TsNode, falseExpr: TsNode): TsTernary; agencyFunctionWrap(fn: TsNode, name: string, module: string, params: { name: string; }[]): TsAgencyFunctionWrap; /** Predefined runtime identifiers. `threads` and `stateStack` are * `__threads()` / `__stateStack()` accessor calls (not bare * identifiers) because post-ALS migration the per-scope * `ThreadStore` and `StateStack` live on the active `agencyStore` * frame instead of in codegen-emitted `const __threads` / `const * __stateStack` locals. Every site that referenced the old locals * now emits the accessor call, which reads from ALS and returns * the live store (or `undefined` outside any frame — see * `runtime/asyncContext.ts`). * * `ctx` is `getRuntimeContext().ctx` rather than a bare `__ctx()` * accessor call: the per-scope `const __ctx = __state?.ctx || * __globalCtx;` local emitted by `setupEnv` would shadow a bare * `__ctx` accessor identifier — and the esbuild TS transform * rewrites *every* `__ctx` reference in a scope (import-bound * ones included) to match the renamed local, so `__ctx()` would * become `__ctx2()` and crash with `__ctx2 is not a function`. * Routing through `getRuntimeContext().ctx` avoids the shadow * entirely. Pre-wrap, parameter-context, and seed sites still use * `ts.id("__ctx")` directly to reach the setupEnv local. */ runtime: { self: TsIdentifier; ctx: TsRaw; threads: TsRaw; stateStack: TsRaw; /** Per-scope GlobalStore accessor. Reads from the active ALS * frame's `globals` slot — pointer-shared with the canonical * store at every frame builder (Stage 1) and the branch-local * clone inside `runInBranchAlsFrame` (Stage 2). Replaces the * pre-ALS `__ctx.globals.…` codegen pattern: every user-visible * global read/write is now routed through this accessor so the * branch-local view participates without further codegen * changes. The non-null assertion (`!`) is appropriate because * every emission site runs inside an Agency execution frame * (function/node body wrapped in `withAlsFrame`, Runner step * body, or bootstrap frame). */ globals: TsRaw; stack: TsIdentifier; step: TsIdentifier; state: TsIdentifier; globalCtx: TsIdentifier; client: TsIdentifier; }; /** Thread operations */ threads: { create(): TsCall; createAndReturnThread(): TsCall; createSubthread(): TsCall; createAndReturnSubthread(): TsCall; get(id: TsNode): TsCall; active(): TsCall; getOrCreateActive(): TsCall; }; };