import { extractNamedArgs, Value, AttributePathSegment } from './utils'; import { RobinPathThread, ExecutionStateTracker, ExecutionLog } from './classes'; import { Statement, Arg, DefineFunction, OnBlock } from './types/Ast.type'; import { CredentialStore, CredentialTester, CredentialTypeSchema, ModuleHost } from './credentials'; /** * RobinPath Interpreter * * See README.md for full documentation and usage examples. */ export declare const ROBINPATH_VERSION = "0.40.0"; export interface ModuleAdapter { name: string; functions: Record; functionMetadata: Record; moduleMetadata: ModuleMetadata; global?: boolean; /** * Credential type schemas declared by this module. * Registered with the runtime during loadModule so the credential editor * can list them without a central registry. */ credentialTypes?: CredentialTypeSchema[]; /** * Optional configuration hook called once during loadModule. The module * receives a ModuleHost (credential store + registry) and typically stashes * it in a module-local closure so handlers can resolve credentials. */ configure?: (host: ModuleHost) => void; } export { Parser, Printer, LineIndexImpl } from './classes'; export type { PrintContext, LineIndex } from './classes'; export { formatErrorWithContext, createErrorWithContext } from './utils'; export type { ExecutionLog, ExecutionStepInfo, LogCallback, BlockEvent, BlockCallback } from './classes'; export type { Value, AttributePathSegment }; export type { Statement, Arg, CommandCall, Assignment, ShorthandAssignment, InlineIf, IfBlock, IfTrue, IfFalse, DefineFunction, ScopeBlock, TogetherBlock, ForLoop, ReturnStatement, BreakStatement, OnBlock, CommentStatement, ChunkMarkerStatement, CellBlock, PromptBlockStatement, ThinkBlock, RememberBlock, UnrememberBlock, CommentWithPosition, CodePosition, DecoratorCall, } from './types/Ast.type'; export type { CredentialFieldType, CredentialFieldSchema, CredentialTypeSchema, CredentialRecord, CredentialListFilter, CredentialStore, CredentialTester, CredentialTestResult, ExecutionCredentialState, ModuleHost, } from './credentials'; export { MemoryCredentialStore, EnvCredentialStore, FileCredentialStore, HttpCredentialStore, DEFAULT_CREDENTIAL_TESTERS, } from './credentials'; export type BuiltinCallback = (callbackArgs: Value[]) => Promise | Value | null; export type BuiltinHandler = (args: Value[], callback?: BuiltinCallback | null) => Promise | Value | null; export type DecoratorHandler = (targetName: string, func: DefineFunction | null, originalArgs: Value[], decoratorArgs: Value[], originalDecoratorArgs?: Arg[]) => Promise; export type ParseDecoratorHandler = (targetName: string, func: DefineFunction | null, decoratorArgs: Arg[], environment: Environment) => Promise | void; export interface ThinkToolDefinition { name: string; description: string; parameters: { name: string; type: string; required: boolean; description: string; }[]; returnType?: string; } export interface ThinkOptions { model?: string; outputType?: string; outputSchema?: string; stream?: boolean; onStream?: (delta: string) => void; tools?: string[]; toolDefinitions?: ThinkToolDefinition[]; executeTool?: (name: string, args: Record) => Promise; } export interface ThinkResult { value: Value; reasoning?: string; usage?: { promptTokens?: number; completionTokens?: number; model?: string; }; } export interface ThinkUsageReport { calls: number; promptTokens: number; completionTokens: number; totalTokens: number; estimatedCost: number; history: { model: string; promptTokens: number; completionTokens: number; cost: number; }[]; } export interface ThinkHandler { execute(prompt: string, options: ThinkOptions): Promise; } /** Memory handler for persistent conversation context across script runs */ export interface ThinkMemoryHandler { load(key: string): Promise<{ role: string; content: string; }[]>; save(key: string, history: { role: string; content: string; }[]): Promise; clear(key: string): Promise; list(): Promise; } /** Confirm handler for human-in-the-loop approval (legacy — use RobinPathHost instead) */ export interface ThinkConfirmHandler { confirm(message: string, details?: string): Promise; } /** Handler for persisting remember block data */ export interface RememberHandler { load(key: string): Promise; save(key: string, entries: string[]): Promise; clear(key: string): Promise; list(): Promise; } /** Configuration for a named AI agent used in think blocks */ export interface AgentConfig { model?: string; systemPrompt?: string; tools?: string[]; } /** Options for ask with choices */ export interface AskOptions { placeholder?: string; defaultValue?: string; choices?: string[]; } /** * Handler for interactive input (ask) and approval gates (approve). * The host provides the implementation — CLI uses stdin, desktop uses UI dialogs. */ export interface AskHandler { /** Prompt user for text input. Returns the user's response string. */ ask(prompt: string, options?: AskOptions): Promise; /** Prompt user for yes/no approval. Returns true if approved, false if rejected. */ approve(message: string, options?: { detail?: string; }): Promise; } /** * Unified host interface — bundles all handler capabilities. * Implement this once per host (CLI, desktop, MCP server) instead of 4+ separate handlers. * All methods are optional — only implement what your host supports. */ export interface RobinPathHost { /** AI provider for think blocks */ think?: { execute(prompt: string, options: ThinkOptions): Promise; }; /** Interactive input and approval */ ask?: { ask(prompt: string, options?: AskOptions): Promise; approve(message: string, options?: { detail?: string; }): Promise; }; /** Persistent memory storage */ remember?: { load(key: string): Promise; save(key: string, entries: string[]): Promise; clear(key: string): Promise; list(): Promise; }; /** Think conversation memory persistence */ thinkMemory?: { load(key: string): Promise<{ role: string; content: string; }[]>; save(key: string, history: { role: string; content: string; }[]): Promise; clear(key: string): Promise; list(): Promise; }; /** Streaming callback for think block tokens */ onStreamToken?: (delta: string) => void; /** Callback after think block completes (cost visibility) */ onThinkComplete?: (info: { model: string; promptTokens: number; completionTokens: number; cost: number; totalCost: number; }) => void; } export interface Environment { variables: Map; functions: Map; builtins: Map; decorators: Map; parseDecorators: Map; metadata: Map; moduleMetadata: Map; currentModule: string | null; variableMetadata: Map>; functionMetadata: Map>; constants: Set; eventHandlers: Map; stateTracker?: ExecutionStateTracker; thinkHandler?: ThinkHandler; thinkMemoryHandler?: ThinkMemoryHandler; thinkConfirmHandler?: ThinkConfirmHandler; thinkMemory: Map; thinkBudget?: number; thinkUsageReport?: ThinkUsageReport; onStreamToken?: (delta: string) => void; onThinkComplete?: (info: { model: string; promptTokens: number; completionTokens: number; cost: number; totalCost: number; }) => void; rememberStore?: Map; rememberHandler?: RememberHandler; agentRegistry?: Map; askHandler?: AskHandler; } export interface Frame { locals: Map; lastValue: Value; isFunctionFrame?: boolean; forgotten?: Set; isIsolatedScope?: boolean; } export { extractNamedArgs }; export type DataType = "string" | "number" | "boolean" | "object" | "array" | "null" | "any"; export type FormInputType = "text" | "number" | "textarea" | "select" | "checkbox" | "radio" | "date" | "datetime" | "file" | "json" | "code" | "varname" | "password" | "resource"; /** Describes a dynamic picker for a `formInputType: 'resource'` parameter. */ export interface ResourceDescriptor { /** Logical resource kind, e.g. "credential", "slack_channel". */ type: string; /** Callable that returns the choices, e.g. "credential.list", "slack.listChannels". */ listFn: string; /** Supported editing modes. */ modes?: ("list" | "byId" | "expression")[]; /** Whether the picker UI should show a search box. */ searchable?: boolean; /** Filter args forwarded to listFn, e.g. { type: "airtable" }. */ filter?: Record; } export interface ParameterMetadata { name: string; label?: string; /** UI-friendly title for the parameter (falls back to label/name). */ title?: string; dataType: DataType; description: string; formInputType: FormInputType; required?: boolean; defaultValue?: Value; allowedTypes?: string[]; children?: ParameterMetadata; /** Ghost text shown in the input. */ placeholder?: string; /** Whether the UI's expression toggle is available. */ allowExpression?: boolean; /** Hide under an "Advanced" section in the editor. */ advanced?: boolean; /** Height of textarea/json/code inputs, in rows. */ rows?: number; /** Syntax-highlight language for code/json inputs. */ language?: string; /** Client-side validation rules. */ validation?: { pattern?: string; }; /** Picker descriptor for `formInputType: 'resource'`. */ resource?: ResourceDescriptor; } /** Human-readable example usage for a function. */ export interface FunctionExample { title: string; code: string; } export interface FunctionMetadata { description: string; parameters: ParameterMetadata[]; returnType: DataType | string; returnDescription?: string; example?: string; /** UI-friendly title (falls back to the function name). */ title?: string; /** One-line summary shown in list views. */ summary?: string; /** Name of an operationGroup on the module this function belongs to. */ group?: string; /** Verb taxonomy for the UI: query/read/write/delete/upload etc. */ action?: "query" | "read" | "write" | "delete" | "upload" | string; /** Lucide icon name. */ icon?: string; /** Host capability required to call this (e.g. a WP capability). */ capability?: string; /** Flags like 'makes_http_call', 'writes_filesystem' — used by schedulers. */ sideEffects?: string[]; /** Safe to retry without side-effect duplication? */ idempotent?: boolean; /** SemVer string when this function was added. */ since?: string; tags?: string[]; /** Optional schema describing the return shape. */ returnSchema?: Record; /** Map of error code → human description. */ errors?: Record; /** Multiple worked examples. */ examples?: FunctionExample[]; } export interface OperationGroup { title: string; description: string; order: number; } export interface ModuleMetadata { description: string; methods: string[]; author?: string; category?: string; doc_url?: string; /** Machine-readable module identifier (defaults to adapter.name). */ slug?: string; /** UI-friendly title. */ title?: string; /** One-line summary. */ summary?: string; /** Path/ref to the module icon (SVG file in the package, or a lucide name). */ icon?: string; /** Brand color hex. */ color?: string; /** Module version (SemVer). */ version?: string; /** URL to longer docs. */ docsUrl?: string; /** Lifecycle marker. */ status?: "stable" | "beta" | "experimental" | "deprecated"; /** Other modules this one depends on. */ requires?: string[]; /** Minimum Node.js version required. */ minNodeVersion?: string; /** Slug of the primary credential type this module consumes (null if none). */ credentialsType?: string | null; /** Named operation groups used by function.group. */ operationGroups?: Record; } export declare class RobinPath { private static versionLogged; /** Default console-based ask fallback (uses Node.js readline for stdin) */ private static consoleAsk; private environment; private persistentExecutor; private lastExecutor; private activeExecutor; private threads; private currentThread; private threadControl; private replBuffer; private astToCodeConverter; private serializer; private stateTracker; private credentialStore; private credentialTypesMap; private credentialTesters; private executionCredentialState; private moduleHost; constructor(options?: { threadControl?: boolean; }); /** * Get execution steps from the last execution */ getExecutionSteps(): import('./classes').ExecutionStepInfo[]; /** * Get execution logs from the last execution */ getExecutionLogs(): ExecutionLog[]; /** * Set a callback for real-time log notifications * The callback is called immediately when a log is added during execution */ setLogCallback(callback: ((log: ExecutionLog) => void) | null): void; /** * Set a callback for block lifecycle events (stepped execution). * Called when each top-level do/enddo block starts, completes, or errors. * * Example: * ``` * rp.setBlockCallback((event) => { * if (event.status === 'start') * console.log(`[${event.index+1}/${event.total}] Starting: ${event.description}`); * if (event.status === 'complete') * console.log(`[${event.index+1}/${event.total}] Done in ${event.durationMs}ms`); * if (event.status === 'error') * console.log(`[${event.index+1}/${event.total}] Error: ${event.error}`); * }); * ``` */ setBlockCallback(callback: ((event: BlockEvent) => void) | null): void; /** * Clear execution state */ clearExecutionState(): void; /** Pause execution between blocks. The current block finishes first. */ pause(): void; /** Resume paused execution. */ resume(): void; /** Cancel execution. The current block finishes, then execution stops. */ cancel(): void; /** Execute one block then auto-pause (step-through debugging). */ step(): void; /** Check if execution is currently paused */ get isPaused(): boolean; /** Check if execution was cancelled */ get isCancelled(): boolean; /** * Native modules registry * Add new modules here to auto-load them */ private static readonly NATIVE_MODULES; /** * Install an external ModuleAdapter — the public equivalent of the * internal native-module loader. Wires everything up in one call: * - registers credential type schemas * - invokes the module's configure() hook with the ModuleHost * - registers handlers + per-function metadata + module metadata * * External modules should use this instead of the three low-level * register* methods so their configure() hook fires. * * @example * import AirtableModule from "@robinpath/airtable"; * rp.installModule(AirtableModule); */ installModule(module: ModuleAdapter): void; /** * Load a single module using the adapter pattern */ private loadModule; /** * Load all native modules */ private loadNativeModules; /** * Register a builtin function */ registerBuiltin(name: string, handler: BuiltinHandler): void; /** * Install a credential store backend. Replaces the default in-memory store. * Mutates the shared ModuleHost in place so already-loaded modules — * which hold a reference to it via their configure() hook — see the new * backend on their next handler call (as long as they dereference * `host.credentials` fresh on each call). * * @example * rp.registerCredentialStore(new FileCredentialStore()); * rp.registerCredentialStore(new HttpCredentialStore({ baseUrl, token })); */ registerCredentialStore(store: CredentialStore): void; /** Return the currently installed credential store. */ getCredentialStore(): CredentialStore; /** * Register a credential type schema. Usually called via a ModuleAdapter's * `credentialTypes` field, but exposed publicly so hosts can inject extras * (e.g. a first-party `openai` credential that isn't tied to a module). */ registerCredentialType(schema: CredentialTypeSchema): void; /** Return all registered credential type schemas. */ getCredentialTypes(): CredentialTypeSchema[]; /** * Register a tester for a credential type. The tester is invoked by * `credential.test slug` after the credential is decrypted. Returning * `{ok: false, error}` surfaces the failure to the caller without throwing. * * Built-in testers ship for: slack_bot_token, smtp_email, api_key, * bearer_token, webhook_url. Overriding is allowed. * * @example * rp.registerCredentialTester('stripe', async (fields) => { * const r = await fetch('https://api.stripe.com/v1/balance', { * headers: { Authorization: `Bearer ${fields.api_key}` }, * }); * return r.ok ? { ok: true } : { ok: false, error: `HTTP ${r.status}` }; * }); */ registerCredentialTester(type: string, tester: CredentialTester): void; /** Look up a tester for a credential type, or null if none is registered. */ getCredentialTester(type: string): CredentialTester | null; /** * Return every distinct scalar secret value resolved during the current * execution. Call this before persisting execution logs and scrub matches * from the log text — see `redactLogs()` for a ready-made helper. */ getRedactableValues(): string[]; /** * Return the credential-access audit log for the current execution * (slug → {type, accessedAt}). */ getCredentialAccessLog(): Record; /** * Clear per-execution credential state (cache + access log). The runtime * calls this automatically at the start of every executeScript/Block/Line, * so hosts rarely need to call it directly. */ resetCredentialExecutionState(): void; /** * Replace every occurrence of the current run's secret values with `mask`. * Use this before persisting or emitting execution logs to guarantee * decrypted credentials never leak. */ redactLogs(text: string, mask?: string): string; /** Set the memory handler for persistent think context across runs */ setThinkMemoryHandler(handler: ThinkMemoryHandler): void; /** Set the confirm handler for human-in-the-loop approval */ setThinkConfirmHandler(handler: ThinkConfirmHandler): void; /** Set the callback for streaming think block tokens to the host */ setOnStreamToken(callback: (delta: string) => void): void; /** Set the callback for think block completion (cost visibility) */ setOnThinkComplete(callback: (info: { model: string; promptTokens: number; completionTokens: number; cost: number; totalCost: number; }) => void): void; /** Set the handler for persisting remember block data */ setRememberHandler(handler: RememberHandler): void; /** Register a named AI agent for use in think blocks (e.g., think rabbit_agent) */ registerAgent(name: string, config: AgentConfig): void; /** Remove a named AI agent from the registry */ unregisterAgent(name: string): void; /** Get the remember store (all remembered entries) */ getRememberStore(): Map; /** Set the handler for interactive input (ask) and approval gates (approve). * Also unifies thinkConfirmHandler to use the same approve method. */ setAskHandler(handler: AskHandler): void; /** * Set all host handlers at once via a unified RobinPathHost interface. * This is the recommended way to configure RobinPath — implement one interface * instead of calling 5+ individual setters. * * @example * rp.setHost({ * think: myThinkProvider, * ask: { ask: myAskFn, approve: myApproveFn }, * remember: myRememberStore, * onStreamToken: (delta) => process.stdout.write(delta), * }); */ setHost(host: RobinPathHost): void; /** * Set the ThinkHandler for AI-powered think blocks. * The host (CLI, MCP server) provides the implementation that calls the AI API. * Also registers think.* sugar functions (classify, extract, summarize, ask, sentiment, translate). */ setThinkHandler(handler: ThinkHandler): void; /** * Register a runtime decorator function that can be used to modify function calls at execution time * Runtime decorators execute during function execution and can modify arguments or behavior * Decorators are only available via API registration, not in scripts * @param name Decorator name (without @ prefix) * @param handler Decorator handler function */ registerDecorator(name: string, handler: DecoratorHandler): void; /** * Register a parse-time decorator function that executes during parsing * Parse decorators inject metadata into AST nodes (def, on, var, const) * They run during parsing, not execution, and work with AST arguments * @param name Decorator name (without @ prefix) * @param handler Parse decorator handler function */ registerParseDecorator(name: string, handler: ParseDecoratorHandler): void; /** * Register built-in parse-time decorators (@desc/@description, @title, @param, @arg, @required) * These decorators execute during parsing and inject metadata into AST nodes */ private registerBuiltinDecorators; /** * Register a module with multiple functions * @example * rp.registerModule('fs', { * read: (args) => { ... }, * write: (args) => { ... } * }); */ registerModule(moduleName: string, functions: Record): void; /** * Register a module function (e.g., 'fs.read') */ registerModuleFunction(module: string, func: string, handler: BuiltinHandler): void; /** * Register an external class constructor (e.g., 'Client', 'Database') */ registerConstructor(name: string, handler: BuiltinHandler): void; /** * Register metadata for a module with multiple functions * @example * rp.registerModuleMeta('fs', { * read: { * description: 'Reads a file from the filesystem', * parameters: [ * { * name: 'filename', * dataType: 'string', * description: 'Path to the file to read', * formInputType: 'text', * required: true * } * ], * returnType: 'string', * returnDescription: 'Contents of the file' * }, * write: { * description: 'Writes content to a file', * parameters: [ * { * name: 'filename', * dataType: 'string', * description: 'Path to the file to write', * formInputType: 'text', * required: true * }, * { * name: 'content', * dataType: 'string', * description: 'Content to write to the file', * formInputType: 'textarea', * required: true * } * ], * returnType: 'boolean', * returnDescription: 'True if write was successful' * } * }); */ registerModuleMeta(moduleName: string, functions: Record): void; /** * Register metadata for a single module function (e.g., 'fs.read') * @example * rp.registerModuleFunctionMeta('fs', 'read', { * description: 'Reads a file from the filesystem', * parameters: [ * { * name: 'filename', * dataType: 'string', * description: 'Path to the file to read', * formInputType: 'text', * required: true * } * ], * returnType: 'string', * returnDescription: 'Contents of the file' * }); */ registerModuleFunctionMeta(module: string, func: string, metadata: FunctionMetadata): void; /** * Get metadata for a function (builtin or module function) * Returns null if no metadata is registered */ getFunctionMetadata(functionName: string): FunctionMetadata | null; /** * Get all registered function metadata */ getAllFunctionMetadata(): Map; /** * Register module-level metadata (description and list of methods) * @example * rp.registerModuleInfo('fs', { * description: 'File system operations for reading and writing files', * methods: ['read', 'write', 'exists', 'delete'] * }); */ registerModuleInfo(moduleName: string, metadata: ModuleMetadata): void; /** * Get module metadata (description and methods list) * Returns null if no metadata is registered */ getModuleInfo(moduleName: string): ModuleMetadata | null; /** * Get all registered module metadata */ getAllModuleInfo(): Map; /** * Get syntax context for available commands * Determines what commands are valid based on the current syntax position */ private getSyntaxContext; /** * Get all available commands, modules, and functions * Returns a structured object with categories, each containing objects with: * - name: The command/function name * - type: The type (native, builtin, module, moduleFunction, userFunction) * - description: Description if available * * @param context Optional syntax context to filter commands based on what's valid next */ getAvailableCommands(context?: { inIfBlock?: boolean; inDefBlock?: boolean; afterIf?: boolean; afterDef?: boolean; afterElseif?: boolean; }): { native: Array<{ name: string; type: string; description: string; }>; builtin: Array<{ name: string; type: string; description: string; }>; modules: Array<{ name: string; type: string; description: string; author?: string; category?: string; }>; moduleFunctions: Array<{ name: string; type: string; description: string; }>; userFunctions: Array<{ name: string; type: string; description: string; }>; }; /** * Check if a script needs more input (incomplete block) * Returns { needsMore: true, waitingFor: 'endif' | 'enddef' | 'endfor' | 'enddo' | 'endon' | 'subexpr' | 'paren' | 'object' | 'array' } if incomplete, * or { needsMore: false } if complete. */ needsMoreInput(script: string): Promise<{ needsMore: boolean; waitingFor?: "endif" | "enddef" | "endfor" | "enddo" | "endon" | "subexpr" | "paren" | "object" | "array"; }>; /** * Get the AST without execution state * Returns a JSON-serializable AST array * * Note: This method only parses the script, it does not execute it. */ getAST(script: string): Promise; /** * Get extracted function definitions (def/enddef blocks) from a script * Returns a JSON-serializable array of function definitions * * Note: This method only parses the script, it does not execute it. */ getExtractedFunctions(script: string): Promise; /** * Serialize a statement to JSON * @param stmt The statement to serialize * @param currentModuleContext Optional module context * @param lastValue Optional execution state * @param nodeKey Optional node key */ private serializeStatement; /** * Get the complete structure of the script in a tree format * Includes main body, functions, event handlers, and variables */ getScriptStructure(script: string): Promise; /** * Get extracted variables from the script (parsed, not executed) * Returns variable names with optional description and initial value */ getExtractedVariables(script: string): Promise>; /** * Update source code based on AST changes * Uses precise character-level positions (codePos.startRow/startCol/endRow/endCol) to update code * Nested nodes are reconstructed as part of their parent's code * @param originalScript The original source code * @param ast The modified AST array (top-level nodes only) * @returns Updated source code */ updateCodeFromAST(originalScript: string, ast: any[]): Promise; /** * Reconstruct code from an AST node * @param node The AST node (serialized) * @param indentLevel Indentation level for nested code * @returns Reconstructed code string, or null if cannot be reconstructed */ reconstructCodeFromASTNode(node: any, indentLevel?: number): string | null; /** * Execute a RobinPath script */ executeScript(script: string): Promise; /** * Execute a single block from a script by nodeKey. * Parses the full script (registers functions, event handlers), * but only executes the block matching the given nodeKey. * * This is useful for testing individual blocks without running the entire script. * All function definitions and event handlers are available to the block. * * @param script The full script source * @param nodeKey The nodeKey of the block to execute (e.g. "root-2") * @returns The block's return value */ executeBlock(script: string, nodeKey: string): Promise; /** * Execute a partial script — flexible execution for IDE-style workflows. * * Modes: * - `{ nodeKeys: ["root-1", "root-3"] }` — run specific blocks by nodeKey * - `{ fromNodeKey: "root-2" }` — run from this block to end * - `{ toNodeKey: "root-2" }` — run from start up to and including this block * - `{ startLine: 5, endLine: 15 }` — run code in line range (1-based) * * All function definitions and event handlers from the full script are always available. */ executePartial(script: string, options: { nodeKeys?: string[]; fromNodeKey?: string; toNodeKey?: string; startLine?: number; endLine?: number; }): Promise; /** * Execute a single line (for REPL) * Uses a persistent executor to maintain state ($, variables) between calls. * Functions and builtins persist across calls. */ executeLine(line: string): Promise; /** * Get the last value ($) * Returns the value from the most recent execution (script or REPL line). */ getLastValue(): Value; /** * REPL-friendly execution that supports multi-line blocks (if/def/for and $( ... )). * * Usage pattern: * - Call this for every user-entered line. * - If done === false, keep collecting lines. * - When done === true, value is the execution result and the buffer is cleared. */ executeReplLine(line: string): Promise<{ done: boolean; value: Value | null; waitingFor?: string; }>; /** * Generate a UUID v4 */ private generateUUID; /** * Create a new thread/session. * Each thread has its own variables, functions, and $, * but shares builtins and metadata with the root interpreter. * * @param id Optional thread ID. If not provided, a UUID will be generated. * @returns The created thread * * @example * const rp = new RobinPath(); * const thread = rp.createThread('my-thread'); * await thread.executeScript('math.add 5 5'); * console.log(thread.getLastValue()); // 10 */ createThread(id?: string): RobinPathThread; /** * Get a thread by ID */ getThread(id: string): RobinPathThread | null; /** * List all threads with their IDs */ listThreads(): Array<{ id: string; isCurrent: boolean; }>; /** * Switch to a different thread */ useThread(id: string): void; /** * Get the current thread */ getCurrentThread(): RobinPathThread | null; /** * Check if thread control is enabled */ isThreadControlEnabled(): boolean; /** * Close a thread by ID * If the closed thread is the current thread, currentThread is set to null */ closeThread(id: string): void; /** * Trigger an event, executing all registered event handlers for the event name * @param eventName The name of the event to trigger * @param args Arguments to pass to event handlers (available as $1, $2, $3, etc.) * @returns Promise that resolves when all handlers have executed */ trigger(eventName: string, ...args: Value[]): Promise; /** * Get all event handlers (onBlocks) registered in the environment * @returns Map of event name to array of OnBlock handlers */ getEventHandlers(): Map; /** * Get all event handlers as a flat array * @returns Array of all OnBlock handlers */ getAllEventHandlers(): OnBlock[]; /** * Get event handlers as serialized AST * @returns Array of serialized event handler AST nodes */ getEventAST(): any[]; /** * Get a variable value */ getVariable(name: string): Value; /** * Set a variable value (for external use) */ setVariable(name: string, value: Value): void; /** * Get all variables as a plain object */ getVariableState(): Record; /** * Get the next statement index that would execute after a given statement. * This method analyzes the AST structure to determine execution flow. * * @param statements The array of all statements * @param currentIndex The index of the current statement * @param context Optional context for conditional branches (which branch was taken) * @returns The index of the next statement to execute, or -1 if execution ends */ getNextStatementIndex(statements: Statement[], currentIndex: number, context?: { ifBlockBranch?: "then" | "elseif" | "else" | null; forLoopIteration?: number; }): number; }