@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.
- package/LICENSE.md +26 -0
- package/dist/agent-run-CXJQ0jPV.mjs +873 -0
- package/dist/agent-run-CXJQ0jPV.mjs.map +1 -0
- package/dist/index.d.mts +179 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1715 -0
- package/dist/index.mjs.map +1 -0
- package/docs/agent.md +322 -0
- package/docs/cookbook/patterns.md +250 -0
- package/docs/cookbook/quickref.md +111 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["parseYAML","stored","runtimeAFS","result"],"sources":["../src/index.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n type AFSAccessMode,\n type AFSDeleteResult,\n type AFSEntry,\n type AFSEvent,\n type AFSEventFilter,\n type AFSExecResult,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSRoot,\n type AFSSearchResult,\n type AFSStatResult,\n type AFSUnsubscribe,\n type AFSWriteEntryPayload,\n type AFSWriteResult,\n type CapabilitiesManifest,\n createProgramAFS,\n type JSONSchema7,\n type ProgramManifest,\n type ProviderManifest,\n type ProviderTreeSchema,\n parseProgramManifest,\n} from \"@aigne/afs\";\nimport {\n Actions,\n AFSBaseProvider,\n Delete,\n Exec,\n Explain,\n List,\n Meta,\n Read,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs/provider\";\nimport {\n ASH_REFERENCE,\n compileSource,\n type JobContext,\n type JobLogger,\n type JobResult,\n type WorldInterface,\n} from \"@aigne/ash\";\nimport { Cron, CronPattern } from \"croner\";\nimport { joinURL } from \"ufo\";\nimport { parse as parseYAML } from \"yaml\";\nimport { z } from \"zod\";\n\nconst DOCS_DIR = join(dirname(fileURLToPath(import.meta.url)), \"..\", \"docs\");\n\nfunction readDoc(relativePath: string): string {\n return readFileSync(join(DOCS_DIR, relativePath), \"utf-8\");\n}\n\n/**\n * Derive tool declarations for agent-run from a ProgramManifest.\n *\n * Generates tools for:\n * - `/program/**` — readonly (read, list, search, stat)\n * - `/data/**` — readwrite (read, list, write, delete, search, stat)\n * - `/{target}/**` — per mount ops from manifest\n */\nexport function deriveToolsFromProgram(\n manifest: ProgramManifest,\n): Array<{ path: string; ops: string[]; maxDepth?: number }> {\n const tools: Array<{ path: string; ops: string[]; maxDepth?: number }> = [\n {\n path: \"/program/**\",\n ops: [\"read\", \"list\", \"search\", \"stat\"],\n maxDepth: 10,\n },\n {\n path: \"/data/**\",\n ops: [\"read\", \"list\", \"write\", \"delete\", \"search\", \"stat\"],\n maxDepth: 10,\n },\n ];\n\n for (const mount of manifest.mounts) {\n const ops = mount.ops ?? [\"read\", \"list\"];\n if (ops.length === 0) continue;\n tools.push({\n path: `${mount.target}/**`,\n ops: [...ops],\n maxDepth: 5,\n });\n }\n\n return tools;\n}\n\nexport interface AFSAshOptions {\n name?: string;\n description?: string;\n /** Directory for persistent .ash script files. When unset, scripts are in-memory only. */\n scriptsDir?: string;\n /** Directory for persistent ASH save outputs. When unset, save data is ephemeral. */\n dataDir?: string;\n /** Additional root actions allowed from ASH runtime (default allows only agent-run). */\n allowRootActions?: Array<\n \"agent-run\" | \"mount\" | \"unmount\" | \"read\" | \"list\" | \"write\" | \"delete\"\n >;\n}\n\ninterface StoredScript {\n source: string;\n updatedAt: Date;\n createdAt: Date;\n}\n\nfunction sanitizeErrorPath(msg: string): string {\n return msg.replace(/'\\/[^']*'/g, \"'[path]'\").replace(/\"\\/[^\"]*\"/g, '\"[path]\"');\n}\n\nfunction normalizeContent(content: unknown): Record<string, unknown> {\n if (content == null) return {};\n if (typeof content === \"object\" && !Array.isArray(content))\n return { content, ...(content as Record<string, unknown>) };\n if (typeof content === \"string\") {\n try {\n const parsed = parseYAML(content);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed))\n return { content, ...(parsed as Record<string, unknown>) };\n } catch {\n // Not valid YAML — fall through\n }\n }\n return { content };\n}\n\n/**\n * AFS ASH Provider\n *\n * Bridges ASH pipeline DSL to AFS. ASH scripts are stored in-memory and\n * executed against AFS via a world bridge that translates ASH's\n * read/write/publish to AFS read/write operations.\n *\n * Structure:\n * - `/` - root directory\n * - `/scripts` - stored .ash scripts\n * - `/scripts/{name}.ash` - individual script files (executable)\n * - `/.actions/run` - execute inline ASH code\n * - `/.actions/validate` - validate ASH source (compile + type-check)\n */\nexport class AFSAsh extends AFSBaseProvider {\n static manifest(): ProviderManifest {\n return {\n name: \"ash\",\n description:\n \"ASH pipeline DSL for deterministic data pipelines.\\n- Store, validate, and execute ASH scripts\\n- Commands: find, where, map, save, publish, tee, fanout, output, input, count, group-by, action, route, lookup\\n- Read /.meta/.ash-reference for full syntax\",\n uriTemplate: \"ash://\",\n category: \"compute\",\n schema: z.object({\n name: z.string().optional(),\n description: z.string().optional(),\n allowRootActions: z\n .array(z.enum([\"agent-run\", \"mount\", \"unmount\", \"read\", \"list\", \"write\", \"delete\"]))\n .optional(),\n }),\n tags: [\"ash\", \"pipeline\", \"etl\", \"dsl\"],\n capabilityTags: [\"read-write\", \"search\", \"auth:none\", \"local\"],\n security: {\n riskLevel: \"system\",\n resourceAccess: [\"process-spawn\"],\n dataSensitivity: [\"code\"],\n notes: [\"Executes ASH pipeline scripts that can read/write data across mounted providers\"],\n },\n capabilities: {\n crossProvider: { afsAccess: true },\n },\n };\n }\n\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"write\", \"delete\", \"exec\", \"search\", \"stat\", \"explain\"],\n tree: {\n \"/\": {\n kind: \"ash:root\",\n operations: [\"list\", \"read\", \"exec\"],\n actions: [\"run\", \"validate\"],\n },\n \"/scripts\": { kind: \"ash:directory\", operations: [\"list\", \"read\"] },\n \"/scripts/{name}.ash\": {\n kind: \"ash:script\",\n operations: [\"read\", \"write\", \"delete\", \"exec\"],\n actions: [\"exec\"],\n },\n },\n auth: { type: \"none\" },\n bestFor: [\"data pipelines\", \"ETL scripts\", \"deterministic DSL\"],\n notFor: [\"general-purpose code\"],\n };\n }\n\n static async load({ config }: AFSModuleLoadParams = {}) {\n return new AFSAsh(config as AFSAshOptions);\n }\n\n override readonly name: string;\n override readonly description?: string;\n override readonly accessMode: AFSAccessMode = \"readwrite\";\n\n private readonly scripts: Map<string, StoredScript> = new Map();\n private afsRoot?: AFSRoot;\n private readonly scriptsDir?: string;\n private readonly dataDir?: string;\n private readonly allowRootActions: Set<string>;\n private readonly triggerSubs = new Map<string, AFSUnsubscribe[]>();\n private readonly cronJobs = new Map<string, Cron[]>();\n private readonly externalScripts = new Map<string, string>();\n private externalScriptSubs: AFSUnsubscribe[] = [];\n\n private dirsReady = false;\n\n constructor(options: AFSAshOptions = {}) {\n super();\n this.name = options.name ?? \"ash\";\n this.description = options.description ?? \"ASH pipeline DSL for deterministic data pipelines\";\n this.scriptsDir = options.scriptsDir;\n this.dataDir = options.dataDir;\n const rawAllow = (options as AFSAshOptions & { allowRootActions?: unknown }).allowRootActions;\n const allowList = Array.isArray(rawAllow)\n ? rawAllow\n : typeof rawAllow === \"string\"\n ? [rawAllow]\n : [\"agent-run\"];\n const validActions = new Set([\n \"agent-run\",\n \"mount\",\n \"unmount\",\n \"read\",\n \"list\",\n \"write\",\n \"delete\",\n ]);\n const normalized = allowList.filter(\n (a): a is \"agent-run\" | \"mount\" | \"unmount\" | \"read\" | \"list\" | \"write\" | \"delete\" =>\n validActions.has(a),\n );\n this.allowRootActions = new Set(normalized.length > 0 ? normalized : [\"agent-run\"]);\n }\n\n async ready(): Promise<void> {\n if (this.dirsReady) return;\n if (this.scriptsDir) await mkdir(this.scriptsDir, { recursive: true });\n if (this.dataDir) await mkdir(this.dataDir, { recursive: true });\n this.dirsReady = true;\n }\n\n private async ensureDirs(): Promise<void> {\n if (!this.dirsReady) await this.ready();\n }\n\n // ========== Script Storage Abstraction ==========\n\n private async getScript(name: string): Promise<StoredScript | undefined> {\n if (this.scriptsDir) {\n const filePath = join(this.scriptsDir, `${name}.ash`);\n try {\n const source = await readFile(filePath, \"utf-8\");\n return { source, createdAt: new Date(), updatedAt: new Date() };\n } catch {\n return undefined;\n }\n }\n return this.scripts.get(name);\n }\n\n private async setScript(name: string, script: StoredScript): Promise<void> {\n if (this.scriptsDir) {\n await this.ensureDirs();\n await writeFile(join(this.scriptsDir, `${name}.ash`), script.source, \"utf-8\");\n }\n this.scripts.set(name, script);\n }\n\n private async hasScript(name: string): Promise<boolean> {\n if (this.scriptsDir) {\n try {\n await stat(join(this.scriptsDir, `${name}.ash`));\n return true;\n } catch {\n return false;\n }\n }\n return this.scripts.has(name);\n }\n\n private async removeScript(name: string): Promise<void> {\n if (this.scriptsDir) {\n try {\n await rm(join(this.scriptsDir, `${name}.ash`));\n } catch {\n // File doesn't exist — no-op\n }\n }\n this.scripts.delete(name);\n }\n\n private async getAllScriptNames(): Promise<string[]> {\n if (this.scriptsDir) {\n try {\n const files = await readdir(this.scriptsDir);\n return files.filter((f) => f.endsWith(\".ash\")).map((f) => f.replace(/\\.ash$/, \"\"));\n } catch {\n return [];\n }\n }\n return Array.from(this.scripts.keys());\n }\n\n private async getScriptCount(): Promise<number> {\n return (await this.getAllScriptNames()).length;\n }\n\n // ========== Data Persistence (dataDir) ==========\n\n /** Sanitize an ASH path to a flat filename: /data/clean → data%2Fclean.json */\n private dataFileName(path: string): string {\n return `${path.replace(/^\\/+/, \"\").replace(/\\//g, \"%2F\")}.json`;\n }\n\n /** Persist save output to dataDir */\n private async persistData(path: string, data: unknown[]): Promise<void> {\n if (!this.dataDir) return;\n await this.ensureDirs();\n await writeFile(join(this.dataDir, this.dataFileName(path)), JSON.stringify(data), \"utf-8\");\n }\n\n /** Load all persisted data files into a dataStore */\n private async loadPersistedData(): Promise<Record<string, unknown[]>> {\n const store: Record<string, unknown[]> = {};\n if (!this.dataDir) return store;\n try {\n const files = await readdir(this.dataDir);\n for (const file of files) {\n if (!file.endsWith(\".json\")) continue;\n const key = `/${file.replace(/\\.json$/, \"\").replace(/%2F/gi, \"/\")}`;\n try {\n store[key] = JSON.parse(await readFile(join(this.dataDir, file), \"utf-8\"));\n } catch {\n // Corrupted file — skip\n }\n }\n } catch {\n // Directory not readable — return empty\n }\n return store;\n }\n\n onMount(afs: AFSRoot): void {\n // Clean up any existing triggers/crons from a previous mount\n this.destroy();\n this.afsRoot = afs;\n\n // Register event triggers for all existing scripts (async, fire-and-forget)\n this.initTriggers().catch(() => {});\n\n // Subscribe to external script registration events\n if (afs.subscribe) {\n const unsubReg = afs.subscribe({ type: \"script:registered\" }, (evt: AFSEvent) => {\n if (evt.data?.runtime !== \"ash\") return;\n this.registerExternalScript(evt.path).catch(() => {});\n });\n const unsubUnreg = afs.subscribe({ type: \"script:unregistered\" }, (evt: AFSEvent) => {\n if (evt.data?.runtime !== \"ash\") return;\n this.unregisterExternalScript(evt.path);\n });\n this.externalScriptSubs = [unsubReg, unsubUnreg];\n }\n }\n\n private async registerExternalScript(path: string): Promise<void> {\n const afs = this.afsRoot;\n if (!afs?.read) return;\n try {\n const file = await afs.read(path, {});\n const source = String(file.data?.content ?? \"\");\n if (!source.trim()) return;\n this.externalScripts.set(path, source);\n this.registerTriggers(path, source);\n } catch {\n // Read failed — skip silently\n }\n }\n\n private unregisterExternalScript(path: string): void {\n this.externalScripts.delete(path);\n this.unregisterTriggers(path);\n }\n\n /** Stop all cron jobs and unsubscribe all event triggers. Call on provider teardown. */\n destroy(): void {\n const allNames = new Set([...this.triggerSubs.keys(), ...this.cronJobs.keys()]);\n for (const name of allNames) {\n this.unregisterTriggers(name);\n }\n // Clean up external script event subscriptions\n for (const unsub of this.externalScriptSubs) unsub();\n this.externalScriptSubs = [];\n this.externalScripts.clear();\n }\n\n private async initTriggers(): Promise<void> {\n await this.ensureDirs();\n for (const name of await this.getAllScriptNames()) {\n const script = await this.getScript(name);\n if (script) this.registerTriggers(name, script.source);\n }\n }\n\n // ========== Event & Cron Trigger Wiring ==========\n\n /**\n * Register EventBus subscriptions and cron schedules for all triggers in a script.\n * Replaces any previous subscriptions/schedules for the same script name.\n */\n private registerTriggers(scriptName: string, source: string): void {\n this.unregisterTriggers(scriptName);\n\n const result = compileSource(source);\n if (!result.program) return;\n\n const afs = this.afsRoot;\n const unsubs: AFSUnsubscribe[] = [];\n const crons: Cron[] = [];\n\n for (const unit of result.program.units) {\n if (unit.kind !== \"job\" || !unit.trigger) continue;\n const jobName = unit.name;\n const trigger = unit.trigger;\n\n if (trigger.kind === \"event\") {\n if (!afs?.subscribe) continue;\n const filter: AFSEventFilter = { path: trigger.path };\n const unsub = afs.subscribe(filter, (evt: AFSEvent) => {\n this.executeTriggerJob(scriptName, jobName, evt);\n });\n unsubs.push(unsub);\n } else if (trigger.kind === \"cron\") {\n try {\n // Validate cron expression before scheduling\n new CronPattern(trigger.expression);\n const cron = new Cron(trigger.expression, { protect: true }, () => {\n const syntheticEvent: AFSEvent = {\n type: \"cron\",\n path: `/cron/${scriptName}/${jobName}`,\n source: \"ash-cron\",\n timestamp: Date.now(),\n };\n this.executeTriggerJob(scriptName, jobName, syntheticEvent);\n });\n crons.push(cron);\n } catch (err) {\n console.error(\n `[ASH cron] Invalid cron expression \"${trigger.expression}\" in ${scriptName}/${jobName}:`,\n err,\n );\n }\n }\n }\n if (unsubs.length > 0) this.triggerSubs.set(scriptName, unsubs);\n if (crons.length > 0) this.cronJobs.set(scriptName, crons);\n }\n\n /** Unsubscribe all event triggers and stop all cron jobs for a given script. */\n private unregisterTriggers(scriptName: string): void {\n const unsubs = this.triggerSubs.get(scriptName);\n if (unsubs) {\n for (const unsub of unsubs) unsub();\n this.triggerSubs.delete(scriptName);\n }\n const crons = this.cronJobs.get(scriptName);\n if (crons) {\n for (const cron of crons) cron.stop();\n this.cronJobs.delete(scriptName);\n }\n }\n\n /**\n * Execute a single triggered job reactively in response to an AFS event.\n * Re-compiles the script, builds a bridged world context, executes the\n * target job with event data as the initial stream, and writes results\n * back to AFS.\n */\n private async executeTriggerJob(\n scriptName: string,\n jobName: string,\n event: AFSEvent,\n ): Promise<void> {\n try {\n // Try internal scripts first, then external scripts, then afsRoot.read fallback\n let source: string | undefined;\n const script = await this.getScript(scriptName);\n if (script) {\n source = script.source;\n } else if (this.externalScripts.has(scriptName)) {\n source = this.externalScripts.get(scriptName);\n } else if (this.afsRoot?.read) {\n try {\n const file = await this.afsRoot.read(scriptName, {});\n source = String(file.data?.content ?? \"\");\n } catch {\n // Read failed — skip\n }\n }\n if (!source) return;\n\n const result = compileSource(source);\n if (!result.program) return;\n\n const job = result.program.units.find((u) => u.kind === \"job\" && u.name === jobName);\n if (!job || job.kind !== \"job\") return;\n\n // Build world + bridged world (reuse same pattern as runAsh)\n const { world, written } = await this.createAsyncWorld();\n const bridgedWorld: WorldInterface = this.afsRoot\n ? {\n read: async (path: string): Promise<unknown[]> => {\n const local = await world.read(path);\n if (local.length > 0) return local;\n if (this.afsRoot?.list) {\n const listResult = await this.afsRoot.list(path, {});\n if (listResult.data.length > 0) {\n const needsEnrich = listResult.data.some((e) => e.content == null);\n let entries = listResult.data;\n if (needsEnrich && this.afsRoot.read) {\n const afsRead = this.afsRoot.read.bind(this.afsRoot);\n entries = await Promise.all(\n listResult.data.map(async (e) => {\n if (e.content != null) return e;\n try {\n const r = await afsRead(e.path, {});\n return r.data ? { ...e, content: r.data.content } : e;\n } catch {\n return e;\n }\n }),\n );\n }\n return entries.map((entry) => ({\n path: entry.path,\n name: entry.path.split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n }));\n }\n }\n if (this.afsRoot?.read) {\n try {\n const readResult = await this.afsRoot.read(path, {});\n if (readResult.data) {\n const entry = readResult.data;\n return [\n {\n path: entry.path ?? path,\n name: (entry.path ?? path).split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n },\n ];\n }\n } catch {\n // Path not found\n }\n }\n return [];\n },\n write: (path: string, data: unknown[]): void => {\n world.write(path, data);\n },\n publish: (topic: string, data: unknown[]): void => {\n world.publish(topic, data);\n },\n exec: world.exec,\n }\n : world;\n\n const ctx: JobContext = {\n world: bridgedWorld,\n caps: new Set<string>([\"*\"]),\n logger: { log() {} },\n output: { output() {} },\n };\n\n // Seed the initial stream with the full event record.\n // Templates can access ${type}, ${path}, ${source}, ${timestamp}, ${data.messageId}, etc.\n const initialStream: unknown[] = [{ ...event }];\n const jobResult = await job.execute(ctx, initialStream);\n\n if (jobResult.status !== \"ok\") {\n console.error(\n `[ASH trigger] ${scriptName}/${jobName} status=${jobResult.status}`,\n jobResult.errors,\n );\n }\n\n // Write results back to AFS\n const afs = this.afsRoot;\n if (afs?.write) {\n for (const [path, data] of Object.entries(written)) {\n const content = JSON.stringify(data);\n await afs.write(path, { content });\n }\n }\n } catch (err) {\n console.error(`[ASH trigger] ${scriptName}/${jobName} threw:`, err);\n }\n }\n\n // ========== List Handlers ==========\n\n @List(\"/\")\n async listRoot(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: [\n {\n id: \"/scripts\",\n path: \"/scripts\",\n summary: \"Stored ASH scripts\",\n meta: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: await this.getScriptCount(),\n },\n },\n {\n id: \"/cookbook\",\n path: \"/cookbook\",\n summary: \"ASH best practices and quick reference\",\n meta: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: 2,\n },\n },\n ],\n };\n }\n\n @List(\"/scripts\")\n async listScripts(_ctx: RouteContext): Promise<AFSListResult> {\n const entries: AFSEntry[] = [];\n for (const name of await this.getAllScriptNames()) {\n const script = await this.getScript(name);\n if (!script) continue;\n entries.push(this.buildScriptEntry(name, script));\n }\n return { data: entries };\n }\n\n @List(\"/scripts/:scriptName\")\n async listScript(ctx: RouteContext<{ scriptName: string }>): Promise<AFSListResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n if (!(await this.hasScript(name))) {\n throw new AFSNotFoundError(ctx.path);\n }\n // Leaf node — no children\n return { data: [] };\n }\n\n // ========== Actions Listing ==========\n\n @Actions(\"/\")\n async listRootActions(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: [\n {\n id: \"run\",\n path: \"/.actions/run\",\n summary: \"Execute inline ASH code\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n name: \"run\",\n description: \"Execute inline ASH pipeline code\",\n inputSchema: {\n type: \"object\",\n properties: {\n source: {\n type: \"string\",\n description: \"ASH pipeline source code. Read /.meta/.ash-reference for syntax.\",\n },\n caps: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Capability paths. Required for write-back to AFS (default: no write-back without caps)\",\n },\n },\n required: [\"source\"],\n },\n },\n },\n {\n id: \"validate\",\n path: \"/.actions/validate\",\n summary: \"Validate ASH source code\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n name: \"validate\",\n description: \"Compile and type-check ASH source, return diagnostics\",\n inputSchema: {\n type: \"object\",\n properties: {\n source: {\n type: \"string\",\n description:\n \"ASH pipeline source code to validate. Read /.meta/.ash-reference for syntax.\",\n },\n },\n required: [\"source\"],\n },\n },\n },\n {\n id: \"agent-run\",\n path: \"/.actions/agent-run\",\n summary: \"Run a single-task agentic loop\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n name: \"agent-run\",\n description:\n \"Execute a multi-round agentic loop: LLM inference → tool_call validation → ASH execution → result feedback. Stops when the LLM returns text or budget exhausts.\",\n inputSchema: {\n type: \"object\",\n properties: {\n task: { type: \"string\", description: \"The task for the agent to accomplish\" },\n model: {\n type: \"string\",\n description: \"AigneHub model path, e.g. /modules/aignehub/defaults/chat\",\n },\n tools: {\n oneOf: [\n {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description:\n \"AFS path pattern. Use * for single-level glob, ** for multi-level glob\",\n },\n ops: {\n type: \"array\",\n items: {\n type: \"string\",\n enum: [\"read\", \"list\", \"exec\", \"search\", \"write\", \"stat\", \"explain\"],\n },\n },\n exclude_actions: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Action names to exclude from exec\",\n },\n maxDepth: {\n type: \"number\",\n description:\n \"Max directory depth for ** glob (default: 0, i.e. ** with no maxDepth matches nothing)\",\n },\n },\n required: [\"path\", \"ops\"],\n },\n },\n {\n type: \"string\",\n enum: [\"none\"],\n description: \"Use 'none' for no tools (LLM-only)\",\n },\n ],\n description: \"AFS capabilities the agent may use, or 'none' for LLM-only mode\",\n },\n budget: {\n type: \"object\",\n properties: {\n max_rounds: { type: \"number\", description: \"Max LLM rounds (default 20)\" },\n actions_per_round: {\n type: \"number\",\n description: \"Max tool calls per round (default 10)\",\n },\n total_tokens: { type: \"number\", description: \"Token budget across all rounds\" },\n },\n },\n system: { type: \"string\", description: \"System prompt for the LLM\" },\n },\n required: [\"task\", \"model\"],\n },\n },\n },\n ],\n };\n }\n\n @Actions(\"/scripts/:scriptName\")\n async listScriptActions(ctx: RouteContext<{ scriptName: string }>): Promise<AFSListResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n throw new AFSNotFoundError(ctx.path);\n }\n const inputSchema = this.buildScriptExecInputSchema(script.source);\n const basePath = joinURL(\"/scripts\", ctx.params.scriptName, \".actions\");\n return {\n data: [\n {\n id: \"exec\",\n path: joinURL(basePath, \"exec\"),\n summary: `Execute script ${name}`,\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n name: \"exec\",\n description: `Execute the ${name} ASH script`,\n inputSchema,\n },\n },\n ],\n };\n }\n\n // ========== Read Handlers ==========\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/\",\n path: \"/\",\n meta: { type: \"directory\", childrenCount: 2 },\n actions: [\n { name: \"run\", description: \"Execute inline ASH code\" },\n { name: \"validate\", description: \"Validate ASH source code\" },\n ],\n };\n }\n\n @Read(\"/scripts\")\n async readScriptsDir(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/scripts\",\n path: \"/scripts\",\n summary: \"Stored ASH scripts\",\n meta: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: await this.getScriptCount(),\n },\n };\n }\n\n @Read(\"/scripts/:scriptName\")\n async readScript(ctx: RouteContext<{ scriptName: string }>): Promise<AFSEntry> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n throw new AFSNotFoundError(ctx.path, `Script not found: ${name}`);\n }\n return this.buildScriptEntry(name, script);\n }\n\n // ========== Cookbook Handlers ==========\n\n private static readonly COOKBOOK_FILES = [\"patterns.md\", \"quickref.md\"] as const;\n\n @List(\"/cookbook\")\n async listCookbook(_ctx: RouteContext): Promise<AFSListResult> {\n return {\n data: AFSAsh.COOKBOOK_FILES.map((file) => ({\n id: joinURL(\"/cookbook\", file),\n path: joinURL(\"/cookbook\", file),\n summary:\n file === \"patterns.md\" ? \"agent-run patterns and pitfalls\" : \"Quick reference card\",\n meta: { kind: \"ash:documentation\" },\n })),\n };\n }\n\n @Read(\"/cookbook\")\n async readCookbookDir(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/cookbook\",\n path: \"/cookbook\",\n meta: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: AFSAsh.COOKBOOK_FILES.length,\n },\n };\n }\n\n @List(\"/cookbook/:file\")\n async listCookbookFile(_ctx: RouteContext<{ file: string }>): Promise<AFSListResult> {\n return { data: [] };\n }\n\n @Read(\"/cookbook/:file\")\n async readCookbook(ctx: RouteContext<{ file: string }>): Promise<AFSEntry> {\n const file = ctx.params.file;\n if (!AFSAsh.COOKBOOK_FILES.includes(file as (typeof AFSAsh.COOKBOOK_FILES)[number]))\n throw new AFSNotFoundError(ctx.path);\n return {\n id: joinURL(\"/cookbook\", file),\n path: joinURL(\"/cookbook\", file),\n content: readDoc(joinURL(\"cookbook\", file)),\n meta: { kind: \"ash:documentation\" },\n };\n }\n\n // ========== Meta Read Handlers ==========\n\n @Read(\"/.meta/agent.md\")\n async readAgentMd(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/.meta/agent.md\",\n path: \"/.meta/agent.md\",\n content: readDoc(\"agent.md\"),\n meta: { kind: \"ash:documentation\", description: \"ASH agent usage guide\" },\n };\n }\n\n @Read(\"/.meta/.ash-reference\")\n async readAshReference(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/.meta/.ash-reference\",\n path: \"/.meta/.ash-reference\",\n content: ASH_REFERENCE,\n meta: {\n kind: \"ash:reference\",\n description: \"ASH language reference for writing valid ASH pipelines\",\n },\n };\n }\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry> {\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: `${this.description}. Read /.meta/.ash-reference for ASH syntax.`,\n tools: [],\n operations: this.getOperationsDeclaration(),\n actions: [\n {\n description: \"Root-level ASH actions\",\n catalog: [\n { name: \"run\", description: \"Execute inline ASH code\" },\n { name: \"validate\", description: \"Validate ASH source code\" },\n ],\n discovery: { pathTemplate: \"/.actions\" },\n },\n {\n kind: \"ash:script\",\n description: \"Script-level actions\",\n catalog: [{ name: \"exec\", description: \"Execute the script\" }],\n discovery: { pathTemplate: \"/scripts/:scriptName/.actions\" },\n },\n ],\n };\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: {\n kind: \"afs:capabilities\",\n description: \"ASH provider capabilities manifest\",\n operations: [\"list\", \"read\", \"write\", \"delete\", \"exec\", \"stat\", \"explain\", \"search\"],\n },\n };\n }\n\n // ========== Meta Handlers ==========\n\n @Meta(\"/\")\n async readRootMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/.meta\",\n path: \"/.meta\",\n content: { type: \"directory\", childrenCount: 2 },\n meta: { type: \"directory\", childrenCount: 2 },\n };\n }\n\n @Meta(\"/cookbook\")\n async readCookbookMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/cookbook/.meta\",\n path: \"/cookbook/.meta\",\n content: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: AFSAsh.COOKBOOK_FILES.length,\n },\n meta: {\n kind: \"ash:directory\",\n type: \"directory\",\n childrenCount: AFSAsh.COOKBOOK_FILES.length,\n },\n };\n }\n\n @Meta(\"/cookbook/:file\")\n async readCookbookFileMeta(ctx: RouteContext<{ file: string }>): Promise<AFSEntry> {\n return {\n id: joinURL(\"/cookbook\", ctx.params.file, \".meta\"),\n path: joinURL(\"/cookbook\", ctx.params.file, \".meta\"),\n content: { kind: \"ash:documentation\" },\n meta: { kind: \"ash:documentation\" },\n };\n }\n\n @Meta(\"/scripts\")\n async readScriptsMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \"/scripts/.meta\",\n path: \"/scripts/.meta\",\n content: { type: \"directory\", childrenCount: await this.getScriptCount() },\n meta: { type: \"directory\", childrenCount: await this.getScriptCount() },\n };\n }\n\n @Meta(\"/scripts/:scriptName\")\n async readScriptMeta(ctx: RouteContext<{ scriptName: string }>): Promise<AFSEntry> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n throw new AFSNotFoundError(ctx.path, `Script not found: ${name}`);\n }\n const entry = this.buildScriptEntry(name, script);\n return {\n id: joinURL(\"/scripts\", ctx.params.scriptName, \".meta\"),\n path: joinURL(\"/scripts\", ctx.params.scriptName, \".meta\"),\n content: entry.meta ?? {},\n meta: entry.meta ?? {},\n };\n }\n\n // ========== Write Handlers ==========\n\n @Write(\"/scripts/:scriptName\")\n async writeScript(\n ctx: RouteContext<{ scriptName: string }>,\n entry: AFSWriteEntryPayload,\n ): Promise<AFSWriteResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const now = new Date();\n const existing = await this.getScript(name);\n\n // Normalize: REST API may pass raw string, or {content: \"...\"} object\n const rawContent = typeof entry === \"string\" ? entry : entry.content;\n\n // Handle meta-only writes — preserve existing content\n if (rawContent === undefined && existing) {\n const stored: StoredScript = {\n source: existing.source,\n createdAt: existing.createdAt,\n updatedAt: now,\n };\n await this.setScript(name, stored);\n return {\n data: this.buildScriptEntry(name, stored),\n message: \"Script updated\",\n };\n }\n\n const source = typeof rawContent === \"string\" ? rawContent : JSON.stringify(rawContent);\n\n const stored: StoredScript = {\n source,\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n };\n await this.setScript(name, stored);\n this.registerTriggers(name, source);\n\n return {\n data: this.buildScriptEntry(name, stored),\n message: existing ? \"Script updated\" : \"Script created\",\n };\n }\n\n // ========== Delete Handlers ==========\n\n @Delete(\"/scripts/:scriptName\")\n async deleteScript(ctx: RouteContext<{ scriptName: string }>): Promise<AFSDeleteResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n if (!(await this.hasScript(name))) {\n throw new AFSNotFoundError(ctx.path, `Script not found: ${name}`);\n }\n this.unregisterTriggers(name);\n await this.removeScript(name);\n return { message: `Script '${name}' deleted` };\n }\n\n @Delete(\"/:path*\")\n async deleteCatchAll(ctx: RouteContext<{ path: string }>): Promise<AFSDeleteResult> {\n throw new AFSNotFoundError(ctx.path);\n }\n\n // ========== Exec Handlers ==========\n\n @Actions.Exec(\"/scripts/:scriptName\", \"exec\")\n async execScript(\n ctx: RouteContext<{ scriptName: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n return {\n success: false,\n data: { error: `Script not found: ${name}` },\n };\n }\n return this.runAsh(script.source, args);\n }\n\n @Exec(\"/scripts/:scriptName\")\n async execScriptDirect(\n ctx: RouteContext<{ scriptName: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n return this.execScript(ctx, args);\n }\n\n @Actions.Exec(\"/\")\n async execRootAction(\n ctx: RouteContext<{ action: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const actionName = ctx.params.action;\n\n if (actionName === \"run\") {\n const source = args.source;\n if (typeof source !== \"string\") {\n throw new Error(\"action 'run' requires 'source' parameter as string\");\n }\n\n // Job-specific execution: run a single named job with event data as initial stream\n const jobName = args.job as string | undefined;\n if (jobName) {\n const runtimeAFS = args._runtime_afs as AFSRoot | undefined;\n return this.runJob(source, jobName, args, { afsOverride: runtimeAFS });\n }\n\n // Deny-by-default: skip AFS write-back when no explicit caps provided\n const hasCaps = Array.isArray(args.caps) && args.caps.length > 0;\n // Extract runtime AFS override (set by execProgram for program mode)\n const runtimeAFS = args._runtime_afs as AFSRoot | undefined;\n const cleanArgs = { ...args };\n delete cleanArgs._runtime_afs;\n return this.runAsh(source, cleanArgs, { allowWriteBack: hasCaps, afsOverride: runtimeAFS });\n }\n\n if (actionName === \"validate\") {\n const source = args.source;\n if (typeof source !== \"string\") {\n throw new Error(\"action 'validate' requires 'source' parameter as string\");\n }\n const result = compileSource(source);\n const errors = result.diagnostics.filter((d) => d.severity !== \"warning\");\n const warnings = result.diagnostics.filter((d) => d.severity === \"warning\");\n return {\n success: true,\n data: {\n valid: errors.length === 0,\n errors,\n warnings,\n jobCount: result.program?.jobs.length ?? 0,\n sourceHash: result.sourceHash,\n },\n };\n }\n\n if (actionName === \"agent-run\") {\n return this.executeAgentRun(args);\n }\n\n throw new Error(`Unknown action: ${actionName}`);\n }\n\n // ========== Stat Handlers ==========\n\n @Stat(\"/\")\n async statRoot(_ctx: RouteContext): Promise<AFSStatResult> {\n return {\n data: {\n id: \"/\",\n path: \"/\",\n meta: {\n type: \"directory\",\n childrenCount: 1,\n scriptCount: await this.getScriptCount(),\n },\n },\n };\n }\n\n @Stat(\"/scripts\")\n async statScriptsDir(_ctx: RouteContext): Promise<AFSStatResult> {\n return {\n data: {\n id: \"/scripts\",\n path: \"/scripts\",\n meta: { type: \"directory\", childrenCount: await this.getScriptCount() },\n },\n };\n }\n\n @Stat(\"/scripts/:scriptName\")\n async statScript(ctx: RouteContext<{ scriptName: string }>): Promise<AFSStatResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n throw new AFSNotFoundError(ctx.path, `Script not found: ${name}`);\n }\n return {\n data: {\n id: joinURL(\"/scripts\", `${name}.ash`),\n path: joinURL(\"/scripts\", `${name}.ash`),\n createdAt: script.createdAt,\n updatedAt: script.updatedAt,\n meta: {\n type: \"file\",\n kind: \"ash:script\",\n scriptName: name,\n size: new TextEncoder().encode(script.source).length,\n },\n },\n };\n }\n\n // ========== Explain Handlers ==========\n\n @Explain(\"/\")\n async explainRoot(_ctx: RouteContext): Promise<AFSExplainResult> {\n return { format: \"markdown\", content: readDoc(\"agent.md\") };\n }\n\n @Explain(\"/scripts/:scriptName\")\n async explainScript(ctx: RouteContext<{ scriptName: string }>): Promise<AFSExplainResult> {\n const name = ctx.params.scriptName.replace(/\\.ash$/, \"\");\n const script = await this.getScript(name);\n if (!script) {\n throw new AFSNotFoundError(ctx.path, `Script not found: ${name}`);\n }\n\n const result = compileSource(script.source);\n const lines: string[] = [];\n lines.push(`# Script: ${name}.ash`);\n lines.push(\"\");\n lines.push(\"## Source\");\n lines.push(\"\");\n lines.push(\"```ash\");\n lines.push(script.source);\n lines.push(\"```\");\n lines.push(\"\");\n lines.push(\"## Analysis\");\n lines.push(\"\");\n lines.push(`- **Jobs**: ${result.program?.jobs.length ?? 0}`);\n lines.push(`- **Diagnostics**: ${result.diagnostics.length}`);\n lines.push(`- **Size**: ${new TextEncoder().encode(script.source).length} bytes`);\n lines.push(\"\");\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // ========== Search Handler ==========\n\n @Search(\"/:path*\")\n async searchScripts(_ctx: RouteContext, query: string): Promise<AFSSearchResult> {\n const results: AFSEntry[] = [];\n const lowerQuery = query.toLowerCase();\n for (const name of await this.getAllScriptNames()) {\n const script = await this.getScript(name);\n if (!script) continue;\n if (\n name.toLowerCase().includes(lowerQuery) ||\n script.source.toLowerCase().includes(lowerQuery)\n ) {\n results.push(this.buildScriptEntry(name, script));\n }\n }\n return { data: results };\n }\n\n // ========== Private Helpers ==========\n\n private buildScriptEntry(name: string, script: StoredScript): AFSEntry {\n const inputSchema = this.buildScriptExecInputSchema(script.source);\n return {\n id: joinURL(\"/scripts\", `${name}.ash`),\n path: joinURL(\"/scripts\", `${name}.ash`),\n content: script.source,\n createdAt: script.createdAt,\n updatedAt: script.updatedAt,\n meta: {\n type: \"file\",\n kind: \"ash:script\",\n kinds: [\"ash:script\", \"afs:executable\", \"afs:node\"],\n scriptName: name,\n size: new TextEncoder().encode(script.source).length,\n },\n actions: [\n {\n name: \"exec\",\n description: `Execute script ${name}`,\n inputSchema: inputSchema as JSONSchema7,\n },\n ],\n };\n }\n\n private buildScriptExecInputSchema(source: string): {\n type: \"object\";\n properties: Record<string, unknown>;\n } {\n const properties: Record<string, unknown> = {\n caps: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Capability paths. Required for write-back to AFS (default: no write-back without caps)\",\n },\n };\n\n const result = compileSource(source);\n if (result.program) {\n for (const [key, value] of result.program.params) {\n properties[key] = {\n type: typeof value === \"number\" ? \"number\" : \"string\",\n description: `Override ASH param '${key}' at execution time`,\n };\n }\n }\n\n return {\n type: \"object\",\n properties,\n };\n }\n\n /**\n * Create an async-capable world that bridges ASH to AFS.\n * Since ASH's WorldInterface is synchronous but AFS is async,\n * we collect operations and replay them, or use a pre-loaded data approach.\n */\n private async createAsyncWorld(afsOverride?: AFSRoot): Promise<{\n world: WorldInterface;\n written: Record<string, unknown[]>;\n published: Record<string, unknown[]>;\n writeCounts: Record<string, number>;\n preload: (path: string, data: unknown[]) => void;\n flushPersist: () => Promise<void>;\n }> {\n const dataStore: Record<string, unknown[]> = { ...(await this.loadPersistedData()) };\n const written: Record<string, unknown[]> = {};\n const published: Record<string, unknown[]> = {};\n const writeCounts: Record<string, number> = {}; // Track overwrite count per path\n\n const afsRoot = afsOverride ?? this.afsRoot;\n const selfPrefix = `/${this.name}/`; // e.g. \"/ash/\" — dynamic, not hardcoded\n const allowRootActions = this.allowRootActions;\n const pendingPersist: Promise<void>[] = [];\n const persistData = (path: string, data: unknown[]) => {\n pendingPersist.push(this.persistData(path, data).catch(() => {}));\n };\n\n return {\n world: {\n read(path: string): unknown[] {\n return dataStore[path] ?? [];\n },\n write(path: string, data: unknown[]): void {\n // Block writes to this provider's own namespace (supply chain attack prevention)\n // Check both absolute (/{name}/...) and provider-relative (/scripts/...) paths\n if (\n path.startsWith(selfPrefix) ||\n path.startsWith(\"/scripts\") ||\n path.startsWith(\"/.actions\") ||\n path.startsWith(\"/.meta\")\n ) {\n throw new Error(`Write blocked: '${path}' is a protected ASH provider path`);\n }\n writeCounts[path] = (writeCounts[path] ?? 0) + 1;\n written[path] = data;\n // Also make written data readable for chained jobs\n dataStore[path] = data;\n persistData(path, data);\n },\n publish(topic: string, data: unknown[]): void {\n published[topic] = data;\n },\n async exec(\n path: string,\n input: unknown[],\n params?: Record<string, unknown>,\n ): Promise<unknown[]> {\n // Block self-referencing exec to this provider (recursion prevention).\n // Root actions are deny-by-default; only explicitly allowed actions pass.\n const rootActionMatch =\n /^\\/\\.actions\\/([^/]+)$/.exec(path) ??\n new RegExp(\n `^${selfPrefix.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\\\\.actions\\\\/([^/]+)$`,\n ).exec(path);\n const isAllowedRootAction =\n rootActionMatch !== null && allowRootActions.has(rootActionMatch[1]!);\n if (\n !isAllowedRootAction &&\n (path.startsWith(selfPrefix) ||\n path.startsWith(\"/.actions\") ||\n path.startsWith(\"/scripts\"))\n ) {\n throw new Error(\n `Exec blocked: self-referencing call to '${path}' would cause recursion`,\n );\n }\n if (afsRoot?.exec) {\n const baseParams = params ?? {};\n // Filter stream records to valid objects\n const records = input.filter(\n (r): r is Record<string, unknown> => typeof r === \"object\" && r !== null,\n );\n\n if (records.length <= 1) {\n // Single record or empty stream: merge stream fields + inline params into one exec call\n const mergedArgs = { ...(records[0] ?? {}), ...baseParams };\n // Forward _runtime_afs so nested actions (e.g., agent-run) use program namespace\n if (afsOverride) mergedArgs._runtime_afs = afsOverride;\n const result = await afsRoot.exec(path, mergedArgs, {});\n return Array.isArray(result.data) ? result.data : [result.data];\n }\n\n // Multiple records: exec per record, collect results\n const results: unknown[] = [];\n for (const record of records) {\n const mergedArgs = { ...record, ...baseParams };\n if (afsOverride) mergedArgs._runtime_afs = afsOverride;\n const result = await afsRoot.exec(path, mergedArgs, {});\n if (Array.isArray(result.data)) results.push(...result.data);\n else results.push(result.data);\n }\n return results;\n }\n return input;\n },\n async input(prompt: string): Promise<string> {\n // Delegate to /ui/.actions/prompt if a UI provider is mounted\n if (afsRoot?.exec) {\n try {\n const result = await afsRoot.exec(\n \"/ui/.actions/prompt\",\n { message: prompt, type: \"text\" },\n {},\n );\n return String(result.data?.response ?? \"\");\n } catch (err) {\n // UI provider not mounted — fall back to empty\n if (err instanceof AFSNotFoundError) return \"\";\n // Real errors (timeout, prompt failure) should propagate\n throw err;\n }\n }\n return \"\";\n },\n },\n written,\n published,\n writeCounts,\n preload(path: string, data: unknown[]) {\n dataStore[path] = data;\n },\n async flushPersist() {\n await Promise.all(pendingPersist);\n },\n };\n }\n\n // ========== Tools Derivation ==========\n\n private deriveTools(\n agentDir: string,\n extraTools: Array<{\n path: string;\n ops: string[];\n exclude_actions?: string[];\n maxDepth?: number;\n }>,\n channelPath?: string,\n ): Array<{ path: string; ops: string[]; exclude_actions?: string[]; maxDepth?: number }> {\n const base = [\n {\n path: `${agentDir}/**`,\n ops: [\"read\", \"list\", \"write\", \"search\", \"stat\", \"exec\"],\n maxDepth: 10,\n },\n { path: \"/modules/ash/.actions/*\", ops: [\"exec\"] },\n ];\n if (channelPath) {\n base.push({ path: `${channelPath}/**`, ops: [\"exec\"], maxDepth: 5 });\n }\n return [...base, ...extraTools];\n }\n\n private async executeAgentRun(args: Record<string, unknown>): Promise<AFSExecResult> {\n // Extract runtime AFS override (forwarded from program context via _runtime_afs)\n const runtimeAFSOverride = args._runtime_afs as AFSRoot | undefined;\n const cleanArgs = { ...args };\n delete cleanArgs._runtime_afs;\n\n const task = cleanArgs.task;\n if (typeof task !== \"string\" || !task) {\n throw new Error(\"agent-run requires 'task' parameter as string\");\n }\n const model = cleanArgs.model;\n if (typeof model !== \"string\" || !model) {\n throw new Error(\"agent-run requires 'model' parameter as string\");\n }\n const rawTools = cleanArgs.tools;\n // \"none\" or missing → LLM-only mode (no tool calling)\n let tools = rawTools === \"none\" || rawTools === undefined ? [] : rawTools;\n if (!Array.isArray(tools)) {\n throw new Error(\"agent-run 'tools' must be an array or 'none'\");\n }\n\n const globalAFS = this.afsRoot;\n if (!globalAFS && !runtimeAFSOverride) {\n throw new Error(\"agent-run requires AFS root to be mounted\");\n }\n\n // Auto-derive tools when agent_dir is provided\n const agentDir = cleanArgs.agent_dir as string | undefined;\n let targetAFS: AFSRoot = runtimeAFSOverride ?? globalAFS!;\n\n if (runtimeAFSOverride && agentDir) {\n // Program mode via _runtime_afs: the runtime AFS already has isolated namespace\n // with projections set up. Derive tools from program manifest.\n try {\n const yamlResult = await runtimeAFSOverride.read!(joinURL(agentDir, \"program.yaml\"), {});\n const yamlContent = String(yamlResult.data?.content ?? \"\");\n if (yamlContent.trim()) {\n const manifest = parseProgramManifest(yamlContent);\n tools = deriveToolsFromProgram(manifest);\n }\n } catch {\n // Can't read manifest from runtimeAFS — use provided tools as-is\n }\n } else if (agentDir && globalAFS) {\n // Detect if agent_dir is a program by checking for program.yaml\n let isProgram = false;\n try {\n await globalAFS.read!(joinURL(agentDir, \"program.yaml\"), {});\n isProgram = true;\n } catch {\n // No program.yaml → legacy mode\n }\n\n if (isProgram) {\n // Program mode: create Runtime AFS and derive tools from manifest.\n // Once detected as program, any failure is an error — no fallback to legacy.\n try {\n // Read manifest to get program id for data path\n const pyResult = await globalAFS.read!(joinURL(agentDir, \"program.yaml\"), {});\n const pyManifest = parseProgramManifest(String(pyResult.data?.content ?? \"\"));\n const dataPath = joinURL(\"/.data\", pyManifest.id);\n // Ensure data directory exists\n try {\n await globalAFS.write!(joinURL(dataPath, \".keep\"), { content: \"\" });\n } catch {\n // Data directory may not be writable — /data mount will fail gracefully\n }\n const { afs: runtimeAFS, manifest } = await createProgramAFS(\n agentDir,\n dataPath,\n globalAFS as import(\"@aigne/afs\").AFS,\n );\n targetAFS = runtimeAFS;\n tools = deriveToolsFromProgram(manifest);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n error: { code: \"PROGRAM_INIT_ERROR\", message: sanitizeErrorPath(msg) },\n };\n }\n } else {\n // Legacy mode: derive tools from agent_dir path\n const extraTools = (cleanArgs.extra_tools ?? tools) as Array<{\n path: string;\n ops: string[];\n exclude_actions?: string[];\n maxDepth?: number;\n }>;\n const channelPath = cleanArgs.channel_path as string | undefined;\n tools = this.deriveTools(agentDir, extraTools, channelPath);\n }\n }\n\n const afs = targetAFS;\n\n const { runAgentLoop } = await import(\"./agent-run.js\");\n\n // Enrich task with stream context (e.g., user's message text from event data)\n let enrichedTask = task as string;\n if (typeof cleanArgs.text === \"string\" && cleanArgs.text) {\n enrichedTask += `\\n\\nUser message: ${cleanArgs.text}`;\n }\n\n const params = {\n task: enrichedTask,\n model: model as string,\n tools: tools as Array<{\n path: string;\n ops: string[];\n exclude_actions?: string[];\n maxDepth?: number;\n }>,\n budget: cleanArgs.budget as\n | { max_rounds?: number; actions_per_round?: number; total_tokens?: number }\n | undefined,\n system: cleanArgs.system as string | undefined,\n session: cleanArgs.session as string | undefined,\n };\n\n const deps = {\n callLLM: async (llmArgs: Record<string, unknown>) => {\n if (!afs.exec)\n return { success: false, data: { error: \"exec not supported\" } } as AFSExecResult;\n // Resolve model to absolute AigneHub path:\n // \"/modules/aignehub/openai/gpt-4.1-nano\" → as-is\n // \"openai/gpt-4.1-nano\" → \"/modules/aignehub/openai/gpt-4.1-nano\"\n let resolvedModel = model as string;\n if (!resolvedModel.startsWith(\"/\")) {\n resolvedModel = `/modules/aignehub/providers/${resolvedModel}`;\n }\n const modelPath = `${resolvedModel}/.actions/chat`;\n\n // Translate agent-run message format → AigneHub format:\n // - \"assistant\" role → \"agent\"\n // - function.arguments: string → parsed object\n // - tool_call_id → toolCallId\n const translated = { ...llmArgs };\n if (Array.isArray(translated.messages)) {\n translated.messages = (translated.messages as Array<Record<string, unknown>>).map(\n (msg) => {\n const m = { ...msg };\n if (m.role === \"assistant\") m.role = \"agent\";\n // Translate tool result: tool_call_id → toolCallId\n if (m.role === \"tool\" && m.tool_call_id && !m.toolCallId) {\n m.toolCallId = m.tool_call_id;\n delete m.tool_call_id;\n }\n if (Array.isArray(m.toolCalls)) {\n m.toolCalls = (m.toolCalls as Array<Record<string, unknown>>).map((tc) => {\n const fn = tc.function as Record<string, unknown> | undefined;\n if (fn && typeof fn.arguments === \"string\") {\n try {\n return {\n ...tc,\n function: { ...fn, arguments: JSON.parse(fn.arguments as string) },\n };\n } catch {\n return tc;\n }\n }\n return tc;\n });\n }\n return m;\n },\n );\n }\n\n const raw = await afs.exec(modelPath, translated, {});\n // AigneHub wraps LLM output in data.result — unwrap so agent-run\n // can access text/toolCalls/inputTokens/outputTokens directly.\n if (raw.success && raw.data) {\n const inner = raw.data as Record<string, unknown>;\n const result = inner.result as Record<string, unknown> | undefined;\n if (result) {\n const usage = result.usage as Record<string, unknown> | undefined;\n raw.data = {\n text: result.text,\n toolCalls: result.toolCalls,\n inputTokens: usage?.inputTokens,\n outputTokens: usage?.outputTokens,\n };\n }\n }\n return raw;\n },\n runAsh: async (source: string, runArgs: Record<string, unknown>) => {\n return this.runAsh(source, runArgs, {\n returnWrittenData: true,\n skipWritePrefix: \"/.results/\",\n });\n },\n callAFS: async (op: string, path: string, opArgs?: Record<string, unknown>) => {\n switch (op) {\n case \"read\": {\n const r = await afs.read!(path, opArgs ?? {});\n return { success: true, data: r.data } as unknown as AFSExecResult;\n }\n case \"list\": {\n const r = await afs.list(path, opArgs ?? {});\n return { success: true, data: r.data } as unknown as AFSExecResult;\n }\n case \"search\": {\n if (!afs.search)\n return { success: false, data: { error: \"search not supported\" } } as AFSExecResult;\n const r = await afs.search(path, (opArgs?.query as string) ?? \"\", opArgs ?? {});\n return { success: true, data: { results: r.data } } as AFSExecResult;\n }\n case \"write\": {\n if (!afs.write)\n return { success: false, data: { error: \"write not supported\" } } as AFSExecResult;\n const r = await afs.write(path, opArgs ?? {});\n return { success: true, data: { written: r.data } } as unknown as AFSExecResult;\n }\n case \"stat\": {\n if (!afs.stat)\n return { success: false, data: { error: \"stat not supported\" } } as AFSExecResult;\n const r = await afs.stat(path);\n return { success: true, data: { stat: r.data } } as unknown as AFSExecResult;\n }\n case \"explain\": {\n if (!afs.explain)\n return { success: false, data: { error: \"explain not supported\" } } as AFSExecResult;\n const r = await afs.explain(path);\n return { success: true, data: { content: r.content } } as AFSExecResult;\n }\n case \"exec\": {\n if (!afs.exec)\n return { success: false, data: { error: \"exec not supported\" } } as AFSExecResult;\n // LLM may send args nested in { args: {...} } (per tool schema) or flat.\n // Unwrap the nested form so providers receive flat args.\n const execArgs =\n opArgs?.args && typeof opArgs.args === \"object\" && !Array.isArray(opArgs.args)\n ? (opArgs.args as Record<string, unknown>)\n : (opArgs ?? {});\n return afs.exec(path, execArgs, {});\n }\n default:\n return {\n success: false,\n data: { error: `Unsupported direct op: ${op}` },\n } as AFSExecResult;\n }\n },\n loadHistory: async (sessionPath: string) => {\n const historyPath = `${sessionPath}/history.jsonl`;\n try {\n const result = await afs.read!(historyPath, {});\n const content = String(result.data?.content ?? \"\");\n if (!content.trim()) return [];\n return content\n .trim()\n .split(\"\\n\")\n .flatMap((line) => {\n try {\n return [JSON.parse(line)];\n } catch {\n return []; // skip malformed lines\n }\n });\n } catch {\n return []; // session doesn't exist yet\n }\n },\n saveHistory: async (\n sessionPath: string,\n messages: import(\"./agent-run.js\").HistoryMessage[],\n ) => {\n const historyPath = `${sessionPath}/history.jsonl`;\n const content = `${messages.map((m: unknown) => JSON.stringify(m)).join(\"\\n\")}\\n`;\n await afs.write!(historyPath, { content });\n },\n };\n\n const result = await runAgentLoop(params, deps);\n\n return {\n success: result.status === \"completed\",\n data: result as unknown as Record<string, unknown>,\n };\n }\n\n /**\n * Execute a single named job from an ASH source.\n * Used by ProgramManager to run trigger jobs with event data.\n */\n private async runJob(\n source: string,\n jobName: string,\n args: Record<string, unknown>,\n options?: { afsOverride?: AFSRoot },\n ): Promise<AFSExecResult> {\n const effectiveSource = this.applyParamOverridesToSource(source, args);\n const result = compileSource(effectiveSource);\n if (!result.program) {\n return {\n success: false,\n data: { error: \"Compilation failed\", diagnostics: result.diagnostics },\n };\n }\n\n const job = result.program.units.find((u) => u.kind === \"job\" && u.name === jobName);\n if (!job || job.kind !== \"job\") {\n return { success: false, data: { error: `Job \"${jobName}\" not found in source` } };\n }\n\n const afsOverride = options?.afsOverride;\n const { world, written } = await this.createAsyncWorld(afsOverride);\n const effectiveAFS = afsOverride ?? this.afsRoot;\n\n const bridgedWorld: WorldInterface = effectiveAFS\n ? {\n read: async (path: string): Promise<unknown[]> => {\n const local = await world.read(path);\n if (local.length > 0) return local;\n if (effectiveAFS.list) {\n const listResult = await effectiveAFS.list(path, {});\n if (listResult.data.length > 0) {\n const needsEnrich = listResult.data.some((e) => e.content == null);\n let entries = listResult.data;\n if (needsEnrich && effectiveAFS.read) {\n const afsRead = effectiveAFS.read.bind(effectiveAFS);\n entries = await Promise.all(\n listResult.data.map(async (e) => {\n if (e.content != null) return e;\n try {\n const r = await afsRead(e.path, {});\n return r.data ? { ...e, content: r.data.content } : e;\n } catch {\n return e;\n }\n }),\n );\n }\n return entries.map((entry) => ({\n path: entry.path,\n name: entry.path.split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n }));\n }\n }\n if (effectiveAFS.read) {\n try {\n const readResult = await effectiveAFS.read(path, {});\n if (readResult.data) {\n const entry = readResult.data;\n return [\n {\n path: entry.path ?? path,\n name: (entry.path ?? path).split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n },\n ];\n }\n } catch {\n // Path not found\n }\n }\n return [];\n },\n write: (path: string, data: unknown[]): void => {\n world.write(path, data);\n },\n publish: (topic: string, data: unknown[]): void => {\n world.publish(topic, data);\n },\n exec: world.exec,\n }\n : world;\n\n const ctx: JobContext = {\n world: bridgedWorld,\n caps: new Set<string>([\"*\"]),\n logger: { log() {} },\n output: { output() {} },\n };\n\n // Seed initial stream with event data from args\n const event = args.event as Record<string, unknown> | undefined;\n const initialStream: unknown[] = event ? [{ ...event }] : [];\n const jobResult = await job.execute(ctx, initialStream);\n\n // Write results back to AFS\n const afs = effectiveAFS;\n if (afs?.write) {\n for (const [path, data] of Object.entries(written)) {\n const content = JSON.stringify(data);\n await afs.write(path, { content });\n }\n }\n\n if (jobResult.status !== \"ok\") {\n return {\n success: false,\n data: {\n error: `Job \"${jobName}\" failed`,\n status: jobResult.status,\n errors: jobResult.errors,\n },\n };\n }\n\n return { success: true, data: { job: jobName, recordCount: jobResult.recordCount } };\n }\n\n private async runAsh(\n source: string,\n args: Record<string, unknown>,\n options?: {\n returnWrittenData?: boolean;\n skipWritePrefix?: string;\n allowWriteBack?: boolean;\n afsOverride?: AFSRoot;\n },\n ): Promise<AFSExecResult> {\n const effectiveSource = this.applyParamOverridesToSource(source, args);\n const result = compileSource(effectiveSource);\n const errors = result.diagnostics.filter((d) => d.severity !== \"warning\");\n\n if (errors.length > 0 || !result.program) {\n return {\n success: false,\n data: {\n error: \"Compilation failed\",\n diagnostics: result.diagnostics.map((d) => ({\n ...d,\n message: sanitizeErrorPath(d.message),\n })),\n sourceHash: result.sourceHash,\n },\n };\n }\n\n // TOCTOU: verify sourceHash if caller provides expectedHash\n const expectedHash = args.expectedHash;\n if (typeof expectedHash === \"string\" && expectedHash !== result.sourceHash) {\n return {\n success: false,\n data: {\n error: \"Source hash mismatch — code was modified between validate and run (TOCTOU)\",\n expectedHash,\n actualHash: result.sourceHash,\n },\n };\n }\n\n const capsArg = args.caps;\n const caps =\n Array.isArray(capsArg) && capsArg.every((c) => typeof c === \"string\")\n ? new Set<string>(capsArg as string[])\n : new Set<string>([\"*\"]);\n\n const afsOverride = options?.afsOverride;\n const { world, written, published, writeCounts, flushPersist } =\n await this.createAsyncWorld(afsOverride);\n\n // If AFS root is available, create a bridged world\n // Use afsOverride (program Runtime AFS) when available, otherwise this.afsRoot\n const effectiveAFS = afsOverride ?? this.afsRoot;\n const bridgedWorld: WorldInterface = effectiveAFS\n ? {\n read: async (path: string): Promise<unknown[]> => {\n // First check local data store (for chained jobs)\n const local = await world.read(path);\n if (local.length > 0) return local;\n\n if (effectiveAFS) {\n // List children (directory-like nodes)\n if (effectiveAFS.list) {\n const listResult = await effectiveAFS.list(path, {});\n if (listResult.data.length > 0) {\n // Enrich entries that lack content via parallel reads\n const needsEnrich = listResult.data.some((e) => e.content == null);\n let entries = listResult.data;\n if (needsEnrich && effectiveAFS.read) {\n const afsRead = effectiveAFS.read.bind(effectiveAFS);\n entries = await Promise.all(\n listResult.data.map(async (e) => {\n if (e.content != null) return e;\n try {\n const r = await afsRead(e.path, {});\n return r.data ? { ...e, content: r.data.content } : e;\n } catch {\n return e;\n }\n }),\n );\n }\n return entries.map((entry) => ({\n path: entry.path,\n name: entry.path.split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n }));\n }\n }\n\n // Leaf fallback — list empty, try read single entry\n if (effectiveAFS.read) {\n try {\n const readResult = await effectiveAFS.read(path, {});\n if (readResult.data) {\n const entry = readResult.data;\n return [\n {\n path: entry.path ?? path,\n name: (entry.path ?? path).split(\"/\").filter(Boolean).pop(),\n ...entry.meta,\n ...normalizeContent(entry.content),\n },\n ];\n }\n } catch {\n // Path not found — return empty\n }\n }\n }\n\n return [];\n },\n write: (path: string, data: unknown[]): void => {\n world.write(path, data);\n },\n publish: (topic: string, data: unknown[]): void => {\n world.publish(topic, data);\n },\n exec: world.exec,\n }\n : world;\n\n const logs: Array<{ stage: string; action: string; detail?: unknown }> = [];\n const logger: JobLogger = {\n log(stage: string, action: string, detail?: unknown) {\n logs.push({ stage, action, detail });\n },\n };\n\n const outputs: string[] = [];\n const ctx: JobContext = {\n world: bridgedWorld,\n caps,\n logger,\n output: {\n output(event) {\n outputs.push(event.content);\n },\n },\n };\n\n const jobResults: JobResult[] = [];\n for (const unit of result.program.units) {\n if (unit.kind === \"job\") {\n // Skip route-target-only jobs — they execute only when dispatched by route\n if (result.program.routeTargets?.has(unit.name)) continue;\n // Skip triggered jobs — they run reactively via EventBus, not on-demand\n if (unit.trigger) continue;\n jobResults.push(await unit.execute(ctx));\n } else {\n await unit.execute(ctx);\n }\n }\n\n // Strip stage metrics (inputCount/outputCount) to prevent side-channel leakage\n const sanitizedJobs = jobResults.map(({ stages, ...rest }: any) => rest);\n\n const allOk = jobResults.every((r) => r.status === \"ok\");\n const allErrors = jobResults.flatMap((r) => r.errors).map(sanitizeErrorPath);\n\n // Write results back to AFS if mounted.\n // Deny-by-default: skip AFS write-back unless explicitly allowed.\n // Use afsOverride (program Runtime AFS) when available for correct path resolution.\n const afs = afsOverride ?? this.afsRoot;\n const skipPrefix = options?.skipWritePrefix;\n if (afs?.write && options?.allowWriteBack !== false) {\n for (const [path, data] of Object.entries(written)) {\n if (skipPrefix && path.startsWith(skipPrefix)) continue;\n try {\n await afs.write(path, { content: JSON.stringify(data) });\n } catch {\n allErrors.push(\"Failed to write to AFS\");\n }\n }\n for (const [topic, data] of Object.entries(published)) {\n try {\n await afs.write(topic, { content: JSON.stringify(data) });\n } catch {\n allErrors.push(\"Failed to publish to AFS\");\n }\n }\n }\n\n // Detect paths that were overwritten multiple times (fanout race / audit concern)\n const overwrittenPaths = Object.entries(writeCounts)\n .filter(([, count]) => count > 1)\n .map(([path, count]) =>\n sanitizeErrorPath(`Path '${path}' was written ${count} times — only last write preserved`),\n );\n if (overwrittenPaths.length > 0) {\n allErrors.push(...overwrittenPaths);\n }\n\n // Ensure all persistence writes complete before returning\n await flushPersist();\n\n return {\n success: allOk && allErrors.length === 0 && overwrittenPaths.length === 0,\n data: {\n jobs: sanitizedJobs,\n written: Object.keys(written),\n published: Object.keys(published),\n outputs,\n errors: allErrors.length > 0 ? allErrors : undefined,\n warnings: result.diagnostics\n .filter((d) => d.severity === \"warning\")\n .map((d) => ({ ...d, message: sanitizeErrorPath(d.message) })),\n sourceHash: result.sourceHash,\n ...(options?.returnWrittenData ? { writtenData: written } : {}),\n },\n };\n }\n\n private applyParamOverridesToSource(source: string, args: Record<string, unknown>): string {\n const lines = source.split(\"\\n\");\n let changed = false;\n\n const replaced = lines.map((line) => {\n const match = /^(\\s*param\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*)(.+)$/.exec(line);\n if (!match) return line;\n const [, prefix, name] = match;\n if (!name) return line;\n const value = args[name];\n if (typeof value !== \"string\" && typeof value !== \"number\") return line;\n changed = true;\n return `${prefix}${typeof value === \"string\" ? JSON.stringify(value) : String(value)}`;\n });\n\n return changed ? replaced.join(\"\\n\") : source;\n }\n}\n\nexport default AFSAsh;\n"],"mappings":"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"}
|
package/docs/agent.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# ASH Provider — Agent 使用指南
|
|
2
|
+
|
|
3
|
+
ASH 是 AFS 的脚本引擎和 agent 执行环境。它提供两个核心能力:
|
|
4
|
+
1. **ASH 脚本**:确定性的管道式 DSL,用于数据查询和转换
|
|
5
|
+
2. **agent-run**:自主 agentic loop,LLM 驱动的多轮工具调用
|
|
6
|
+
|
|
7
|
+
ASH 应始终挂载在 `/ash/`,是 agent 执行任何自主行为的基础。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ASH 脚本语言
|
|
12
|
+
|
|
13
|
+
### 命令(16 个)
|
|
14
|
+
|
|
15
|
+
| 命令 | 输入 → 输出 | 作用 |
|
|
16
|
+
|------|-------------|------|
|
|
17
|
+
| `find /path` | none → stream | 查询 AFS 路径,返回元数据记录 |
|
|
18
|
+
| `find /path where f == v` | none → stream | 带过滤的查询(query pushdown) |
|
|
19
|
+
| `where field op value` | stream → stream | 过滤记录(`==` `!=` `>` `<` `>=` `<=`) |
|
|
20
|
+
| `map field` | stream → stream | 提取单字段 |
|
|
21
|
+
| `map { out: expr }` | stream → stream | 对象转换(`score: score * 2 + $bonus`) |
|
|
22
|
+
| `save /path` | stream → none | 持久化记录(终止管道) |
|
|
23
|
+
| `publish /topic` | stream → none | 发布到主题(终止管道) |
|
|
24
|
+
| `tee /path` | stream → stream | 侧写副本,流继续 |
|
|
25
|
+
| `count` | stream → stream | 产出 `{ count: N }` |
|
|
26
|
+
| `group-by field` | stream → stream | 产出 `[{ key, items }]` |
|
|
27
|
+
| `output "msg"` | stream → stream | 输出文本,流继续 |
|
|
28
|
+
| `input "prompt"` | none → stream | 提示用户输入 |
|
|
29
|
+
| `fanout { a, b }` | stream → stream | 并行分支 |
|
|
30
|
+
| `action /path` | stream → stream | 执行 AFS action(通过 world.exec) |
|
|
31
|
+
| `route field { "v" -> job j }` | stream → none | 按字段值路由到不同 job(终止管道) |
|
|
32
|
+
| `lookup /path on key` | stream → stream | 与另一路径数据 left-join |
|
|
33
|
+
|
|
34
|
+
### 顶层语句与注解
|
|
35
|
+
|
|
36
|
+
```ash
|
|
37
|
+
param threshold = 70 # 声明参数(调用时可覆盖)
|
|
38
|
+
let bonus = 10 # 绑定变量(字面量或管道结果)
|
|
39
|
+
let total = find /data/users | count # let 也可以接管道
|
|
40
|
+
|
|
41
|
+
@caps(read /data/* write /out/* exec /api/enrich)
|
|
42
|
+
@budget(actions 50, records 10000)
|
|
43
|
+
@on_error(skip)
|
|
44
|
+
@retry(3)
|
|
45
|
+
@timeout(30000)
|
|
46
|
+
@readonly
|
|
47
|
+
job extract {
|
|
48
|
+
find /data/users where active == true
|
|
49
|
+
| where score > $threshold
|
|
50
|
+
| map { fullName: name + " " + surname, score: score * 2 + $bonus }
|
|
51
|
+
| tee /data/backup
|
|
52
|
+
| save /data/clean
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**触发器**:
|
|
57
|
+
```ash
|
|
58
|
+
# 事件触发:当指定路径上的事件发生时运行
|
|
59
|
+
job ingest on /data/raw:created { find /data/raw | save /data/clean }
|
|
60
|
+
|
|
61
|
+
# 定时触发:按 cron 表达式定时运行(标准 5 字段格式)
|
|
62
|
+
job ticker on cron("*/5 * * * *") { find /metrics | save /snapshots }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 管道规则
|
|
66
|
+
|
|
67
|
+
每个 ASH 脚本都是:**source → transform → sink**
|
|
68
|
+
|
|
69
|
+
- `save`、`publish`、`route` 输出 `none` — 后面不能再接管道
|
|
70
|
+
- 每个阶段的输出类型必须匹配下一阶段的输入类型
|
|
71
|
+
- 无分支,无副作用(除了 save/action/publish/tee)
|
|
72
|
+
- `$name` 引用 param 和 let 变量
|
|
73
|
+
|
|
74
|
+
### ASH 不能做的事(安全设计)
|
|
75
|
+
|
|
76
|
+
| 缺失特性 | 原因 |
|
|
77
|
+
|----------|------|
|
|
78
|
+
| 无 read 命令 | `find` 只返回元数据,不返回文件内容。防止任意文件读取。 |
|
|
79
|
+
| 无 emit/literal | 不能凭空创建记录。防止路径注入。 |
|
|
80
|
+
| 无循环 | 无 while/for/递归。使停机分析成为可能。 |
|
|
81
|
+
| 无条件分支 | 无 if/else。`where` 是最接近的,但只作用于记录流。 |
|
|
82
|
+
|
|
83
|
+
每个缺失特性都是一个被避免的攻击面。变量和表达式(`let`、算术、字符串拼接)是编译器静态检查的,不允许动态路径构造。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## agent-run:Agentic Loop
|
|
88
|
+
|
|
89
|
+
agent-run 不是 ASH 的扩展——它在 ASH 之上运行。
|
|
90
|
+
|
|
91
|
+
### 工作原理
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
用户提供:task, model, tools, budget, system prompt
|
|
95
|
+
↓
|
|
96
|
+
agent-run 从 tools 声明生成 LLM tool schema
|
|
97
|
+
↓
|
|
98
|
+
循环:
|
|
99
|
+
1. 调用 LLM(带 messages + tool schema)
|
|
100
|
+
2. 无 tool_calls → 返回 LLM 最终文本(结束)
|
|
101
|
+
3. 验证每个 tool_call 的路径和操作
|
|
102
|
+
4. 路由执行:
|
|
103
|
+
- read/list/search/write/stat/explain → 直接 AFS 调用
|
|
104
|
+
- exec → 生成 ASH 脚本 → 沙箱执行
|
|
105
|
+
5. 结果追加到 messages
|
|
106
|
+
6. 检查 budget(rounds, actions, tokens, timeout)
|
|
107
|
+
7. 回到 1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 参数说明
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"task": "要完成的任务(成为 user message)",
|
|
115
|
+
"model": "/modules/aignehub/providers/{provider}/{model}",
|
|
116
|
+
"tools": [
|
|
117
|
+
{
|
|
118
|
+
"path": "/some/path/*",
|
|
119
|
+
"ops": ["read", "list", "exec"],
|
|
120
|
+
"exclude_actions": ["delete"],
|
|
121
|
+
"maxDepth": 4
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
"budget": {
|
|
125
|
+
"max_rounds": 15,
|
|
126
|
+
"actions_per_round": 8,
|
|
127
|
+
"total_tokens": 200000,
|
|
128
|
+
"timeout": 300
|
|
129
|
+
},
|
|
130
|
+
"system": "System prompt(角色、方法、输出格式)"
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 参数详解
|
|
135
|
+
|
|
136
|
+
**model**:AigneHub 模型路径。用 `list /modules/aignehub/providers/` 发现可用模型。
|
|
137
|
+
|
|
138
|
+
**tools**:声明 LLM 可以访问的 AFS 路径和操作。
|
|
139
|
+
- `path`:支持 `*`(单层匹配)和 `**`(多层匹配,需配合 maxDepth)
|
|
140
|
+
- `ops`:允许的操作列表
|
|
141
|
+
- `exclude_actions`:禁止的 exec action 名称
|
|
142
|
+
- `maxDepth`:`**` 的最大深度(必须显式指定,默认 0 等于不匹配)
|
|
143
|
+
|
|
144
|
+
**budget**:资源限制。
|
|
145
|
+
- `max_rounds`:LLM 调用最大轮数
|
|
146
|
+
- `actions_per_round`:每轮最大 tool call 数
|
|
147
|
+
- `total_tokens`:累计 token 上限
|
|
148
|
+
- `timeout`:整体超时秒数(覆盖 MCP 默认超时)
|
|
149
|
+
|
|
150
|
+
### 你的第一步:从声明路径开始
|
|
151
|
+
|
|
152
|
+
如果你是在 agent-run 内运行的 agent:**你的可访问路径已经在 tools 声明里了**。
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
❌ 错误做法:从根目录向下摸索
|
|
156
|
+
list /modules/project/providers → 拒绝(不在 tools 里)
|
|
157
|
+
list /modules/project/providers/tesla → 拒绝(少了 /src/)
|
|
158
|
+
|
|
159
|
+
✅ 正确做法:直接使用声明路径
|
|
160
|
+
tools 声明了 /modules/project/providers/tesla/src/**
|
|
161
|
+
→ 直接 list /modules/project/providers/tesla/src/
|
|
162
|
+
→ 然后 read 你需要的文件
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**规则**:先看 tools 声明了哪些路径,直接 list 这些路径开始工作。不要猜路径,不要从上层目录探索——path-validator 会拒绝未声明的路径。
|
|
166
|
+
|
|
167
|
+
如果你需要了解 ASH 本身的用法,tools 声明中通常包含 `/ash/**`(读取权限),你可以:
|
|
168
|
+
- `explain /ash` — 读取本文档
|
|
169
|
+
- `list /ash/cookbook/` — 发现实战参考资料
|
|
170
|
+
- `read /ash/cookbook/quickref.md` — 速查卡
|
|
171
|
+
|
|
172
|
+
### 操作路由
|
|
173
|
+
|
|
174
|
+
| 操作 | 路由 | 原因 |
|
|
175
|
+
|------|------|------|
|
|
176
|
+
| read | 直接 AFS | ASH find 只返回元数据,不返回文件内容 |
|
|
177
|
+
| list | 直接 AFS | 同上 |
|
|
178
|
+
| search | 直接 AFS | 全文搜索需要直接 AFS |
|
|
179
|
+
| write | 直接 AFS | 简单写入,不需要沙箱 |
|
|
180
|
+
| stat | 直接 AFS | 元数据查询 |
|
|
181
|
+
| explain | 直接 AFS | 文档查询 |
|
|
182
|
+
| exec | 通过 ASH | 副作用操作需要 @caps 沙箱 + 安全检查 |
|
|
183
|
+
|
|
184
|
+
### Glob 规则
|
|
185
|
+
|
|
186
|
+
`*` 匹配一层:`/a/*` 匹配 `/a/b`,不匹配 `/a/b/c`
|
|
187
|
+
|
|
188
|
+
`**` 匹配多层:`/a/**` 匹配 `/a/b/c`,但需指定 maxDepth:
|
|
189
|
+
```json
|
|
190
|
+
{ "path": "/src/**", "ops": ["read"], "maxDepth": 3 }
|
|
191
|
+
```
|
|
192
|
+
这匹配 `/src/a`、`/src/a/b`、`/src/a/b/c`(最多 3 层)。
|
|
193
|
+
|
|
194
|
+
**maxDepth 未指定时默认 0**——即 `**` 等于不匹配任何东西。必须显式指定。
|
|
195
|
+
|
|
196
|
+
要访问嵌套目录,两种方式:
|
|
197
|
+
```json
|
|
198
|
+
// 方式 1:逐层声明(精确控制)
|
|
199
|
+
{ "path": "/src/*", "ops": ["read"] },
|
|
200
|
+
{ "path": "/src/runtime/*", "ops": ["read"] }
|
|
201
|
+
|
|
202
|
+
// 方式 2:递归 glob(方便但更宽)
|
|
203
|
+
{ "path": "/src/**", "ops": ["read"], "maxDepth": 4 }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Tool Call 格式
|
|
207
|
+
|
|
208
|
+
agent-run 自动适配多种 LLM 返回格式:
|
|
209
|
+
|
|
210
|
+
| 格式 | 来源 | 特征 |
|
|
211
|
+
|------|------|------|
|
|
212
|
+
| OpenAI | AigneHub 大部分模型 | `{ function: { name, arguments: "JSON字符串" } }` |
|
|
213
|
+
| Vercel AI SDK | 部分集成 | `{ toolName, args: {对象} }` |
|
|
214
|
+
| Google | Gemini 系列 | `{ name, ...args扁平在对象上 }` |
|
|
215
|
+
|
|
216
|
+
无需关心——agent-run 内部的 `normalizeToolCall()` 处理所有格式。
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Skills 系统
|
|
221
|
+
|
|
222
|
+
Skill = system prompt + 配置 + agent-run 执行。
|
|
223
|
+
|
|
224
|
+
### Skill 文件结构
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
skill-name/
|
|
228
|
+
├── SKILL.md # System prompt(角色、方法、输出格式)
|
|
229
|
+
└── config.json # 默认配置(模型、budget、tools 模板)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### SKILL.md 编写要点
|
|
233
|
+
|
|
234
|
+
1. **明确角色**——"首席安全工程师"比"代码审查者"找到更多 bug
|
|
235
|
+
2. **定义方法步骤**——引导 LLM 先探索再分析,不要一个文件就下结论
|
|
236
|
+
3. **设定对抗思维**——"假设所有输入都是恶意的"产出更好
|
|
237
|
+
4. **规定输出格式**——LLM 遵循格式指令很好,用于获得一致输出
|
|
238
|
+
5. **控制在 500 字内**——system prompt 消耗 context budget
|
|
239
|
+
|
|
240
|
+
### config.json 结构
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"name": "skill-name",
|
|
245
|
+
"description": "何时触发此 skill",
|
|
246
|
+
"presets": {
|
|
247
|
+
"deep": { "model": "...", "budget": { "timeout": 600 }, "cost_estimate_usd": 3.0 },
|
|
248
|
+
"quick": { "model": "...", "budget": { "max_rounds": 5 }, "cost_estimate_usd": 0.15 }
|
|
249
|
+
},
|
|
250
|
+
"tool_template": {
|
|
251
|
+
"pattern": "/modules/project/providers/{target}/src/**",
|
|
252
|
+
"ops": ["read", "list"],
|
|
253
|
+
"maxDepth": 4
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 执行 Skill
|
|
259
|
+
|
|
260
|
+
读取 SKILL.md + config.json → 构造 agent-run 调用:
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"task": "审计 tesla provider 的安全性",
|
|
264
|
+
"model": "/modules/aignehub/providers/google/gemini-2.5-pro",
|
|
265
|
+
"tools": [{ "path": "/modules/project/providers/tesla/src/**", "ops": ["read","list"], "maxDepth": 4 }],
|
|
266
|
+
"budget": { "max_rounds": 15, "timeout": 600 },
|
|
267
|
+
"system": "<SKILL.md 内容>"
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Skill 设计模式
|
|
272
|
+
|
|
273
|
+
**探索→读取→分析**:代码审计、文档分析
|
|
274
|
+
- Round 1: list 目录了解结构
|
|
275
|
+
- Round 2-N: read 关键文件
|
|
276
|
+
- 最终: 综合分析输出
|
|
277
|
+
|
|
278
|
+
**读取 Memory→综合**:状态报告、摘要
|
|
279
|
+
- Round 1: list + read 所有 memory 文件
|
|
280
|
+
- Round 2: 综合报告
|
|
281
|
+
|
|
282
|
+
**多 Provider 交叉引用**:一致性检查、集成测试
|
|
283
|
+
- Round 1-2: 分别读取 provider A 和 B
|
|
284
|
+
- Round 3+: 交叉对比
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 常见问题与解法
|
|
289
|
+
|
|
290
|
+
### 超时
|
|
291
|
+
MCP 工具默认超时 30 秒。Gemini Pro 读大代码库需要 120-300 秒。
|
|
292
|
+
**解法**:使用 `budget.timeout` 覆盖。
|
|
293
|
+
|
|
294
|
+
### 单层 glob 不够深
|
|
295
|
+
`/src/*` 读不到 `/src/runtime/isolate.ts`。
|
|
296
|
+
**解法**:用 `**` + `maxDepth`,或逐层声明。
|
|
297
|
+
|
|
298
|
+
### LLM 猜错路径
|
|
299
|
+
LLM 经常省略 `/src/` 或猜测不存在的路径。path-validator 拒绝后 LLM 会自我修正。
|
|
300
|
+
**解法**:直接从 tools 声明的路径开始 list,不要从上层目录猜。如果仍需探索,budget 多留 1-2 轮。
|
|
301
|
+
|
|
302
|
+
### find ≠ read
|
|
303
|
+
ASH 的 `find` 返回元数据记录(path, name, size),不是文件内容。
|
|
304
|
+
**解法**:agent-run 已将 read/list 路由到直接 AFS 调用。无需担心。
|
|
305
|
+
|
|
306
|
+
### Budget 调优参考
|
|
307
|
+
|
|
308
|
+
| 任务类型 | max_rounds | timeout | tokens |
|
|
309
|
+
|----------|-----------|---------|--------|
|
|
310
|
+
| 单文件分析 | 3 | 60s | 20K |
|
|
311
|
+
| 5 文件审计 | 6-8 | 120s | 100K |
|
|
312
|
+
| 完整 provider 审计 | 12-15 | 300s | 200K |
|
|
313
|
+
| 大规模批量扫描 | 15-20 | 600s | 300K |
|
|
314
|
+
|
|
315
|
+
### 模型选择参考
|
|
316
|
+
|
|
317
|
+
| 场景 | 推荐模型 | 原因 |
|
|
318
|
+
|------|----------|------|
|
|
319
|
+
| 单文件深度分析 | Claude Haiku 4.5 | 快、精确、代码级引用 |
|
|
320
|
+
| 跨文件架构审查 | Gemini 2.5 Pro | 1M context、找架构问题 |
|
|
321
|
+
| 批量扫描 | Gemini 2.5 Flash | 最快、大 context、浅层分析 |
|
|
322
|
+
| 红队安全测试 | Claude Haiku 4.5 | 最具体的攻击向量 |
|