//#region extensions/crypto/src/services/plan-types.d.ts /** * Plan IR (Intermediate Representation) — the structured format for compound operations. * * The LLM compiles natural language into this IR. The validator checks it. The scheduler * persists it. The executor runs it. Every compound operation — from "swap ETH to USDC" * to "if ETH > $4000 at 5pm, sell half then bridge to Arbitrum" — compiles to a Plan. * * ─── Design Principles ───────────────────────────────────────────────── * * 1. Plans are data, not code. A Plan is JSON-serializable, inspectable, diffable. * The LLM produces them. Humans can read them. The validator can reason about them. * * 2. Small set of orthogonal primitives. Six node types compose into any compound * operation: Action, Sequence, Conditional, Loop, Wait, and Gate. No special-casing. * * 3. Separation of trigger from execution. A Plan says WHAT to do. A Trigger says * WHEN to start. The scheduler owns triggers; the executor owns plans. * * 4. Explicit failure modes. Every node can declare `onFailure`: abort the plan, * skip and continue, or retry N times. No implicit behavior. * * 5. Observable state. Every plan execution produces a PlanExecution record with * per-step status, timestamps, results, and errors. Fully auditable. */ /** A reference to a value that may come from a previous step's output. */ type ValueRef = { type: 'literal'; value: string | number | boolean; } | { type: 'step_output'; stepId: string; path: string; } | { type: 'env'; key: string; } | { type: 'runtime'; fn: RuntimeFn; args: ValueRef[]; }; /** Runtime functions the executor can evaluate. */ type RuntimeFn = 'price' | 'balance' | 'gas_price' | 'timestamp' | 'block_number'; /** Comparison operators for conditions. */ type CompareOp = 'gt' | 'gte' | 'lt' | 'lte' | 'eq' | 'neq'; /** Logical operators for combining conditions. */ type LogicOp = 'and' | 'or' | 'not'; /** A single comparison: left right. */ interface CompareCondition { type: 'compare'; left: ValueRef; op: CompareOp; right: ValueRef; /** Human-readable description for display. */ label?: string; } /** Logical combination of conditions. */ interface LogicCondition { type: 'logic'; op: LogicOp; conditions: Condition[]; } type Condition = CompareCondition | LogicCondition; /** What to do when a node fails. */ type FailurePolicy = { strategy: 'abort'; } | { strategy: 'skip'; reason?: string; } | { strategy: 'retry'; maxAttempts: number; delayMs: number; backoffMultiplier?: number; }; /** Base fields shared by all plan nodes. */ interface PlanNodeBase { /** Unique identifier within this plan. Used by ValueRef to reference outputs. */ id: string; /** Human-readable label shown to user. */ label: string; /** What to do if this node fails. Default: abort. */ onFailure?: FailurePolicy; /** Optional timeout for this node in ms. */ timeoutMs?: number; } /** Call a tool with parameters. The atomic unit of work. */ interface ActionNode extends PlanNodeBase { type: 'action'; /** Tool name (e.g., 'defi_swap', 'transfer', 'manage_orders'). */ tool: string; /** Tool parameters. Values can be literals or references to prior step outputs. */ params: Record; /** * If true, executor must confirm with user before executing (regardless of autosign). * Use for high-value or irreversible operations. */ requireConfirmation?: boolean; /** * Fallback branch executed when this action fails after all retries are exhausted. * If present, the executor runs this sub-tree instead of propagating the failure up. * Use for graceful degradation (e.g., swap fails → skip bridge, notify user). */ onError?: PlanNode; } /** Run child nodes in order. The output of each node is available to the next. */ interface SequenceNode extends PlanNodeBase { type: 'sequence'; steps: PlanNode[]; } /** Run child nodes concurrently. Only for independent operations (reads, price checks). */ interface ParallelNode extends PlanNodeBase { type: 'parallel'; steps: PlanNode[]; /** If true, continue even if some parallel steps fail. Default: false. */ allowPartialFailure?: boolean; } /** Conditional branching. */ interface IfNode extends PlanNodeBase { type: 'if'; condition: Condition; then: PlanNode; else?: PlanNode; } /** * Pause execution until a condition is met or a duration passes. * The scheduler polls the condition at `pollIntervalMs`. */ interface WaitNode extends PlanNodeBase { type: 'wait'; /** Wait until this condition is true. */ until?: Condition; /** Wait for a fixed duration (ms). Mutually exclusive with `until`. */ durationMs?: number; /** Wait until a specific time (ISO 8601). Mutually exclusive with `until` and `durationMs`. */ untilTime?: string; /** How often to check the `until` condition (ms). Default: 60_000 (1 min). */ pollIntervalMs?: number; /** Maximum time to wait before giving up (ms). Default: 86_400_000 (24h). */ maxWaitMs?: number; } /** Repeat a node. */ interface LoopNode extends PlanNodeBase { type: 'loop'; body: PlanNode; /** Stop when this condition is true. Checked after each iteration. */ exitWhen?: Condition; /** Maximum iterations. Required as a safety bound. */ maxIterations: number; /** Delay between iterations (ms). Default: 0. */ delayMs?: number; } type PlanNode = ActionNode | SequenceNode | ParallelNode | IfNode | WaitNode | LoopNode; /** Execute at a specific time. */ interface TimeTrigger { type: 'time'; /** ISO 8601 datetime string (e.g., "2026-03-06T17:00:00Z"). */ at: string; } /** Execute on a recurring schedule. */ interface IntervalTrigger { type: 'interval'; /** Interval in ms between executions. */ everyMs: number; /** First execution time (ISO 8601). If omitted, starts immediately. */ startAt?: string; /** Stop recurring after this time. */ endAt?: string; /** Max total executions. */ maxRuns?: number; } /** Execute when a condition becomes true (polled). */ interface ConditionTrigger { type: 'condition'; /** The condition to watch. */ when: Condition; /** How often to poll (ms). Default: 60_000. */ pollIntervalMs?: number; /** Stop watching after this time (ms from creation). */ expiresAfterMs?: number; /** If true, trigger fires every time condition is met (not just first). Default: false. */ recurring?: boolean; } /** Execute immediately. */ interface ImmediateTrigger { type: 'immediate'; } /** Execute on a cron schedule (e.g., "0 9 * * 1" for every Monday at 9am). */ interface CronTrigger { type: 'cron'; /** Standard 5-field cron expression: minute hour day-of-month month day-of-week. */ expression: string; /** IANA timezone (e.g., "America/New_York"). Default: UTC. */ timezone?: string; /** Max total executions. */ maxRuns?: number; } /** Execute when a price threshold is breached. */ interface PriceTrigger { type: 'price'; /** Token symbol to watch (e.g., "ETH", "BTC"). */ token: string; /** Trigger when price is above, below, or crosses the threshold. */ condition: 'above' | 'below' | 'crosses'; /** Price threshold in USD. */ threshold: number; /** Hysteresis: price must move this % past threshold before re-triggering. Default: 1. */ hysteresisPercent?: number; /** Minimum cooldown between triggers in ms. Default: 300_000 (5 min). */ cooldownMs?: number; /** If true, trigger fires every time condition is met (not just first). Default: false. */ recurring?: boolean; } /** Execute when an on-chain event is detected (contract log). */ interface OnChainEventTrigger { type: 'onchain_event'; /** Chain ID to monitor. */ chainId: number; /** Contract address to watch. */ contractAddress: string; /** Event signature to filter (e.g. 'Transfer(address,address,uint256)'). */ eventSignature: string; /** Optional topic filters (indexed params). null = any value. */ topicFilters?: (string | null)[]; /** If true, trigger fires on every matching event. Default: false (one-shot). */ recurring?: boolean; } /** Execute when a token balance crosses a threshold. */ interface BalanceTrigger { type: 'balance'; /** Token symbol or contract address. */ token: string; /** Chain ID. Default: 8453 (Base). */ chainId?: number; /** Condition: balance drops below or rises above threshold. */ condition: 'above' | 'below'; /** Balance threshold (in token units, not wei). */ threshold: number; /** If true, trigger fires repeatedly. Default: false. */ recurring?: boolean; } type Trigger = TimeTrigger | IntervalTrigger | ConditionTrigger | ImmediateTrigger | CronTrigger | PriceTrigger | OnChainEventTrigger | BalanceTrigger; type PlanStatus = 'draft' | 'validated' | 'scheduled' | 'running' | 'paused' | 'completed' | 'failed' | 'cancelled'; interface Plan { /** Unique plan ID. Generated on creation. */ id: string; /** Human-readable name (e.g., "Sell ETH at $4000 and bridge to Arbitrum"). */ name: string; /** The user who created this plan. */ userId: string; /** When was this plan created. */ createdAt: number; /** Current status. */ status: PlanStatus; /** When to start execution. If omitted, executes immediately. */ trigger?: Trigger; /** The operation tree. */ root: PlanNode; /** Validation results (populated by PlanValidator). */ validation?: ValidationResult; /** Tags for organization (e.g., ['swap', 'eth', 'scheduled']). */ tags?: string[]; /** The original natural language request that produced this plan. */ naturalLanguage?: string; } type IssueSeverity = 'error' | 'warning' | 'info'; interface ValidationIssue { severity: IssueSeverity; /** Which node caused this issue (by id). Null for plan-level issues. */ nodeId: string | null; /** Issue code for programmatic handling. */ code: string; /** Human-readable description. */ message: string; } interface ValidationResult { valid: boolean; issues: ValidationIssue[]; /** Estimated total gas cost in ETH (rough). */ estimatedGasEth?: number; /** Estimated total time to complete (ms). */ estimatedDurationMs?: number; /** Tools this plan will use. */ toolsUsed: string[]; /** Chains this plan will touch. */ chainsUsed: number[]; } type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'waiting'; interface StepExecution { nodeId: string; status: StepStatus; startedAt?: number; completedAt?: number; /** The result returned by the tool (for action nodes). */ result?: unknown; /** Error message if failed. */ error?: string; /** Number of retry attempts made. */ retryCount?: number; } interface PlanExecution { planId: string; /** Unique execution ID (a plan can execute multiple times via interval triggers). */ executionId: string; status: 'running' | 'completed' | 'failed' | 'cancelled'; startedAt: number; completedAt?: number; steps: StepExecution[]; /** Cumulative gas spent in ETH. */ gasSpentEth?: number; } /** A reusable plan template with parameterizable fields. */ interface PlanTemplate { /** Unique template ID. */ id: string; /** Human-readable name (e.g., "DCA ETH weekly"). */ name: string; /** Description of what this template does. */ description?: string; /** The user who created this template. */ createdBy: string; /** When this template was saved. */ createdAt: number; /** Tags for organization. */ tags?: string[]; /** * The intent that created this template. Stored so it can be * re-compiled with different parameters. */ intent: { naturalLanguage: string; steps: Record[]; trigger?: Record; tags?: string[]; }; /** * Parameter placeholders. Each key is a placeholder name (e.g., "amount"), * and the value describes where it appears and its default. */ params?: Record; } interface PlanStore { save(plan: Plan): void; load(planId: string): Plan | null; loadAll(userId?: string): Plan[]; delete(planId: string): boolean; saveExecution(exec: PlanExecution): void; loadExecutions(planId: string): PlanExecution[]; } interface DeadLetterEntry { /** The plan that failed. */ planId: string; /** The node that failed. */ nodeId: string; /** The execution ID. */ executionId: string; /** The user who owns the plan. */ userId: string; /** Error message from the final attempt. */ error: string; /** Number of retry attempts made. */ retryCount: number; /** Tool name (for action nodes). */ tool?: string; /** Resolved params at time of failure. */ params?: Record; /** When the failure occurred. */ timestamp: number; } interface ExecutionCheckpoint { /** The execution ID. */ executionId: string; /** The plan being executed. */ planId: string; /** The user who owns the plan. */ userId: string; /** ID of the node currently being executed (or next to execute). */ currentNodeId: string; /** Results from completed steps, serialized as [nodeId, result] tuples. */ stepResults: Array<[string, unknown]>; /** Step execution records so far. */ steps: StepExecution[]; /** Execution status. */ status: 'running' | 'paused'; /** When execution started. */ startedAt: number; /** When this checkpoint was written. */ updatedAt: number; } declare const CONTRADICTION_CODES: { readonly BUY_AND_SELL_SAME_TOKEN: "CONTRA_BUY_SELL"; readonly SPEND_MORE_THAN_BALANCE: "CONTRA_OVERSPEND"; readonly OPPOSITE_CONDITIONS: "CONTRA_OPPOSITE_COND"; readonly IMPOSSIBLE_TIMING: "CONTRA_TIMING"; readonly CIRCULAR_DEPENDENCY: "CONTRA_CIRCULAR"; readonly DUPLICATE_ACTION: "CONTRA_DUPLICATE"; readonly CONFLICTING_SLIPPAGE: "CONTRA_SLIPPAGE"; readonly UNSUPPORTED_CHAIN: "CONTRA_CHAIN"; readonly MISSING_TOOL: "CONTRA_NO_TOOL"; readonly INFINITE_LOOP: "CONTRA_INFINITE"; }; type ContradictionCode = typeof CONTRADICTION_CODES[keyof typeof CONTRADICTION_CODES]; //#endregion export { ActionNode, BalanceTrigger, CONTRADICTION_CODES, CompareCondition, CompareOp, Condition, ConditionTrigger, ContradictionCode, CronTrigger, DeadLetterEntry, ExecutionCheckpoint, FailurePolicy, IfNode, ImmediateTrigger, IntervalTrigger, IssueSeverity, LogicCondition, LogicOp, LoopNode, OnChainEventTrigger, ParallelNode, Plan, PlanExecution, PlanNode, PlanStatus, PlanStore, PlanTemplate, PriceTrigger, RuntimeFn, SequenceNode, StepExecution, StepStatus, TimeTrigger, Trigger, ValidationIssue, ValidationResult, ValueRef, WaitNode }; //# sourceMappingURL=plan-types.d.mts.map