@aigne/afs-ash 1.11.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-run-CXJQ0jPV.mjs","names":["found","data"],"sources":["../src/ash-generator.ts","../src/path-validator.ts","../src/tool-schema.ts","../src/agent-run.ts"],"sourcesContent":["/**\n * ASH source generator for agent-run.\n *\n * Converts validated tool_calls into a single ASH program\n * with @caps scoped to the exact paths in this round's calls.\n */\n\nexport interface ValidatedToolCall {\n id: string;\n op: \"read\" | \"list\" | \"exec\";\n path: string;\n args: Record<string, unknown>;\n}\n\n/**\n * Format a value as an ASH inline literal.\n * Strings get quoted, numbers/booleans are bare.\n */\nfunction formatValue(v: unknown): string {\n if (typeof v === \"string\") return JSON.stringify(v);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n return JSON.stringify(v);\n}\n\n/**\n * Format args as ASH inline object: { key: \"val\", num: 42 }\n */\nfunction formatInlineArgs(args: Record<string, unknown>): string {\n const entries = Object.entries(args);\n if (entries.length === 0) return \"\";\n const pairs = entries.map(([k, v]) => `${k}: ${formatValue(v)}`);\n return ` { ${pairs.join(\", \")} }`;\n}\n\n/**\n * Generate a single pipeline statement for a tool call.\n */\nfunction generateStatement(call: ValidatedToolCall): string {\n const resultPath = `/.results/${call.id}`;\n\n if (call.op === \"read\" || call.op === \"list\") {\n return `find ${call.path} | save ${resultPath}`;\n }\n\n // exec\n const inlineArgs = formatInlineArgs(call.args);\n return `action ${call.path}${inlineArgs} | save ${resultPath}`;\n}\n\n/**\n * Derive @caps declaration from the calls in this round.\n *\n * Capabilities:\n * - read: for read/list ops (exact path)\n * - exec: for exec ops (exact path)\n * - write: always /.results/* (where save goes)\n */\nfunction deriveCaps(calls: ValidatedToolCall[]): string {\n const parts: string[] = [];\n\n for (const call of calls) {\n if (call.op === \"read\" || call.op === \"list\") {\n parts.push(`read ${call.path}`);\n } else if (call.op === \"exec\") {\n parts.push(`exec ${call.path}`);\n }\n }\n\n // Always need write for save targets\n parts.push(\"write /.results/*\");\n\n return `@caps(${parts.join(\" \")})`;\n}\n\n/**\n * Generate a complete ASH program from validated tool calls.\n *\n * Each call becomes a separate pipeline within a single job.\n * The program is scoped with @caps derived from actual paths.\n */\nexport function generateAsh(calls: ValidatedToolCall[], round: number): string {\n const caps = deriveCaps(calls);\n const statements = calls.map(generateStatement);\n const body = statements.length > 0 ? statements.join(\"\\n \") : 'output \"no-op\"';\n\n return `${caps}\\njob round_${round} {\\n ${body}\\n}`;\n}\n","/**\n * Path validation for agent-run tool_calls.\n *\n * Validates that LLM-requested paths are within the declared tools sandbox.\n * Supports single-level `*` and multi-level `**` glob matching.\n */\n\nexport interface ToolEntry {\n path: string;\n ops: string[];\n exclude_actions?: string[];\n /** Maximum depth for `**` glob. Counts levels from `**` position. Required when path contains `**`. Defaults to 0. */\n maxDepth?: number;\n}\n\n/**\n * Match an actual path against a declaration pattern.\n *\n * Supports:\n * - Exact: \"/a/b\" matches \"/a/b\"\n * - Single-level `*`: \"/a/*\" matches \"/a/b\" but NOT \"/a/b/c\"\n * - Multi-level `**`: \"/a/**\" matches \"/a/b/c\" up to `maxDepth` levels from `**` position\n *\n * @param maxDepth Maximum levels `**` can consume. Defaults to 0 (no expansion).\n */\nexport function matchPath(actual: string, pattern: string, maxDepth = 0): boolean {\n if (actual === pattern) return true;\n\n const patternParts = pattern.split(\"/\");\n const actualParts = actual.split(\"/\");\n\n const dstarIdx = patternParts.indexOf(\"**\");\n\n if (dstarIdx === -1) {\n // No ** — single-level * logic only\n return matchSingleLevel(actualParts, patternParts);\n }\n\n // ** glob matching with maxDepth\n const prefix = patternParts.slice(0, dstarIdx);\n const suffix = patternParts.slice(dstarIdx + 1);\n\n // Actual must be at least as long as prefix + suffix\n if (actualParts.length < prefix.length + suffix.length) return false;\n\n // Match prefix segments\n for (let i = 0; i < prefix.length; i++) {\n if (prefix[i] === \"*\") continue;\n if (prefix[i] !== actualParts[i]) return false;\n }\n\n // Match suffix segments (aligned to end of actual)\n const suffixStart = actualParts.length - suffix.length;\n if (suffixStart < prefix.length) return false;\n for (let i = 0; i < suffix.length; i++) {\n if (suffix[i] === \"*\") continue;\n if (suffix[i] !== actualParts[suffixStart + i]) return false;\n }\n\n // Count levels consumed by **\n const dstarLevels = actualParts.length - prefix.length - suffix.length;\n return dstarLevels >= 0 && dstarLevels <= maxDepth;\n}\n\n/** Single-level * matching (no **). */\nfunction matchSingleLevel(actualParts: string[], patternParts: string[]): boolean {\n const hasWildcard = patternParts.some((p) => p === \"*\");\n if (!hasWildcard) return false;\n\n if (actualParts.length === patternParts.length) {\n for (let i = 0; i < patternParts.length; i++) {\n if (patternParts[i] === \"*\") continue;\n if (patternParts[i] !== actualParts[i]) return false;\n }\n return true;\n }\n\n if (actualParts.length < patternParts.length) {\n for (let i = actualParts.length; i < patternParts.length; i++) {\n if (patternParts[i] !== \"*\") return false;\n }\n for (let i = 0; i < actualParts.length; i++) {\n if (patternParts[i] !== \"*\" && patternParts[i] !== actualParts[i]) return false;\n }\n return true;\n }\n\n return false;\n}\n\n/**\n * Extract the action name from an exec path.\n * E.g., \"/modules/github/issues/42/.actions/close-issue\" → \"close-issue\"\n */\nfunction extractActionName(path: string): string | undefined {\n const marker = \"/.actions/\";\n const idx = path.lastIndexOf(marker);\n if (idx === -1) return undefined;\n return path.slice(idx + marker.length).split(\"/\")[0];\n}\n\n/**\n * Validate a tool_call's path and operation against the tools declaration.\n */\nexport function validateToolCall(\n path: string,\n op: string,\n tools: ToolEntry[],\n): { allowed: boolean; reason?: string } {\n // For exec paths, also derive the base resource path (without /.actions/<name>)\n // so patterns like \"/modules/github/issues/*\" can match exec calls to\n // \"/modules/github/issues/42/.actions/add-comment\"\n let basePath: string | undefined;\n if (op === \"exec\") {\n const marker = \"/.actions/\";\n const idx = path.indexOf(marker);\n if (idx !== -1) basePath = path.slice(0, idx);\n }\n\n // Find a matching tool entry — check ALL entries, not just the first path match.\n // Multiple entries may cover overlapping paths with different ops.\n let pathMatched = false;\n for (const entry of tools) {\n const md = entry.maxDepth ?? 0;\n if (!matchPath(path, entry.path, md) && !(basePath && matchPath(basePath, entry.path, md)))\n continue;\n\n pathMatched = true;\n\n // Check operation is allowed\n if (!entry.ops.includes(op)) {\n continue; // Try other entries — a different entry may allow this op\n }\n\n // For exec operations, check exclude_actions\n if (op === \"exec\" && entry.exclude_actions?.length) {\n const actionName = extractActionName(path);\n if (actionName && entry.exclude_actions.includes(actionName)) {\n return { allowed: false, reason: `Action '${actionName}' is excluded on '${entry.path}'` };\n }\n }\n\n return { allowed: true };\n }\n\n if (pathMatched) {\n return { allowed: false, reason: `Operation '${op}' not allowed on '${path}'` };\n }\n return { allowed: false, reason: `Path '${path}' not in tools declaration` };\n}\n","/**\n * Tool schema generator for agent-run.\n *\n * Converts ToolEntry[] declarations into OpenAI function-calling format.\n * One tool per unique AFS operation, with path descriptions listing allowed patterns.\n * When actionSchemas are provided, generates per-action tools with explicit typed parameters.\n */\n\nimport type { ToolEntry } from \"./path-validator.js\";\n\nexport interface OpenAITool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, Record<string, unknown>>;\n required: string[];\n };\n };\n}\n\n/** Discovered action schema from startup discovery phase. */\nexport interface ActionSchema {\n actionName: string;\n description: string;\n pathPattern: string;\n inputSchema?: {\n type?: string;\n properties?: Record<string, { type: string; description?: string }>;\n required?: string[];\n };\n}\n\ntype OpName = \"read\" | \"list\" | \"exec\" | \"search\" | \"write\" | \"stat\" | \"explain\";\n\nconst OP_DEFINITIONS: Record<\n OpName,\n {\n name: string;\n description: string;\n extraProps: Record<string, { type: string; description: string }>;\n extraRequired: string[];\n }\n> = {\n read: {\n name: \"afs_read\",\n description: \"Read content at an AFS path\",\n extraProps: {},\n extraRequired: [],\n },\n list: {\n name: \"afs_list\",\n description: \"List directory contents at an AFS path\",\n extraProps: {\n depth: { type: \"number\", description: \"Recursion depth (default 1)\" },\n pattern: { type: \"string\", description: \"Filter pattern, e.g. *.md\" },\n },\n extraRequired: [],\n },\n exec: {\n name: \"afs_exec\",\n description:\n \"Execute an action at an AFS path. IMPORTANT: Before calling, use afs_list on the parent path's .actions/ to discover available actions and their inputSchema, then pass the required fields in args.\",\n extraProps: {\n args: { type: \"object\", description: \"Action arguments matching the action's inputSchema\" },\n },\n extraRequired: [],\n },\n search: {\n name: \"afs_search\",\n description: \"Search for content within an AFS path\",\n extraProps: {\n query: { type: \"string\", description: \"Search query\" },\n },\n extraRequired: [\"query\"],\n },\n write: {\n name: \"afs_write\",\n description: \"Write content to an AFS path\",\n extraProps: {\n content: { type: \"string\", description: \"Content to write\" },\n },\n extraRequired: [\"content\"],\n },\n stat: {\n name: \"afs_stat\",\n description: \"Get metadata for an AFS path\",\n extraProps: {},\n extraRequired: [],\n },\n explain: {\n name: \"afs_explain\",\n description: \"Get a human-readable explanation for an AFS path\",\n extraProps: {},\n extraRequired: [],\n },\n};\n\n/**\n * Build OpenAI function-calling tools from ToolEntry declarations.\n *\n * Deduplicates operations across entries — one tool per unique op.\n * Each tool's path description lists all allowed patterns for that op.\n *\n * When actionSchemas are provided (from startup discovery), generates\n * per-action tools (afs_action_{name}) with explicit typed parameters\n * so LLMs know exactly what fields each action requires.\n */\nexport function buildToolSchema(tools: ToolEntry[], actionSchemas?: ActionSchema[]): OpenAITool[] {\n // Collect paths per operation, excluded actions, and whether ** is used\n const pathsByOp = new Map<string, string[]>();\n const excludedActionsByOp = new Map<string, string[]>();\n const maxDepthByOp = new Map<string, Map<string, number>>(); // op → (path → maxDepth)\n\n for (const entry of tools) {\n for (const op of entry.ops) {\n if (!pathsByOp.has(op)) pathsByOp.set(op, []);\n const paths = pathsByOp.get(op)!;\n if (!paths.includes(entry.path)) paths.push(entry.path);\n\n // Track maxDepth for ** patterns\n if (entry.path.includes(\"**\") && entry.maxDepth != null) {\n if (!maxDepthByOp.has(op)) maxDepthByOp.set(op, new Map());\n maxDepthByOp.get(op)!.set(entry.path, entry.maxDepth);\n }\n\n // Collect exclude_actions for exec operations\n if (op === \"exec\" && entry.exclude_actions?.length) {\n if (!excludedActionsByOp.has(op)) excludedActionsByOp.set(op, []);\n const excluded = excludedActionsByOp.get(op)!;\n for (const a of entry.exclude_actions) {\n if (!excluded.includes(a)) excluded.push(a);\n }\n }\n }\n }\n\n const result: OpenAITool[] = [];\n\n for (const [op, paths] of pathsByOp) {\n const def = OP_DEFINITIONS[op as OpName];\n if (!def) continue;\n\n const depthMap = maxDepthByOp.get(op);\n const hasDstar = paths.some((p) => p.includes(\"**\"));\n\n let pathDesc = `AFS path. Allowed: ${paths.join(\", \")}.`;\n if (hasDstar && depthMap) {\n const depthNotes = [...depthMap.entries()].map(([p, d]) => `${p} (maxDepth ${d})`).join(\", \");\n pathDesc += ` ** matches multiple levels: ${depthNotes}.`;\n }\n pathDesc += \" Note: * matches one level only (e.g. /a/* matches /a/b but NOT /a/b/c).\";\n\n // Include excluded actions in exec tool description\n const excluded = excludedActionsByOp.get(op);\n if (excluded?.length) {\n pathDesc += ` Excluded actions: ${excluded.join(\", \")}.`;\n }\n\n // Enrich afs_exec when discovered action schemas exist:\n // inject action summaries into description, make args required,\n // and give args explicit properties so LLMs fill them correctly.\n let description = def.description;\n let extraProps = def.extraProps as Record<string, Record<string, unknown>>;\n let extraRequired = def.extraRequired;\n if (op === \"exec\" && actionSchemas?.length) {\n const lines = actionSchemas.map((a) => {\n const fields = Object.entries(a.inputSchema?.properties ?? {})\n .map(([k, v]) => {\n const req = a.inputSchema?.required?.includes(k) ? \" (required)\" : \"\";\n return `${k}: ${v.type ?? \"string\"}${req}`;\n })\n .join(\", \");\n return `- ${a.pathPattern}: {${fields || \"none\"}} — ${a.description}`;\n });\n description =\n \"Execute an action. Pass the action's parameters in args.\\n\" +\n `Available actions:\\n${lines.join(\"\\n\")}`;\n extraRequired = [\"args\"];\n\n // Merge all action schemas' properties into args so LLMs see\n // the actual parameter structure, not just an opaque object.\n // Note: do NOT merge required fields — different actions have different\n // required fields. The per-action descriptions indicate which fields are required.\n const mergedProps: Record<string, Record<string, unknown>> = {};\n for (const a of actionSchemas) {\n if (a.inputSchema?.properties) {\n for (const [k, v] of Object.entries(a.inputSchema.properties)) {\n mergedProps[k] = {\n type: v.type ?? \"string\",\n ...(v.description ? { description: v.description } : {}),\n };\n }\n }\n }\n\n extraProps = {\n args: {\n type: \"object\",\n description: \"Action arguments matching the action's inputSchema\",\n ...(Object.keys(mergedProps).length > 0 ? { properties: mergedProps } : {}),\n },\n };\n }\n\n result.push({\n type: \"function\",\n function: {\n name: def.name,\n description,\n parameters: {\n type: \"object\",\n properties: {\n path: { type: \"string\", description: pathDesc },\n ...extraProps,\n },\n required: [\"path\", ...extraRequired],\n },\n },\n });\n }\n\n return result;\n}\n","/**\n * Agent-run loop for ASH provider.\n *\n * Combines LLM inference (via AigneHub), tool_call validation (path-validator),\n * ASH execution (for read/list/exec), and direct AFS calls (for search/write/stat/explain)\n * into a multi-round agentic loop.\n */\n\nimport type { AFSExecResult } from \"@aigne/afs\";\nimport { generateAsh, type ValidatedToolCall } from \"./ash-generator.js\";\nimport { type ToolEntry, validateToolCall } from \"./path-validator.js\";\nimport { type ActionSchema, buildToolSchema } from \"./tool-schema.js\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface AgentRunParams {\n task: string;\n model: string;\n tools: ToolEntry[];\n budget?: {\n max_rounds?: number;\n actions_per_round?: number;\n total_tokens?: number;\n };\n system?: string;\n session?: string;\n}\n\nexport interface TraceEntry {\n round: number;\n tool_calls: Array<{\n id: string;\n name: string;\n path: string;\n status: \"ok\" | \"error\";\n error?: string;\n }>;\n tokens: { input: number; output: number };\n}\n\nexport interface AgentRunResult {\n status: \"completed\" | \"budget_exhausted\" | \"error\";\n result?: string;\n error?: string;\n rounds: number;\n total_actions: number;\n total_tokens: number;\n trace: TraceEntry[];\n}\n\n/** Message types for JSONL history (OpenAI canonical snake_case format) */\nexport interface HistoryToolCall {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n}\n\nexport type HistoryMessage =\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string; tool_calls?: HistoryToolCall[] }\n | { role: \"tool\"; tool_call_id: string; content: string };\n\nexport interface AgentRunDeps {\n callLLM: (args: Record<string, unknown>) => Promise<AFSExecResult>;\n runAsh: (source: string, args: Record<string, unknown>) => Promise<AFSExecResult>;\n callAFS: (op: string, path: string, args?: Record<string, unknown>) => Promise<AFSExecResult>;\n loadHistory?: (sessionPath: string) => Promise<HistoryMessage[]>;\n saveHistory?: (sessionPath: string, messages: HistoryMessage[]) => Promise<void>;\n}\n\n// ─── Constants ──────────────────────────────────────────────────────────────\n\nconst DEFAULT_MAX_ROUNDS = 20;\nconst DEFAULT_ACTIONS_PER_ROUND = 10;\nconst RESULTS_PREFIX = \"/.results/\";\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\n/**\n * Operations routed through ASH (deterministic sandbox).\n *\n * Currently empty: all ops go through direct AFS calls.\n * agent-run's security comes from path-validator (tools declaration whitelist),\n * not from ASH @caps. The ASH sandbox is valuable for user-written scripts\n * (/.actions/run) but redundant for agent-run's auto-generated single-step execs.\n */\nconst ASH_OPS = new Set<string>([]);\n\n/** Required arguments per operation (beyond path) */\nconst REQUIRED_ARGS: Record<string, string[]> = {\n search: [\"query\"],\n write: [\"content\"],\n};\n\n/** Map tool function name → AFS operation name */\nfunction toolNameToOp(name: string): string | undefined {\n // Per-action tools (afs_action_send, afs_action_do_thing, etc.) → exec\n if (name.startsWith(\"afs_action_\")) return \"exec\";\n\n const map: Record<string, string> = {\n afs_read: \"read\",\n afs_list: \"list\",\n afs_exec: \"exec\",\n afs_search: \"search\",\n afs_write: \"write\",\n afs_stat: \"stat\",\n afs_explain: \"explain\",\n };\n return map[name];\n}\n\ninterface ToolCallInput {\n toolCallId: string;\n toolName: string;\n args: Record<string, unknown>;\n}\n\n/**\n * Normalize a tool call from any format to our internal ToolCallInput.\n *\n * AigneHub returns OpenAI format:\n * { id, type: \"function\", function: { name, arguments } }\n * Some SDKs return Vercel AI SDK format:\n * { toolCallId, toolName, args }\n */\nfunction normalizeToolCall(tc: Record<string, unknown>): ToolCallInput {\n // Vercel AI SDK format\n if (tc.toolCallId && tc.toolName) {\n return {\n toolCallId: tc.toolCallId as string,\n toolName: tc.toolName as string,\n args: (tc.args as Record<string, unknown>) ?? {},\n };\n }\n\n // OpenAI format: { id, function: { name, arguments } }\n const fn = tc.function as Record<string, unknown> | undefined;\n const rawArgs = fn?.arguments;\n let args: Record<string, unknown> = {};\n if (typeof rawArgs === \"string\") {\n try {\n args = JSON.parse(rawArgs);\n } catch {\n args = { _parseError: `Invalid JSON in function arguments: ${rawArgs.slice(0, 200)}` };\n }\n } else if (rawArgs && typeof rawArgs === \"object\") {\n args = rawArgs as Record<string, unknown>;\n }\n\n return {\n toolCallId: (tc.toolCallId ?? tc.id ?? \"\") as string,\n toolName: (tc.toolName ?? fn?.name ?? \"\") as string,\n args,\n };\n}\n\n/**\n * Fix path for per-action tool calls.\n *\n * LLMs often make mistakes with per-action tools:\n * 1. Put tool name in path: /.actions/afs_action_send → /.actions/send\n * 2. Drop mount prefix: /default/conversations/123 → /telegram/default/conversations/123\n *\n * Uses discovered pathPattern to auto-correct missing mount prefixes.\n * Mutates call.args.path in place.\n */\nfunction fixPerActionPath(call: ToolCallInput, schemasByAction: Map<string, ActionSchema>): void {\n const path = call.args.path as string | undefined;\n if (!path) return;\n\n // Extract real action name: afs_action_send → send, afs_action_do_thing → do-thing\n const rawName = call.toolName.slice(\"afs_action_\".length);\n const realName = rawName.replace(/_/g, \"-\");\n\n // Fix action name in path\n const marker = \"/.actions/\";\n const idx = path.lastIndexOf(marker);\n if (idx !== -1) {\n const currentAction = path.slice(idx + marker.length).split(\"/\")[0];\n if (currentAction && currentAction !== realName) {\n call.args.path = path.slice(0, idx) + marker + realName;\n }\n }\n\n // Fix missing mount prefix using discovered pathPattern\n const schema = schemasByAction.get(realName);\n if (!schema?.pathPattern) return;\n\n const fixedPath = call.args.path as string;\n const starIdx = schema.pathPattern.indexOf(\"*\");\n if (starIdx === -1) return;\n\n const expectedPrefix = schema.pathPattern.slice(0, starIdx);\n if (fixedPath.startsWith(expectedPrefix)) return; // Already correct\n\n // Try to find the missing prefix: check if LLM's path is a suffix of the full path\n // e.g., expectedPrefix = \"/telegram/default/conversations/\"\n // fixedPath starts with \"/default/conversations/\" → missing \"/telegram\"\n for (let i = 1; i < expectedPrefix.length; i++) {\n if (expectedPrefix[i] === \"/\" && fixedPath.startsWith(expectedPrefix.slice(i))) {\n call.args.path = expectedPrefix.slice(0, i) + fixedPath;\n return;\n }\n }\n}\n\n/** Extract exec args from tool call: try nested `args` field first, fall back to all fields except `path`. */\nfunction extractExecArgs(callArgs: Record<string, unknown>): Record<string, unknown> {\n if (callArgs.args && typeof callArgs.args === \"object\" && !Array.isArray(callArgs.args)) {\n return callArgs.args as Record<string, unknown>;\n }\n const { path: _, ...rest } = callArgs;\n return rest;\n}\n\n// ─── Action Discovery ───────────────────────────────────────────────────────\n\n/**\n * Discover available actions and their inputSchemas at startup.\n *\n * Strategy (per exec-capable tool entry):\n * 1. Instance-probe: list basePath to find a child, then list its .actions/\n * 2. Capabilities fallback: walk up path hierarchy to find /.meta/.capabilities,\n * extract action schemas from the manifest's catalog entries\n *\n * Results are used to generate per-action tools with explicit typed parameters.\n * Best-effort: failures are silently ignored and the generic afs_exec fallback remains.\n */\nasync function discoverActionSchemas(\n tools: ToolEntry[],\n deps: AgentRunDeps,\n): Promise<ActionSchema[]> {\n const schemas: ActionSchema[] = [];\n const discoveredPaths = new Set<string>();\n const discoveredActions = new Set<string>();\n\n for (const tool of tools) {\n if (!tool.ops.includes(\"exec\")) continue;\n\n // Strip trailing glob: /foo/bar/* → /foo/bar, /foo/** → /foo\n const basePath = tool.path.replace(/\\/?\\*+$/, \"\");\n if (!basePath || discoveredPaths.has(basePath)) continue;\n discoveredPaths.add(basePath);\n\n try {\n // Fast path: tool path already targets .actions/ — list it directly\n if (basePath.endsWith(\"/.actions\")) {\n await discoverFromActionsDir(tool, basePath, discoveredActions, schemas, deps);\n continue;\n }\n\n // Strategy 1: Instance-probe — list basePath to find a child's .actions/\n const found = await discoverViaInstanceProbe(\n tool,\n basePath,\n discoveredActions,\n schemas,\n deps,\n );\n\n // Strategy 2: Capabilities fallback — read /.meta/.capabilities from mount root\n if (!found) {\n await discoverViaCapabilities(tool, basePath, discoveredActions, schemas, deps);\n }\n } catch {\n // Discovery is best-effort — continue with generic afs_exec\n }\n }\n\n return schemas;\n}\n\n/** Fast path: tool path already ends with /.actions/* — list the directory directly. */\nasync function discoverFromActionsDir(\n tool: ToolEntry,\n actionsPath: string,\n discoveredActions: Set<string>,\n schemas: ActionSchema[],\n deps: AgentRunDeps,\n): Promise<void> {\n const result = await deps.callAFS(\"list\", actionsPath);\n if (!result.success) return;\n\n const actions = extractEntries(result.data);\n for (const action of actions) {\n const name = extractActionNameFromEntry(action);\n if (!name || discoveredActions.has(name)) continue;\n discoveredActions.add(name);\n\n schemas.push({\n actionName: name,\n description: action.meta?.description || `Execute ${name}`,\n pathPattern: `${tool.path.replace(/\\*+$/, name)}`,\n inputSchema: action.meta?.inputSchema,\n });\n }\n}\n\n/** Strategy 1: list basePath, pick first child, list its .actions/ */\nasync function discoverViaInstanceProbe(\n tool: ToolEntry,\n basePath: string,\n discoveredActions: Set<string>,\n schemas: ActionSchema[],\n deps: AgentRunDeps,\n): Promise<boolean> {\n const listResult = await deps.callAFS(\"list\", basePath);\n if (!listResult.success) return false;\n\n const entries = extractEntries(listResult.data);\n if (entries.length === 0) return false;\n\n // Check for MCP tools: entries with meta.kind === \"mcp:tool\" are directly executable\n // and carry their own inputSchema — no need to probe .actions/\n const mcpTools = entries.filter(\n (e) => e.meta?.kind === \"mcp:tool\" || e.meta?.kinds?.includes?.(\"mcp:tool\"),\n );\n if (mcpTools.length > 0) {\n let found = false;\n for (const mcpTool of mcpTools) {\n const name = mcpTool.meta?.mcp?.name || extractActionNameFromEntry(mcpTool);\n if (!name || discoveredActions.has(name)) continue;\n discoveredActions.add(name);\n found = true;\n\n const toolPath = mcpTool.path || `${basePath}/${name}`;\n schemas.push({\n actionName: name,\n description: mcpTool.meta?.description || `Execute ${name}`,\n pathPattern: toolPath,\n inputSchema: mcpTool.meta?.inputSchema,\n });\n }\n return found;\n }\n\n const firstChild = entries[0]!;\n const childPath = firstChild.path || firstChild.id;\n if (!childPath) return false;\n\n const actionsPath = `${childPath}/.actions`;\n const actionsResult = await deps.callAFS(\"list\", actionsPath);\n if (!actionsResult.success) return false;\n\n const actions = extractEntries(actionsResult.data);\n let found = false;\n for (const action of actions) {\n const name = extractActionNameFromEntry(action);\n if (!name || discoveredActions.has(name)) continue;\n discoveredActions.add(name);\n found = true;\n\n schemas.push({\n actionName: name,\n description: action.meta?.description || `Execute ${name}`,\n pathPattern: `${tool.path}/.actions/${name}`,\n inputSchema: action.meta?.inputSchema,\n });\n }\n return found;\n}\n\n/**\n * Strategy 2: walk up path hierarchy to find a provider's /.meta/.capabilities,\n * then extract action schemas from the manifest's catalog + inputSchema.\n *\n * For a tool path like /telegram/default/conversations/*, tries:\n * /telegram/default/conversations/.meta/.capabilities\n * /telegram/default/.meta/.capabilities\n * /telegram/.meta/.capabilities\n */\nasync function discoverViaCapabilities(\n tool: ToolEntry,\n basePath: string,\n discoveredActions: Set<string>,\n schemas: ActionSchema[],\n deps: AgentRunDeps,\n): Promise<boolean> {\n // Walk up path segments\n const segments = basePath.split(\"/\").filter(Boolean);\n\n for (let depth = segments.length; depth >= 1; depth--) {\n const ancestorPath = `/${segments.slice(0, depth).join(\"/\")}`;\n const capsPath = `${ancestorPath}/.meta/.capabilities`;\n\n try {\n const result = await deps.callAFS(\"read\", capsPath);\n if (!result.success) continue;\n\n const content = extractCapabilitiesContent(result.data);\n if (!content?.actions) continue;\n\n let found = false;\n for (const actionGroup of content.actions) {\n const catalog = actionGroup.catalog;\n if (!Array.isArray(catalog)) continue;\n\n for (const entry of catalog) {\n const name = entry.name;\n if (!name || discoveredActions.has(name)) continue;\n discoveredActions.add(name);\n found = true;\n\n schemas.push({\n actionName: name,\n description: entry.description || `Execute ${name}`,\n pathPattern: `${tool.path}/.actions/${name}`,\n inputSchema: entry.inputSchema,\n });\n }\n }\n if (found) return true;\n } catch {\n // Discovery is best-effort — try next ancestor\n }\n }\n return false;\n}\n\n/** Extract capabilities content from a read result (may be nested in data.content or data directly). */\nfunction extractCapabilitiesContent(\n data: unknown,\n): { actions?: Array<{ catalog?: Array<Record<string, any>> }> } | null {\n if (!data || typeof data !== \"object\") return null;\n const d = data as Record<string, any>;\n // Direct content\n if (d.actions) return d as any;\n // Nested in content field\n if (d.content && typeof d.content === \"object\" && (d.content as any).actions) {\n return d.content as any;\n }\n return null;\n}\n\n/** Extract entries array from callAFS response data (may be raw array or wrapped). */\nfunction extractEntries(data: unknown): Array<Record<string, any>> {\n if (Array.isArray(data)) return data;\n if (data && typeof data === \"object\" && Array.isArray((data as any).data)) {\n return (data as any).data;\n }\n return [];\n}\n\n/** Extract action name from an action entry (from path or id). */\nfunction extractActionNameFromEntry(entry: Record<string, any>): string | undefined {\n // Try meta.name first\n if (entry.meta?.name) return entry.meta.name;\n // Extract from path: /foo/.actions/send → send\n const path = entry.path || entry.id || \"\";\n const marker = \"/.actions/\";\n const idx = path.lastIndexOf(marker);\n if (idx !== -1) return path.slice(idx + marker.length).split(\"/\")[0];\n // Fallback: use id directly\n if (entry.id && !entry.id.includes(\"/\")) return entry.id;\n return undefined;\n}\n\n// ─── History Normalization ───────────────────────────────────────────────────\n\n/** Normalize an in-memory message (AigneHub camelCase) to canonical JSONL format (OpenAI snake_case). */\nfunction normalizeForHistory(msg: Record<string, unknown>): HistoryMessage | null {\n const role = msg.role as string;\n if (role === \"system\") return null; // system never saved\n\n if (role === \"user\") {\n return { role: \"user\", content: String(msg.content ?? \"\") };\n }\n\n if (role === \"assistant\") {\n const result: HistoryMessage = { role: \"assistant\", content: String(msg.content ?? \"\") };\n // Normalize toolCalls (camelCase from AigneHub) → tool_calls (snake_case canonical)\n const rawToolCalls = (msg.toolCalls ?? msg.tool_calls) as\n | Array<Record<string, unknown>>\n | undefined;\n if (rawToolCalls?.length) {\n (result as any).tool_calls = rawToolCalls.map((tc) => {\n const fn = tc.function as Record<string, unknown> | undefined;\n // Support both OpenAI format (function.arguments) and Vercel AI SDK format (args)\n const rawArgs = fn?.arguments ?? tc.args;\n return {\n id: (tc.id ?? tc.toolCallId ?? \"\") as string,\n type: \"function\" as const,\n function: {\n name: (fn?.name ?? tc.toolName ?? \"\") as string,\n arguments: typeof rawArgs === \"string\" ? rawArgs : JSON.stringify(rawArgs ?? {}),\n },\n };\n });\n }\n return result;\n }\n\n if (role === \"tool\") {\n return {\n role: \"tool\",\n tool_call_id: (msg.tool_call_id ?? msg.toolCallId ?? \"\") as string,\n content: String(msg.content ?? \"\"),\n };\n }\n\n return null;\n}\n\n// ─── Core Loop ──────────────────────────────────────────────────────────────\n\nexport async function runAgentLoop(\n params: AgentRunParams,\n deps: AgentRunDeps,\n): Promise<AgentRunResult> {\n const maxRounds = params.budget?.max_rounds ?? DEFAULT_MAX_ROUNDS;\n const actionsPerRound = params.budget?.actions_per_round ?? DEFAULT_ACTIONS_PER_ROUND;\n const tokenBudget = params.budget?.total_tokens ?? Number.POSITIVE_INFINITY;\n\n // ─── Startup: discover action schemas (best-effort) ─────────────────\n const actionSchemas = await discoverActionSchemas(params.tools, deps);\n\n // Index schemas by action name for path fixup\n const schemasByAction = new Map<string, ActionSchema>();\n for (const s of actionSchemas) {\n schemasByAction.set(s.actionName, s);\n }\n\n // Build tool schema from declarations + discovered action schemas\n const toolSchema = buildToolSchema(params.tools, actionSchemas);\n\n // ─── Startup: load history + assemble messages ──────────────────────\n let history: HistoryMessage[] = [];\n if (params.session && deps.loadHistory) {\n try {\n history = await deps.loadHistory(params.session);\n } catch {\n // loadHistory failure should not prevent agent-run from running\n }\n }\n\n const messages: Array<Record<string, unknown>> = [];\n // 1. system — stable prefix for prompt cache\n if (params.system) {\n messages.push({ role: \"system\", content: params.system });\n }\n // 2. history — incremental prefix, cacheable\n for (const msg of history) {\n messages.push({ ...msg });\n }\n // 3. current user message\n messages.push({ role: \"user\", content: params.task });\n\n // Save session helper — normalizes messages and writes JSONL\n const saveSession = async () => {\n if (!params.session || !deps.saveHistory) return;\n try {\n const toSave: HistoryMessage[] = [];\n for (const msg of messages) {\n const normalized = normalizeForHistory(msg);\n if (normalized) toSave.push(normalized);\n }\n await deps.saveHistory(params.session, toSave);\n } catch {\n // Save failure should not break agent-run\n }\n };\n\n const trace: TraceEntry[] = [];\n let totalTokens = 0;\n let totalActions = 0;\n\n for (let round = 1; round <= maxRounds; round++) {\n // Call LLM (omit tools/toolChoice when no tools are available)\n const llmArgs: Record<string, unknown> = { messages: [...messages] };\n if (toolSchema.length > 0) {\n llmArgs.tools = toolSchema;\n llmArgs.toolChoice = \"auto\";\n }\n const llmResult = await deps.callLLM(llmArgs);\n\n if (!llmResult.success) {\n const errMsg =\n (llmResult.data as any)?.error ?? (llmResult as any).error?.message ?? \"unknown error\";\n trace.push({ round, tool_calls: [], tokens: { input: 0, output: 0 } });\n await saveSession();\n return {\n status: \"error\",\n error: `LLM call failed: ${errMsg}`,\n rounds: round,\n total_actions: totalActions,\n total_tokens: totalTokens,\n trace,\n };\n }\n\n const data = llmResult.data as Record<string, unknown>;\n const inputTokens = (data.inputTokens as number) ?? 0;\n const outputTokens = (data.outputTokens as number) ?? 0;\n totalTokens += inputTokens + outputTokens;\n\n const text = data.text as string | undefined;\n const rawToolCalls = data.toolCalls as Array<Record<string, unknown>> | undefined;\n\n // No tool calls → LLM is done\n if (!rawToolCalls || rawToolCalls.length === 0) {\n trace.push({ round, tool_calls: [], tokens: { input: inputTokens, output: outputTokens } });\n // Add final assistant message before saving\n messages.push({ role: \"assistant\", content: text ?? \"\" });\n await saveSession();\n return {\n status: \"completed\",\n result: text ?? \"\",\n rounds: round,\n total_actions: totalActions,\n total_tokens: totalTokens,\n trace,\n };\n }\n\n // Check token budget AFTER getting response but BEFORE executing tools\n if (totalTokens > tokenBudget) {\n trace.push({ round, tool_calls: [], tokens: { input: inputTokens, output: outputTokens } });\n await saveSession();\n return {\n status: \"budget_exhausted\",\n result: text,\n rounds: round,\n total_actions: totalActions,\n total_tokens: totalTokens,\n trace,\n };\n }\n\n // Normalize tool calls from any format (OpenAI / Vercel AI SDK)\n const toolCalls = rawToolCalls.map(normalizeToolCall);\n\n // Add assistant message with tool calls (keep raw format for LLM round-trip)\n messages.push({\n role: \"assistant\",\n content: text ?? \"\",\n toolCalls: rawToolCalls,\n });\n\n // Truncate to actions_per_round — notify LLM about dropped calls\n const roundCalls = toolCalls.slice(0, actionsPerRound);\n const droppedCalls = toolCalls.slice(actionsPerRound);\n const traceEntries: TraceEntry[\"tool_calls\"] = [];\n\n // Validate all calls first\n const validatedCalls: Array<{\n call: ToolCallInput;\n op: string;\n valid: boolean;\n reason?: string;\n }> = [];\n for (const call of roundCalls) {\n const op = toolNameToOp(call.toolName);\n if (!op) {\n validatedCalls.push({\n call,\n op: \"unknown\",\n valid: false,\n reason: `Unknown tool: ${call.toolName}`,\n });\n continue;\n }\n\n // Fix paths for per-action tools: LLMs often put the tool name\n // (afs_action_send) in the path instead of the real action name (send).\n if (call.toolName.startsWith(\"afs_action_\")) {\n fixPerActionPath(call, schemasByAction);\n }\n\n const path = call.args.path as string;\n if (!path) {\n validatedCalls.push({ call, op, valid: false, reason: \"Missing path argument\" });\n continue;\n }\n const validation = validateToolCall(path, op, params.tools);\n if (!validation.allowed) {\n validatedCalls.push({ call, op, valid: false, reason: validation.reason });\n continue;\n }\n // Check required args per operation\n const missingArg = REQUIRED_ARGS[op]?.find((arg) => !(arg in call.args));\n if (missingArg) {\n validatedCalls.push({\n call,\n op,\n valid: false,\n reason: `Missing required argument '${missingArg}' for ${op}`,\n });\n continue;\n }\n validatedCalls.push({ call, op, valid: true });\n }\n\n // Split into ASH-routable and direct calls\n const ashCalls: ValidatedToolCall[] = [];\n const directCalls: Array<{ call: ToolCallInput; op: string }> = [];\n const errorResults: Array<{ id: string; error: string }> = [];\n\n for (const { call, op, valid, reason } of validatedCalls) {\n if (!valid) {\n errorResults.push({ id: call.toolCallId, error: reason ?? \"Validation failed\" });\n traceEntries.push({\n id: call.toolCallId,\n name: call.toolName,\n path: String(call.args.path ?? \"\"),\n status: \"error\",\n error: reason,\n });\n continue;\n }\n\n const path = call.args.path as string;\n if (ASH_OPS.has(op)) {\n ashCalls.push({\n id: call.toolCallId,\n op: op as \"read\" | \"list\" | \"exec\",\n path,\n args: extractExecArgs(call.args),\n });\n } else {\n directCalls.push({ call, op });\n }\n traceEntries.push({ id: call.toolCallId, name: call.toolName, path, status: \"ok\" });\n }\n\n // Execute ASH-routable calls\n const ashResults: Record<string, string> = {};\n if (ashCalls.length > 0) {\n const source = generateAsh(ashCalls, round);\n\n // Security: the generated ASH source already contains @caps(exec /path write /.results/*)\n // which enforces path-level access via the compiler's checkCap mechanism.\n // We don't pass a `caps` array here, so ctx.caps defaults to [\"*\"] (wildcard),\n // letting the script-level @caps annotation be the sole enforcer.\n // Previously, deriveCapsArray produced \"op path\" format strings that didn't match\n // the legacy ctx.caps prefix check, silently blocking all agent-run exec calls.\n const ashResult = await deps.runAsh(source, {\n returnWrittenData: true,\n skipWritePrefix: RESULTS_PREFIX,\n });\n\n if (ashResult.success && (ashResult.data as any)?.writtenData) {\n const writtenData = (ashResult.data as any).writtenData as Record<string, unknown[]>;\n for (const call of ashCalls) {\n const key = `${RESULTS_PREFIX}${call.id}`;\n const data = writtenData[key];\n ashResults[call.id] = data ? JSON.stringify(data) : \"No result\";\n }\n } else {\n // ASH execution failed — set error for all ASH calls\n for (const call of ashCalls) {\n ashResults[call.id] =\n `ASH execution error: ${(ashResult.data as any)?.error ?? \"unknown\"}`;\n }\n }\n }\n\n // Execute direct calls (all ops including exec)\n const directResults: Record<string, string> = {};\n for (const { call, op } of directCalls) {\n const path = call.args.path as string;\n const directArgs = { ...call.args };\n delete directArgs.path;\n\n try {\n const result = await deps.callAFS(op, path, directArgs);\n directResults[call.toolCallId] = result.success\n ? JSON.stringify(result.data)\n : `Error: ${(result.data as any)?.error ?? \"failed\"}`;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n directResults[call.toolCallId] = `Error: ${msg}`;\n }\n }\n\n // Append tool results to messages\n for (const call of roundCalls) {\n const errorEntry = errorResults.find((e) => e.id === call.toolCallId);\n if (errorEntry) {\n messages.push({\n role: \"tool\",\n tool_call_id: call.toolCallId,\n content: `Error: ${errorEntry.error}`,\n });\n } else if (ashResults[call.toolCallId] !== undefined) {\n messages.push({\n role: \"tool\",\n tool_call_id: call.toolCallId,\n content: ashResults[call.toolCallId],\n });\n } else if (directResults[call.toolCallId] !== undefined) {\n messages.push({\n role: \"tool\",\n tool_call_id: call.toolCallId,\n content: directResults[call.toolCallId],\n });\n } else {\n messages.push({\n role: \"tool\",\n tool_call_id: call.toolCallId,\n content: \"Error: No result returned for this tool call\",\n });\n }\n }\n\n // Notify LLM about dropped tool calls so it doesn't get confused\n for (const call of droppedCalls) {\n messages.push({\n role: \"tool\",\n tool_call_id: call.toolCallId,\n content: `Error: Tool call dropped — exceeded actions_per_round limit (${actionsPerRound}). Retry in next round.`,\n });\n }\n\n totalActions += roundCalls.length - errorResults.length;\n trace.push({\n round,\n tool_calls: traceEntries,\n tokens: { input: inputTokens, output: outputTokens },\n });\n }\n\n // Max rounds exhausted\n await saveSession();\n return {\n status: \"budget_exhausted\",\n rounds: maxRounds,\n total_actions: totalActions,\n total_tokens: totalTokens,\n trace,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ import { AFSAccessMode, AFSDeleteResult, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSRoot, AFSSearchResult, AFSStatResult, AFSWriteEntryPayload, AFSWriteResult, ProgramManifest, ProviderManifest, ProviderTreeSchema } from "@aigne/afs";
2
+ import { AFSBaseProvider, RouteContext } from "@aigne/afs/provider";
3
+
4
+ //#region src/index.d.ts
5
+ /**
6
+ * Derive tool declarations for agent-run from a ProgramManifest.
7
+ *
8
+ * Generates tools for:
9
+ * - `/program/**` — readonly (read, list, search, stat)
10
+ * - `/data/**` — readwrite (read, list, write, delete, search, stat)
11
+ * - `/{target}/**` — per mount ops from manifest
12
+ */
13
+ declare function deriveToolsFromProgram(manifest: ProgramManifest): Array<{
14
+ path: string;
15
+ ops: string[];
16
+ maxDepth?: number;
17
+ }>;
18
+ interface AFSAshOptions {
19
+ name?: string;
20
+ description?: string;
21
+ /** Directory for persistent .ash script files. When unset, scripts are in-memory only. */
22
+ scriptsDir?: string;
23
+ /** Directory for persistent ASH save outputs. When unset, save data is ephemeral. */
24
+ dataDir?: string;
25
+ /** Additional root actions allowed from ASH runtime (default allows only agent-run). */
26
+ allowRootActions?: Array<"agent-run" | "mount" | "unmount" | "read" | "list" | "write" | "delete">;
27
+ }
28
+ /**
29
+ * AFS ASH Provider
30
+ *
31
+ * Bridges ASH pipeline DSL to AFS. ASH scripts are stored in-memory and
32
+ * executed against AFS via a world bridge that translates ASH's
33
+ * read/write/publish to AFS read/write operations.
34
+ *
35
+ * Structure:
36
+ * - `/` - root directory
37
+ * - `/scripts` - stored .ash scripts
38
+ * - `/scripts/{name}.ash` - individual script files (executable)
39
+ * - `/.actions/run` - execute inline ASH code
40
+ * - `/.actions/validate` - validate ASH source (compile + type-check)
41
+ */
42
+ declare class AFSAsh extends AFSBaseProvider {
43
+ static manifest(): ProviderManifest;
44
+ static treeSchema(): ProviderTreeSchema;
45
+ static load({
46
+ config
47
+ }?: AFSModuleLoadParams): Promise<AFSAsh>;
48
+ readonly name: string;
49
+ readonly description?: string;
50
+ readonly accessMode: AFSAccessMode;
51
+ private readonly scripts;
52
+ private afsRoot?;
53
+ private readonly scriptsDir?;
54
+ private readonly dataDir?;
55
+ private readonly allowRootActions;
56
+ private readonly triggerSubs;
57
+ private readonly cronJobs;
58
+ private readonly externalScripts;
59
+ private externalScriptSubs;
60
+ private dirsReady;
61
+ constructor(options?: AFSAshOptions);
62
+ ready(): Promise<void>;
63
+ private ensureDirs;
64
+ private getScript;
65
+ private setScript;
66
+ private hasScript;
67
+ private removeScript;
68
+ private getAllScriptNames;
69
+ private getScriptCount;
70
+ /** Sanitize an ASH path to a flat filename: /data/clean → data%2Fclean.json */
71
+ private dataFileName;
72
+ /** Persist save output to dataDir */
73
+ private persistData;
74
+ /** Load all persisted data files into a dataStore */
75
+ private loadPersistedData;
76
+ onMount(afs: AFSRoot): void;
77
+ private registerExternalScript;
78
+ private unregisterExternalScript;
79
+ /** Stop all cron jobs and unsubscribe all event triggers. Call on provider teardown. */
80
+ destroy(): void;
81
+ private initTriggers;
82
+ /**
83
+ * Register EventBus subscriptions and cron schedules for all triggers in a script.
84
+ * Replaces any previous subscriptions/schedules for the same script name.
85
+ */
86
+ private registerTriggers;
87
+ /** Unsubscribe all event triggers and stop all cron jobs for a given script. */
88
+ private unregisterTriggers;
89
+ /**
90
+ * Execute a single triggered job reactively in response to an AFS event.
91
+ * Re-compiles the script, builds a bridged world context, executes the
92
+ * target job with event data as the initial stream, and writes results
93
+ * back to AFS.
94
+ */
95
+ private executeTriggerJob;
96
+ listRoot(_ctx: RouteContext): Promise<AFSListResult>;
97
+ listScripts(_ctx: RouteContext): Promise<AFSListResult>;
98
+ listScript(ctx: RouteContext<{
99
+ scriptName: string;
100
+ }>): Promise<AFSListResult>;
101
+ listRootActions(_ctx: RouteContext): Promise<AFSListResult>;
102
+ listScriptActions(ctx: RouteContext<{
103
+ scriptName: string;
104
+ }>): Promise<AFSListResult>;
105
+ readRoot(_ctx: RouteContext): Promise<AFSEntry>;
106
+ readScriptsDir(_ctx: RouteContext): Promise<AFSEntry>;
107
+ readScript(ctx: RouteContext<{
108
+ scriptName: string;
109
+ }>): Promise<AFSEntry>;
110
+ private static readonly COOKBOOK_FILES;
111
+ listCookbook(_ctx: RouteContext): Promise<AFSListResult>;
112
+ readCookbookDir(_ctx: RouteContext): Promise<AFSEntry>;
113
+ listCookbookFile(_ctx: RouteContext<{
114
+ file: string;
115
+ }>): Promise<AFSListResult>;
116
+ readCookbook(ctx: RouteContext<{
117
+ file: string;
118
+ }>): Promise<AFSEntry>;
119
+ readAgentMd(_ctx: RouteContext): Promise<AFSEntry>;
120
+ readAshReference(_ctx: RouteContext): Promise<AFSEntry>;
121
+ readCapabilities(_ctx: RouteContext): Promise<AFSEntry>;
122
+ readRootMeta(_ctx: RouteContext): Promise<AFSEntry>;
123
+ readCookbookMeta(_ctx: RouteContext): Promise<AFSEntry>;
124
+ readCookbookFileMeta(ctx: RouteContext<{
125
+ file: string;
126
+ }>): Promise<AFSEntry>;
127
+ readScriptsMeta(_ctx: RouteContext): Promise<AFSEntry>;
128
+ readScriptMeta(ctx: RouteContext<{
129
+ scriptName: string;
130
+ }>): Promise<AFSEntry>;
131
+ writeScript(ctx: RouteContext<{
132
+ scriptName: string;
133
+ }>, entry: AFSWriteEntryPayload): Promise<AFSWriteResult>;
134
+ deleteScript(ctx: RouteContext<{
135
+ scriptName: string;
136
+ }>): Promise<AFSDeleteResult>;
137
+ deleteCatchAll(ctx: RouteContext<{
138
+ path: string;
139
+ }>): Promise<AFSDeleteResult>;
140
+ execScript(ctx: RouteContext<{
141
+ scriptName: string;
142
+ }>, args: Record<string, unknown>): Promise<AFSExecResult>;
143
+ execScriptDirect(ctx: RouteContext<{
144
+ scriptName: string;
145
+ }>, args: Record<string, unknown>): Promise<AFSExecResult>;
146
+ execRootAction(ctx: RouteContext<{
147
+ action: string;
148
+ }>, args: Record<string, unknown>): Promise<AFSExecResult>;
149
+ statRoot(_ctx: RouteContext): Promise<AFSStatResult>;
150
+ statScriptsDir(_ctx: RouteContext): Promise<AFSStatResult>;
151
+ statScript(ctx: RouteContext<{
152
+ scriptName: string;
153
+ }>): Promise<AFSStatResult>;
154
+ explainRoot(_ctx: RouteContext): Promise<AFSExplainResult>;
155
+ explainScript(ctx: RouteContext<{
156
+ scriptName: string;
157
+ }>): Promise<AFSExplainResult>;
158
+ searchScripts(_ctx: RouteContext, query: string): Promise<AFSSearchResult>;
159
+ private buildScriptEntry;
160
+ private buildScriptExecInputSchema;
161
+ /**
162
+ * Create an async-capable world that bridges ASH to AFS.
163
+ * Since ASH's WorldInterface is synchronous but AFS is async,
164
+ * we collect operations and replay them, or use a pre-loaded data approach.
165
+ */
166
+ private createAsyncWorld;
167
+ private deriveTools;
168
+ private executeAgentRun;
169
+ /**
170
+ * Execute a single named job from an ASH source.
171
+ * Used by ProgramManager to run trigger jobs with event data.
172
+ */
173
+ private runJob;
174
+ private runAsh;
175
+ private applyParamOverridesToSource;
176
+ }
177
+ //#endregion
178
+ export { AFSAsh, AFSAsh as default, AFSAshOptions, deriveToolsFromProgram };
179
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":"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"}