@aigne/afs-registry 1.11.0-beta.11 → 1.11.0-beta.13
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/dist/index.d.mts +111 -23
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +677 -614
- package/dist/index.mjs.map +1 -1
- package/dist/scanner-CI1h9bn6.mjs +277 -0
- package/dist/scanner-CI1h9bn6.mjs.map +1 -0
- package/dist/scanner-LVTipem0.mjs +3 -0
- package/package.json +3 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["builtinProviders.providers","providers"],"sources":["../schema/providers.json","../src/index.ts"],"sourcesContent":["","import {\n Actions,\n AFSBaseProvider,\n type AFSEntry,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListOptions,\n type AFSListResult,\n AFSNotFoundError,\n type AFSReadOptions,\n type AFSReadResult,\n type AFSRoot,\n type AFSSearchOptions,\n type AFSSearchResult,\n type AFSStatOptions,\n type AFSStatResult,\n AFSValidationError,\n Explain,\n List,\n Meta,\n Read,\n type RouteContext,\n Search,\n Stat,\n} from \"@aigne/afs\";\nimport { buildURI, getTemplateVariableNames } from \"@aigne/afs/utils/uri-template\";\nimport { joinURL } from \"ufo\";\nimport builtinProviders from \"../schema/providers.json\" with { type: \"json\" };\n\n/**\n * A single provider manifest entry in the registry.\n *\n * Aligned with the core ProviderManifest (serialized form: schema as JSON Schema\n * instead of Zod, camelCase field names).\n */\nexport interface ProviderManifest {\n name: string;\n description: string;\n category: string;\n /** URI template with {param} placeholders, e.g. \"s3://{bucket}/{prefix+?}\" */\n uriTemplate: string;\n /** JSON Schema describing provider parameters (serialized from Zod) */\n schema?: Record<string, unknown>;\n tags?: string[];\n useCases?: string[];\n}\n\n/**\n * Options for constructing an AFSRegistry provider.\n */\nexport interface AFSRegistryOptions {\n /** Static provider manifests (for testing / offline use). Overrides url if provided. */\n providers?: ProviderManifest[];\n /** Remote URL to fetch provider manifests from. Falls back to bundled data on failure. */\n url?: string;\n}\n\n/**\n * AFS Registry Provider — virtual file tree for discovering and mounting providers.\n *\n * File tree:\n * ```\n * /\n * ├── providers/{name}/manifest.json\n * ├── providers/{name}/README.md\n * ├── providers/{name}/.actions/mount\n * ├── by-category/{category}/{name}/\n * ├── by-tag/{tag}/{name}/\n * └── .actions/search\n * ```\n */\nexport class AFSRegistry extends AFSBaseProvider {\n readonly name = \"registry\";\n readonly description =\n \"AFS Provider Registry — discover and install available providers.\\n- Browse providers by name, category, or tag\\n- Read provider manifests, README docs, and configuration schemas\\n- Search providers by keyword (name, description, tags, use cases)\\n- Exec actions: `search` (full-text query), `mount` (per-provider, install to AFS)\\n- Path structure: `/providers/{name}/manifest.json`, `/by-category/{cat}`, `/by-tag/{tag}`\";\n readonly accessMode = \"readwrite\" as const;\n\n private providers: ProviderManifest[];\n private remoteUrl?: string;\n private fetchPromise?: Promise<void>;\n private loadProviderFn?: (\n uri: string,\n path: string,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n\n constructor(options: AFSRegistryOptions = {}) {\n super();\n if (options.providers && options.providers.length > 0) {\n // Static providers provided — use them directly\n this.providers = JSON.parse(JSON.stringify(options.providers));\n } else {\n // Start with bundled fallback, then fetch from remote if url given\n this.providers = JSON.parse(JSON.stringify(builtinProviders.providers as ProviderManifest[]));\n this.remoteUrl = options.url;\n if (this.remoteUrl) {\n this.fetchPromise = this.fetchRemoteProviders(this.remoteUrl);\n }\n }\n }\n\n private async fetchRemoteProviders(url: string): Promise<void> {\n try {\n const response = await fetch(url);\n if (!response.ok) return;\n const data = (await response.json()) as { providers?: Record<string, unknown>[] };\n if (Array.isArray(data?.providers) && data.providers.length > 0) {\n // Normalize field names for backward compatibility with older registry formats\n const normalized = data.providers.map((p) => {\n const entry = { ...p } as Record<string, unknown>;\n // uri → uriTemplate\n if (!entry.uriTemplate && entry.uri) {\n entry.uriTemplate = entry.uri;\n delete entry.uri;\n }\n // use_cases → useCases\n if (!entry.useCases && entry.use_cases) {\n entry.useCases = entry.use_cases;\n delete entry.use_cases;\n }\n // capabilities_summary → removed (no replacement)\n delete entry.capabilities_summary;\n return entry;\n });\n this.providers = normalized as unknown as ProviderManifest[];\n }\n } catch {\n // Silent fallback to bundled data\n }\n }\n\n private async ensureLoaded(): Promise<void> {\n if (this.fetchPromise) {\n await this.fetchPromise;\n this.fetchPromise = undefined;\n }\n }\n\n onMount(root: AFSRoot): void {\n this.loadProviderFn = (root as any).loadProvider;\n }\n\n // ── Async gate: ensure remote data is loaded before any operation ──\n\n override async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n await this.ensureLoaded();\n return super.list(path, options);\n }\n\n override async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n await this.ensureLoaded();\n return super.read(path, options);\n }\n\n override async stat(path: string, options?: AFSStatOptions): Promise<AFSStatResult> {\n await this.ensureLoaded();\n return super.stat(path, options);\n }\n\n override async search(\n path: string,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<AFSSearchResult> {\n await this.ensureLoaded();\n return super.search(path, query, options);\n }\n\n override async exec(\n path: string,\n args: Record<string, unknown>,\n options: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ensureLoaded();\n return super.exec(path, args, options);\n }\n\n override async explain(path: string, options?: AFSExplainOptions): Promise<AFSExplainResult> {\n await this.ensureLoaded();\n return super.explain(path, options);\n }\n\n // ── Indexes ──\n\n private buildByCategory(): Map<string, ProviderManifest[]> {\n const map = new Map<string, ProviderManifest[]>();\n for (const p of this.providers) {\n const list = map.get(p.category) || [];\n list.push(p);\n map.set(p.category, list);\n }\n return map;\n }\n\n private buildByTag(): Map<string, ProviderManifest[]> {\n const map = new Map<string, ProviderManifest[]>();\n for (const p of this.providers) {\n for (const tag of p.tags || []) {\n const list = map.get(tag) || [];\n list.push(p);\n map.set(tag, list);\n }\n }\n return map;\n }\n\n private findProvider(name: string): ProviderManifest | undefined {\n return this.providers.find((p) => p.name === name);\n }\n\n // ── List Routes ──\n\n @List(\"/\")\n async listRoot(_ctx: RouteContext) {\n return {\n data: [\n {\n id: \"providers\",\n path: \"/providers\",\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n },\n {\n id: \"by-category\",\n path: \"/by-category\",\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n },\n {\n id: \"by-tag\",\n path: \"/by-tag\",\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n },\n ] as AFSEntry[],\n };\n }\n\n @List(\"/providers\")\n async listProviders(_ctx: RouteContext) {\n return {\n data: this.providers.map((p) => ({\n id: p.name,\n path: joinURL(\"/providers\", p.name),\n summary: p.description,\n meta: {\n kind: \"registry:provider\",\n childrenCount: 3, // manifest.json, README.md, .actions\n },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/providers/:name\")\n async listProviderContents(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n const base = joinURL(\"/providers\", provider.name);\n return {\n data: [\n {\n id: \"manifest.json\",\n path: joinURL(base, \"manifest.json\"),\n meta: { kind: \"afs:file\" },\n },\n {\n id: \"README.md\",\n path: joinURL(base, \"README.md\"),\n meta: { kind: \"afs:file\" },\n },\n ] as AFSEntry[],\n };\n }\n\n @List(\"/by-category\")\n async listCategories(_ctx: RouteContext) {\n return {\n data: Array.from(this.buildByCategory().entries()).map(([cat, providers]) => ({\n id: cat,\n path: joinURL(\"/by-category\", cat),\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-category/:category\")\n async listCategoryProviders(ctx: RouteContext<{ category: string }>) {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n data: providers.map((p) => ({\n id: p.name,\n path: joinURL(\"/by-category\", ctx.params.category, p.name),\n summary: p.description,\n meta: { kind: \"registry:provider\", childrenCount: 2 },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-tag\")\n async listTags(_ctx: RouteContext) {\n return {\n data: Array.from(this.buildByTag().entries()).map(([tag, providers]) => ({\n id: tag,\n path: joinURL(\"/by-tag\", tag),\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-category/:category/:name\")\n async listCategoryProviderChildren(ctx: RouteContext<{ category: string; name: string }>) {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/by-tag/:tag\")\n async listTagProviders(ctx: RouteContext<{ tag: string }>) {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n data: providers.map((p) => ({\n id: p.name,\n path: joinURL(\"/by-tag\", ctx.params.tag, p.name),\n summary: p.description,\n meta: { kind: \"registry:provider\" },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-tag/:tag/:name\")\n async listTagProviderChildren(ctx: RouteContext<{ tag: string; name: string }>) {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/providers/:name/manifest.json\")\n @List(\"/providers/:name/README.md\")\n async listFileNode(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n // ── Read Routes ──\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"/\",\n path: \"/\",\n content: { type: \"registry\", providerCount: this.providers.length },\n meta: { kind: \"registry:root\", childrenCount: 3 },\n };\n }\n\n @Read(\"/providers\")\n async readProviders(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"providers\",\n path: \"/providers\",\n content: { type: \"directory\", count: this.providers.length },\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n };\n }\n\n @Read(\"/providers/:name\")\n async readProvider(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: joinURL(\"/providers\", provider.name),\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\", childrenCount: 2 },\n };\n }\n\n @Read(\"/providers/:name/manifest.json\")\n async readManifest(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \"manifest.json\",\n path: ctx.path,\n content: { ...provider },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/providers/:name/README.md\")\n async readReadme(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const lines = [\n `# ${provider.name}`,\n \"\",\n provider.description,\n \"\",\n `**Category:** ${provider.category}`,\n `**URI Template:** \\`${provider.uriTemplate}\\``,\n ];\n\n if (provider.schema) {\n const props = (provider.schema as any).properties as\n | Record<string, { type?: string; description?: string }>\n | undefined;\n const required = new Set(((provider.schema as any).required as string[]) ?? []);\n if (props) {\n lines.push(\"\", \"## Configuration\", \"\");\n for (const [key, val] of Object.entries(props)) {\n const req = required.has(key) ? \" **(required)**\" : \"\";\n lines.push(`- \\`${key}\\` (${val.type ?? \"string\"})${req} — ${val.description ?? \"\"}`);\n }\n }\n }\n\n if (provider.tags?.length) {\n lines.push(\"\", `**Tags:** ${provider.tags.join(\", \")}`);\n }\n if (provider.useCases?.length) {\n lines.push(\"\", `## Use Cases`, \"\", ...provider.useCases.map((u) => `- ${u}`));\n }\n lines.push(\"\");\n\n return {\n id: \"README.md\",\n path: ctx.path,\n content: lines.join(\"\\n\"),\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/by-category\")\n async readByCategory(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"by-category\",\n path: \"/by-category\",\n content: { type: \"directory\", count: this.buildByCategory().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n };\n }\n\n @Read(\"/by-category/:category\")\n async readCategory(ctx: RouteContext<{ category: string }>): Promise<AFSEntry | undefined> {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: ctx.params.category,\n path: joinURL(\"/by-category\", ctx.params.category),\n content: { type: \"category\", count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Read(\"/by-category/:category/:name\")\n async readCategoryProvider(\n ctx: RouteContext<{ category: string; name: string }>,\n ): Promise<AFSEntry | undefined> {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: ctx.path,\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Read(\"/by-tag\")\n async readByTag(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"by-tag\",\n path: \"/by-tag\",\n content: { type: \"directory\", count: this.buildByTag().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n };\n }\n\n @Read(\"/by-tag/:tag\")\n async readTag(ctx: RouteContext<{ tag: string }>): Promise<AFSEntry | undefined> {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: ctx.params.tag,\n path: joinURL(\"/by-tag\", ctx.params.tag),\n content: { type: \"tag\", count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Read(\"/by-tag/:tag/:name\")\n async readTagProvider(\n ctx: RouteContext<{ tag: string; name: string }>,\n ): Promise<AFSEntry | undefined> {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: ctx.path,\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: {\n operations: {\n list: true,\n read: true,\n write: false,\n delete: false,\n exec: true,\n stat: true,\n explain: true,\n search: true,\n },\n },\n meta: { kind: \"afs:capabilities\" },\n };\n }\n\n // ── Meta Routes ──\n\n @Meta(\"/\")\n async rootMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/.meta\",\n content: {\n providerCount: this.providers.length,\n categories: Array.from(this.buildByCategory().keys()),\n tags: Array.from(this.buildByTag().keys()),\n },\n meta: {\n kind: \"registry:root\",\n childrenCount: 3,\n },\n };\n }\n\n @Meta(\"/providers\")\n async providersMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/providers/.meta\",\n content: { count: this.providers.length },\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n };\n }\n\n @Meta(\"/providers/:name\")\n async providerMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \".meta\"),\n content: {\n name: provider.name,\n category: provider.category,\n uriTemplate: provider.uriTemplate,\n },\n meta: { kind: \"registry:provider\", childrenCount: 2 },\n };\n }\n\n @Meta(\"/providers/:name/manifest.json\")\n async manifestMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"manifest.json\", \".meta\"),\n content: { format: \"json\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/providers/:name/README.md\")\n async readmeMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"README.md\", \".meta\"),\n content: { format: \"markdown\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/by-category\")\n async byCategoryMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/by-category/.meta\",\n content: { count: this.buildByCategory().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n };\n }\n\n @Meta(\"/by-category/:category\")\n async categoryMeta(ctx: RouteContext<{ category: string }>): Promise<AFSEntry> {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-category\", ctx.params.category, \".meta\"),\n content: { category: ctx.params.category, count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Meta(\"/by-category/:category/:name\")\n async categoryProviderMeta(\n ctx: RouteContext<{ category: string; name: string }>,\n ): Promise<AFSEntry> {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-category\", ctx.params.category, provider.name, \".meta\"),\n content: { name: provider.name },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Meta(\"/by-tag\")\n async byTagMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/by-tag/.meta\",\n content: { count: this.buildByTag().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n };\n }\n\n @Meta(\"/by-tag/:tag\")\n async tagMeta(ctx: RouteContext<{ tag: string }>): Promise<AFSEntry> {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-tag\", ctx.params.tag, \".meta\"),\n content: { tag: ctx.params.tag, count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Meta(\"/by-tag/:tag/:name\")\n async tagProviderMeta(ctx: RouteContext<{ tag: string; name: string }>): Promise<AFSEntry> {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-tag\", ctx.params.tag, provider.name, \".meta\"),\n content: { name: provider.name },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n // ── Actions Routes ──\n\n @Actions(\"/\")\n async listRootActions(_ctx: RouteContext) {\n return {\n data: [\n {\n id: \"search\",\n path: \"/.actions/search\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n },\n actions: [\n {\n name: \"search\",\n description: \"Search for providers matching a query\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Search query\" },\n },\n },\n },\n ],\n },\n ] as AFSEntry[],\n };\n }\n\n @Actions.Exec(\"/\", \"search\")\n async searchProviders(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult> {\n // Return all providers — the agent filters client-side\n return {\n success: true,\n data: {\n query: (args.query as string) || \"\",\n providers: this.providers.map((p) => ({ ...p })),\n },\n };\n }\n\n /**\n * Build mount action inputSchema for a provider\n */\n private buildMountSchema(provider: ProviderManifest): Record<string, unknown> {\n return {\n type: \"object\",\n properties: {\n path: { type: \"string\", description: \"Mount path\" },\n uri: {\n type: \"string\",\n description: `Full provider URI (overrides template). Template: ${provider.uriTemplate}`,\n },\n accessMode: {\n type: \"string\",\n enum: [\"readonly\", \"readwrite\"],\n description: \"Access mode (default: readonly)\",\n },\n auth: { type: \"string\", description: \"Authentication token\" },\n description: { type: \"string\", description: \"Human-readable description\" },\n scope: {\n type: \"string\",\n enum: [\"cwd\", \"project\", \"user\"],\n description:\n \"Where to persist the mount config. 'cwd' (default) = current directory, 'project' = project root (.git), 'user' = user home\",\n },\n sensitiveArgs: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Field names that should be treated as sensitive credentials (stored in credentials.toml instead of config.toml)\",\n },\n ...((provider.schema as any)?.properties ?? {}),\n },\n required: [\"path\", ...((provider.schema as any)?.required ?? [])],\n };\n }\n\n @Actions(\"/providers/:name\")\n async listProviderActions(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = this.buildMountSchema(provider);\n\n return {\n data: [\n {\n id: \"mount\",\n path: joinURL(\"/providers\", provider.name, \".actions\", \"mount\"),\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n },\n actions: [\n {\n name: \"mount\",\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n ],\n },\n ] as AFSEntry[],\n };\n }\n\n @Read(\"/providers/:name/.actions/mount\")\n async readMountAction(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = this.buildMountSchema(provider);\n return {\n id: \"mount\",\n path: joinURL(\"/providers\", provider.name, \".actions\", \"mount\"),\n content: {\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n };\n }\n\n @Actions.Exec(\"/providers/:name\", \"mount\")\n async mountProvider(\n ctx: RouteContext<{ name: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n if (!this.loadProviderFn) {\n throw new Error(\"loadProvider not configured — Registry was not mounted on an AFS instance\");\n }\n\n // Validate required 'path' argument\n if (typeof args.path !== \"string\" || args.path.trim() === \"\") {\n throw new AFSValidationError(\"Input validation failed: path: must be a non-empty string\");\n }\n\n const mountPath = args.path as string;\n let uri = args.uri as string | undefined;\n\n if (!uri) {\n // Build URI from template using provided args.\n // Missing optional vars are omitted; missing required vars produce\n // a partial URI (e.g. \"cloudflare://\") that the credential resolver\n // will complete after interactive collection.\n const varNames = getTemplateVariableNames(provider.uriTemplate);\n const vars: Record<string, string | undefined> = {};\n for (const name of varNames) {\n const value = args[name];\n vars[name] = value != null ? String(value) : undefined;\n }\n try {\n uri = buildURI(provider.uriTemplate, vars);\n } catch {\n // Required vars missing — build a minimal scheme:// URI\n // so the credential resolver can still identify the provider\n const scheme = provider.uriTemplate.split(\"://\")[0];\n uri = `${scheme}://`;\n }\n }\n\n // Pass all args except path/uri as options (includes accessMode, auth, description, and provider-specific params)\n const { path: _path, uri: _uri, sensitiveArgs, ...options } = args;\n // Attach _sensitiveArgs annotation so credential resolver can build ad-hoc schema\n if (Array.isArray(sensitiveArgs) && sensitiveArgs.length > 0) {\n options._sensitiveArgs = sensitiveArgs;\n }\n\n await this.loadProviderFn(\n uri,\n mountPath,\n Object.keys(options).length > 0 ? options : undefined,\n );\n\n return {\n success: true,\n data: {\n provider: provider.name,\n uri,\n path: mountPath,\n },\n };\n }\n\n // ── Search Route ──\n\n @Search(\"/\")\n async searchRoot(\n _ctx: RouteContext,\n query: string,\n options?: { limit?: number },\n ): Promise<AFSSearchResult> {\n const q = query.toLowerCase();\n let matched = this.providers.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.category.toLowerCase().includes(q) ||\n p.uriTemplate.toLowerCase().includes(q) ||\n (p.tags || []).some((t) => t.toLowerCase().includes(q)) ||\n (p.useCases || []).some((u) => u.toLowerCase().includes(q)),\n );\n if (options?.limit !== undefined && matched.length > options.limit) {\n matched = matched.slice(0, options.limit);\n }\n return {\n data: matched.map((p) => ({\n id: p.name,\n path: joinURL(\"/providers\", p.name),\n summary: p.description,\n meta: { kind: \"registry:provider\" },\n })),\n };\n }\n\n // ── Explain Route ──\n\n @Explain(\"/:path*\")\n async explainPath(_ctx: RouteContext): Promise<AFSExplainResult> {\n return {\n format: \"markdown\",\n content: [\n \"# AFS Provider Registry\",\n \"\",\n \"This provider exposes a virtual file tree of available AFS providers.\",\n \"\",\n \"## Structure\",\n \"- `/providers/{name}/manifest.json` — Provider metadata\",\n \"- `/providers/{name}/README.md` — Human-readable description\",\n \"- `/providers/{name}/.actions/mount` — Mount action\",\n \"- `/by-category/{category}/` — Browse by category\",\n \"- `/by-tag/{tag}/` — Browse by tag\",\n \"- `/.actions/search` — Full-text search across providers\",\n \"\",\n `**Total providers:** ${this.providers.length}`,\n ].join(\"\\n\"),\n };\n }\n\n // ── Stat Route ──\n\n @Stat(\"/\")\n @Stat(\"/providers\")\n @Stat(\"/providers/:name\")\n @Stat(\"/providers/:name/manifest.json\")\n @Stat(\"/providers/:name/README.md\")\n @Stat(\"/by-category\")\n @Stat(\"/by-category/:category\")\n @Stat(\"/by-category/:category/:name\")\n @Stat(\"/by-tag\")\n @Stat(\"/by-tag/:tag\")\n @Stat(\"/by-tag/:tag/:name\")\n async statPath(ctx: RouteContext): Promise<AFSStatResult> {\n // Delegate to read to get actual entry data\n const readResult = await this.read(ctx.path);\n if (readResult.data) {\n return { data: readResult.data };\n }\n throw new AFSNotFoundError(ctx.path);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACwEA,IAAa,cAAb,cAAiC,gBAAgB;CAC/C,AAAS,OAAO;CAChB,AAAS,cACP;CACF,AAAS,aAAa;CAEtB,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAMR,YAAY,UAA8B,EAAE,EAAE;AAC5C,SAAO;AACP,MAAI,QAAQ,aAAa,QAAQ,UAAU,SAAS,EAElD,MAAK,YAAY,KAAK,MAAM,KAAK,UAAU,QAAQ,UAAU,CAAC;OACzD;AAEL,QAAK,YAAY,KAAK,MAAM,KAAK,UAAUA,UAAiD,CAAC;AAC7F,QAAK,YAAY,QAAQ;AACzB,OAAI,KAAK,UACP,MAAK,eAAe,KAAK,qBAAqB,KAAK,UAAU;;;CAKnE,MAAc,qBAAqB,KAA4B;AAC7D,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,IAAI;AACjC,OAAI,CAAC,SAAS,GAAI;GAClB,MAAM,OAAQ,MAAM,SAAS,MAAM;AACnC,OAAI,MAAM,QAAQ,MAAM,UAAU,IAAI,KAAK,UAAU,SAAS,EAkB5D,MAAK,YAhBc,KAAK,UAAU,KAAK,MAAM;IAC3C,MAAM,QAAQ,EAAE,GAAG,GAAG;AAEtB,QAAI,CAAC,MAAM,eAAe,MAAM,KAAK;AACnC,WAAM,cAAc,MAAM;AAC1B,YAAO,MAAM;;AAGf,QAAI,CAAC,MAAM,YAAY,MAAM,WAAW;AACtC,WAAM,WAAW,MAAM;AACvB,YAAO,MAAM;;AAGf,WAAO,MAAM;AACb,WAAO;KACP;UAGE;;CAKV,MAAc,eAA8B;AAC1C,MAAI,KAAK,cAAc;AACrB,SAAM,KAAK;AACX,QAAK,eAAe;;;CAIxB,QAAQ,MAAqB;AAC3B,OAAK,iBAAkB,KAAa;;CAKtC,MAAe,KAAK,MAAc,SAAkD;AAClF,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,KAAK,MAAM,QAAQ;;CAGlC,MAAe,KAAK,MAAc,SAAkD;AAClF,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,KAAK,MAAM,QAAQ;;CAGlC,MAAe,KAAK,MAAc,SAAkD;AAClF,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,KAAK,MAAM,QAAQ;;CAGlC,MAAe,OACb,MACA,OACA,SAC0B;AAC1B,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,OAAO,MAAM,OAAO,QAAQ;;CAG3C,MAAe,KACb,MACA,MACA,SACwB;AACxB,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,KAAK,MAAM,MAAM,QAAQ;;CAGxC,MAAe,QAAQ,MAAc,SAAwD;AAC3F,QAAM,KAAK,cAAc;AACzB,SAAO,MAAM,QAAQ,MAAM,QAAQ;;CAKrC,AAAQ,kBAAmD;EACzD,MAAM,sBAAM,IAAI,KAAiC;AACjD,OAAK,MAAM,KAAK,KAAK,WAAW;GAC9B,MAAM,OAAO,IAAI,IAAI,EAAE,SAAS,IAAI,EAAE;AACtC,QAAK,KAAK,EAAE;AACZ,OAAI,IAAI,EAAE,UAAU,KAAK;;AAE3B,SAAO;;CAGT,AAAQ,aAA8C;EACpD,MAAM,sBAAM,IAAI,KAAiC;AACjD,OAAK,MAAM,KAAK,KAAK,UACnB,MAAK,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE;GAC9B,MAAM,OAAO,IAAI,IAAI,IAAI,IAAI,EAAE;AAC/B,QAAK,KAAK,EAAE;AACZ,OAAI,IAAI,KAAK,KAAK;;AAGtB,SAAO;;CAGT,AAAQ,aAAa,MAA4C;AAC/D,SAAO,KAAK,UAAU,MAAM,MAAM,EAAE,SAAS,KAAK;;CAKpD,MACM,SAAS,MAAoB;AACjC,SAAO,EACL,MAAM;GACJ;IACE,IAAI;IACJ,MAAM;IACN,MAAM;KAAE,MAAM;KAAiB,eAAe,KAAK,UAAU;KAAQ;IACtE;GACD;IACE,IAAI;IACJ,MAAM;IACN,MAAM;KAAE,MAAM;KAAiB,eAAe,KAAK,iBAAiB,CAAC;KAAM;IAC5E;GACD;IACE,IAAI;IACJ,MAAM;IACN,MAAM;KAAE,MAAM;KAAiB,eAAe,KAAK,YAAY,CAAC;KAAM;IACvE;GACF,EACF;;CAGH,MACM,cAAc,MAAoB;AACtC,SAAO,EACL,MAAM,KAAK,UAAU,KAAK,OAAO;GAC/B,IAAI,EAAE;GACN,MAAM,QAAQ,cAAc,EAAE,KAAK;GACnC,SAAS,EAAE;GACX,MAAM;IACJ,MAAM;IACN,eAAe;IAChB;GACF,EAAE,EACJ;;CAGH,MACM,qBAAqB,KAAqC;EAC9D,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;EACnD,MAAM,OAAO,QAAQ,cAAc,SAAS,KAAK;AACjD,SAAO,EACL,MAAM,CACJ;GACE,IAAI;GACJ,MAAM,QAAQ,MAAM,gBAAgB;GACpC,MAAM,EAAE,MAAM,YAAY;GAC3B,EACD;GACE,IAAI;GACJ,MAAM,QAAQ,MAAM,YAAY;GAChC,MAAM,EAAE,MAAM,YAAY;GAC3B,CACF,EACF;;CAGH,MACM,eAAe,MAAoB;AACvC,SAAO,EACL,MAAM,MAAM,KAAK,KAAK,iBAAiB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,KAAKC,kBAAgB;GAC5E,IAAI;GACJ,MAAM,QAAQ,gBAAgB,IAAI;GAClC,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE,EAAE,EACJ;;CAGH,MACM,sBAAsB,KAAyC;EACnE,MAAMA,cAAY,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS;AACjE,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO,EACL,MAAMA,YAAU,KAAK,OAAO;GAC1B,IAAI,EAAE;GACN,MAAM,QAAQ,gBAAgB,IAAI,OAAO,UAAU,EAAE,KAAK;GAC1D,SAAS,EAAE;GACX,MAAM;IAAE,MAAM;IAAqB,eAAe;IAAG;GACtD,EAAE,EACJ;;CAGH,MACM,SAAS,MAAoB;AACjC,SAAO,EACL,MAAM,MAAM,KAAK,KAAK,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,KAAKA,kBAAgB;GACvE,IAAI;GACJ,MAAM,QAAQ,WAAW,IAAI;GAC7B,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE,EAAE,EACJ;;CAGH,MACM,6BAA6B,KAAuD;AAGxF,MAAI,CAFc,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS,EACrC,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK,CACpD,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO,EAAE,MAAM,EAAE,EAAgB;;CAGnC,MACM,iBAAiB,KAAoC;EACzD,MAAMA,cAAY,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI;AACvD,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO,EACL,MAAMA,YAAU,KAAK,OAAO;GAC1B,IAAI,EAAE;GACN,MAAM,QAAQ,WAAW,IAAI,OAAO,KAAK,EAAE,KAAK;GAChD,SAAS,EAAE;GACX,MAAM,EAAE,MAAM,qBAAqB;GACpC,EAAE,EACJ;;CAGH,MACM,wBAAwB,KAAkD;AAG9E,MAAI,CAFc,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI,EAC3B,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK,CACpD,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO,EAAE,MAAM,EAAE,EAAgB;;CAGnC,MAEM,aAAa,KAAqC;AAEtD,MAAI,CADa,KAAK,aAAa,IAAI,OAAO,KAAK,CACpC,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO,EAAE,MAAM,EAAE,EAAgB;;CAKnC,MACM,SAAS,MAAmD;AAChE,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS;IAAE,MAAM;IAAY,eAAe,KAAK,UAAU;IAAQ;GACnE,MAAM;IAAE,MAAM;IAAiB,eAAe;IAAG;GAClD;;CAGH,MACM,cAAc,MAAmD;AACrE,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS;IAAE,MAAM;IAAa,OAAO,KAAK,UAAU;IAAQ;GAC5D,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,UAAU;IAAQ;GACtE;;CAGH,MACM,aAAa,KAAoE;EACrF,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI,SAAS;GACb,MAAM,QAAQ,cAAc,SAAS,KAAK;GAC1C,SAAS;IAAE,MAAM;IAAY,MAAM,SAAS;IAAM,aAAa,SAAS;IAAa;GACrF,MAAM;IAAE,MAAM;IAAqB,eAAe;IAAG;GACtD;;CAGH,MACM,aAAa,KAAoE;EACrF,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,IAAI;GACV,SAAS,EAAE,GAAG,UAAU;GACxB,MAAM,EAAE,MAAM,YAAY;GAC3B;;CAGH,MACM,WAAW,KAAoE;EACnF,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;EAEnD,MAAM,QAAQ;GACZ,KAAK,SAAS;GACd;GACA,SAAS;GACT;GACA,iBAAiB,SAAS;GAC1B,uBAAuB,SAAS,YAAY;GAC7C;AAED,MAAI,SAAS,QAAQ;GACnB,MAAM,QAAS,SAAS,OAAe;GAGvC,MAAM,WAAW,IAAI,IAAM,SAAS,OAAe,YAAyB,EAAE,CAAC;AAC/E,OAAI,OAAO;AACT,UAAM,KAAK,IAAI,oBAAoB,GAAG;AACtC,SAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,MAAM,EAAE;KAC9C,MAAM,MAAM,SAAS,IAAI,IAAI,GAAG,oBAAoB;AACpD,WAAM,KAAK,OAAO,IAAI,MAAM,IAAI,QAAQ,SAAS,GAAG,IAAI,KAAK,IAAI,eAAe,KAAK;;;;AAK3F,MAAI,SAAS,MAAM,OACjB,OAAM,KAAK,IAAI,aAAa,SAAS,KAAK,KAAK,KAAK,GAAG;AAEzD,MAAI,SAAS,UAAU,OACrB,OAAM,KAAK,IAAI,gBAAgB,IAAI,GAAG,SAAS,SAAS,KAAK,MAAM,KAAK,IAAI,CAAC;AAE/E,QAAM,KAAK,GAAG;AAEd,SAAO;GACL,IAAI;GACJ,MAAM,IAAI;GACV,SAAS,MAAM,KAAK,KAAK;GACzB,MAAM,EAAE,MAAM,YAAY;GAC3B;;CAGH,MACM,eAAe,MAAmD;AACtE,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS;IAAE,MAAM;IAAa,OAAO,KAAK,iBAAiB,CAAC;IAAM;GAClE,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,iBAAiB,CAAC;IAAM;GAC5E;;CAGH,MACM,aAAa,KAAwE;EACzF,MAAMA,cAAY,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS;AACjE,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO;GACL,IAAI,IAAI,OAAO;GACf,MAAM,QAAQ,gBAAgB,IAAI,OAAO,SAAS;GAClD,SAAS;IAAE,MAAM;IAAY,OAAOA,YAAU;IAAQ;GACtD,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE;;CAGH,MACM,qBACJ,KAC+B;EAE/B,MAAM,WADY,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS,EACrC,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK;AACnE,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI,SAAS;GACb,MAAM,IAAI;GACV,SAAS;IAAE,MAAM;IAAY,MAAM,SAAS;IAAM,aAAa,SAAS;IAAa;GACrF,MAAM,EAAE,MAAM,qBAAqB;GACpC;;CAGH,MACM,UAAU,MAAmD;AACjE,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS;IAAE,MAAM;IAAa,OAAO,KAAK,YAAY,CAAC;IAAM;GAC7D,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,YAAY,CAAC;IAAM;GACvE;;CAGH,MACM,QAAQ,KAAmE;EAC/E,MAAMA,cAAY,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI;AACvD,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO;GACL,IAAI,IAAI,OAAO;GACf,MAAM,QAAQ,WAAW,IAAI,OAAO,IAAI;GACxC,SAAS;IAAE,MAAM;IAAO,OAAOA,YAAU;IAAQ;GACjD,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE;;CAGH,MACM,gBACJ,KAC+B;EAE/B,MAAM,WADY,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI,EAC3B,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK;AACnE,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI,SAAS;GACb,MAAM,IAAI;GACV,SAAS;IAAE,MAAM;IAAY,MAAM,SAAS;IAAM,aAAa,SAAS;IAAa;GACrF,MAAM,EAAE,MAAM,qBAAqB;GACpC;;CAGH,MACM,iBAAiB,MAAmD;AACxE,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS,EACP,YAAY;IACV,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACT,EACF;GACD,MAAM,EAAE,MAAM,oBAAoB;GACnC;;CAKH,MACM,SAAS,MAAuC;AACpD,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS;IACP,eAAe,KAAK,UAAU;IAC9B,YAAY,MAAM,KAAK,KAAK,iBAAiB,CAAC,MAAM,CAAC;IACrD,MAAM,MAAM,KAAK,KAAK,YAAY,CAAC,MAAM,CAAC;IAC3C;GACD,MAAM;IACJ,MAAM;IACN,eAAe;IAChB;GACF;;CAGH,MACM,cAAc,MAAuC;AACzD,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS,EAAE,OAAO,KAAK,UAAU,QAAQ;GACzC,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,UAAU;IAAQ;GACtE;;CAGH,MACM,aAAa,KAAwD;EACzE,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,cAAc,SAAS,MAAM,QAAQ;GACnD,SAAS;IACP,MAAM,SAAS;IACf,UAAU,SAAS;IACnB,aAAa,SAAS;IACvB;GACD,MAAM;IAAE,MAAM;IAAqB,eAAe;IAAG;GACtD;;CAGH,MACM,aAAa,KAAwD;EACzE,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,cAAc,SAAS,MAAM,iBAAiB,QAAQ;GACpE,SAAS,EAAE,QAAQ,QAAQ;GAC3B,MAAM,EAAE,MAAM,YAAY;GAC3B;;CAGH,MACM,WAAW,KAAwD;EACvE,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,cAAc,SAAS,MAAM,aAAa,QAAQ;GAChE,SAAS,EAAE,QAAQ,YAAY;GAC/B,MAAM,EAAE,MAAM,YAAY;GAC3B;;CAGH,MACM,eAAe,MAAuC;AAC1D,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS,EAAE,OAAO,KAAK,iBAAiB,CAAC,MAAM;GAC/C,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,iBAAiB,CAAC;IAAM;GAC5E;;CAGH,MACM,aAAa,KAA4D;EAC7E,MAAMA,cAAY,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS;AACjE,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,gBAAgB,IAAI,OAAO,UAAU,QAAQ;GAC3D,SAAS;IAAE,UAAU,IAAI,OAAO;IAAU,OAAOA,YAAU;IAAQ;GACnE,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE;;CAGH,MACM,qBACJ,KACmB;EAEnB,MAAM,WADY,KAAK,iBAAiB,CAAC,IAAI,IAAI,OAAO,SAAS,EACrC,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK;AACnE,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,gBAAgB,IAAI,OAAO,UAAU,SAAS,MAAM,QAAQ;GAC1E,SAAS,EAAE,MAAM,SAAS,MAAM;GAChC,MAAM,EAAE,MAAM,qBAAqB;GACpC;;CAGH,MACM,UAAU,MAAuC;AACrD,SAAO;GACL,IAAI;GACJ,MAAM;GACN,SAAS,EAAE,OAAO,KAAK,YAAY,CAAC,MAAM;GAC1C,MAAM;IAAE,MAAM;IAAiB,eAAe,KAAK,YAAY,CAAC;IAAM;GACvE;;CAGH,MACM,QAAQ,KAAuD;EACnE,MAAMA,cAAY,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI;AACvD,MAAI,CAACA,YAAW,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACpD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,WAAW,IAAI,OAAO,KAAK,QAAQ;GACjD,SAAS;IAAE,KAAK,IAAI,OAAO;IAAK,OAAOA,YAAU;IAAQ;GACzD,MAAM;IAAE,MAAM;IAAiB,eAAeA,YAAU;IAAQ;GACjE;;CAGH,MACM,gBAAgB,KAAqE;EAEzF,MAAM,WADY,KAAK,YAAY,CAAC,IAAI,IAAI,OAAO,IAAI,EAC3B,MAAM,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK;AACnE,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,WAAW,IAAI,OAAO,KAAK,SAAS,MAAM,QAAQ;GAChE,SAAS,EAAE,MAAM,SAAS,MAAM;GAChC,MAAM,EAAE,MAAM,qBAAqB;GACpC;;CAKH,MACM,gBAAgB,MAAoB;AACxC,SAAO,EACL,MAAM,CACJ;GACE,IAAI;GACJ,MAAM;GACN,MAAM;IACJ,MAAM;IACN,OAAO,CAAC,kBAAkB,WAAW;IACtC;GACD,SAAS,CACP;IACE,MAAM;IACN,aAAa;IACb,aAAa;KACX,MAAM;KACN,YAAY,EACV,OAAO;MAAE,MAAM;MAAU,aAAa;MAAgB,EACvD;KACF;IACF,CACF;GACF,CACF,EACF;;CAGH,MACM,gBAAgB,MAAoB,MAAuD;AAE/F,SAAO;GACL,SAAS;GACT,MAAM;IACJ,OAAQ,KAAK,SAAoB;IACjC,WAAW,KAAK,UAAU,KAAK,OAAO,EAAE,GAAG,GAAG,EAAE;IACjD;GACF;;;;;CAMH,AAAQ,iBAAiB,UAAqD;AAC5E,SAAO;GACL,MAAM;GACN,YAAY;IACV,MAAM;KAAE,MAAM;KAAU,aAAa;KAAc;IACnD,KAAK;KACH,MAAM;KACN,aAAa,qDAAqD,SAAS;KAC5E;IACD,YAAY;KACV,MAAM;KACN,MAAM,CAAC,YAAY,YAAY;KAC/B,aAAa;KACd;IACD,MAAM;KAAE,MAAM;KAAU,aAAa;KAAwB;IAC7D,aAAa;KAAE,MAAM;KAAU,aAAa;KAA8B;IAC1E,OAAO;KACL,MAAM;KACN,MAAM;MAAC;MAAO;MAAW;MAAO;KAChC,aACE;KACH;IACD,eAAe;KACb,MAAM;KACN,OAAO,EAAE,MAAM,UAAU;KACzB,aACE;KACH;IACD,GAAK,SAAS,QAAgB,cAAc,EAAE;IAC/C;GACD,UAAU,CAAC,QAAQ,GAAK,SAAS,QAAgB,YAAY,EAAE,CAAE;GAClE;;CAGH,MACM,oBAAoB,KAAqC;EAC7D,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;EAEnD,MAAM,cAAc,KAAK,iBAAiB,SAAS;AAEnD,SAAO,EACL,MAAM,CACJ;GACE,IAAI;GACJ,MAAM,QAAQ,cAAc,SAAS,MAAM,YAAY,QAAQ;GAC/D,MAAM;IACJ,MAAM;IACN,OAAO,CAAC,kBAAkB,WAAW;IACtC;GACD,SAAS,CACP;IACE,MAAM;IACN,aAAa,aAAa,SAAS,KAAK;IACxC,aAAa;IACd,CACF;GACF,CACF,EACF;;CAGH,MACM,gBAAgB,KAAoE;EACxF,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;EAEnD,MAAM,cAAc,KAAK,iBAAiB,SAAS;AACnD,SAAO;GACL,IAAI;GACJ,MAAM,QAAQ,cAAc,SAAS,MAAM,YAAY,QAAQ;GAC/D,SAAS;IACP,aAAa,aAAa,SAAS,KAAK;IACxC,aAAa;IACd;GACD,MAAM;IACJ,MAAM;IACN,OAAO,CAAC,kBAAkB,WAAW;IACrC,aAAa,aAAa,SAAS,KAAK;IACxC,aAAa;IACd;GACF;;CAGH,MACM,cACJ,KACA,MACwB;EACxB,MAAM,WAAW,KAAK,aAAa,IAAI,OAAO,KAAK;AACnD,MAAI,CAAC,SAAU,OAAM,IAAI,iBAAiB,IAAI,KAAK;AAEnD,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,4EAA4E;AAI9F,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,MAAM,KAAK,GACxD,OAAM,IAAI,mBAAmB,4DAA4D;EAG3F,MAAM,YAAY,KAAK;EACvB,IAAI,MAAM,KAAK;AAEf,MAAI,CAAC,KAAK;GAKR,MAAM,WAAW,yBAAyB,SAAS,YAAY;GAC/D,MAAM,OAA2C,EAAE;AACnD,QAAK,MAAM,QAAQ,UAAU;IAC3B,MAAM,QAAQ,KAAK;AACnB,SAAK,QAAQ,SAAS,OAAO,OAAO,MAAM,GAAG;;AAE/C,OAAI;AACF,UAAM,SAAS,SAAS,aAAa,KAAK;WACpC;AAIN,UAAM,GADS,SAAS,YAAY,MAAM,MAAM,CAAC,GACjC;;;EAKpB,MAAM,EAAE,MAAM,OAAO,KAAK,MAAM,eAAe,GAAG,YAAY;AAE9D,MAAI,MAAM,QAAQ,cAAc,IAAI,cAAc,SAAS,EACzD,SAAQ,iBAAiB;AAG3B,QAAM,KAAK,eACT,KACA,WACA,OAAO,KAAK,QAAQ,CAAC,SAAS,IAAI,UAAU,OAC7C;AAED,SAAO;GACL,SAAS;GACT,MAAM;IACJ,UAAU,SAAS;IACnB;IACA,MAAM;IACP;GACF;;CAKH,MACM,WACJ,MACA,OACA,SAC0B;EAC1B,MAAM,IAAI,MAAM,aAAa;EAC7B,IAAI,UAAU,KAAK,UAAU,QAC1B,MACC,EAAE,KAAK,aAAa,CAAC,SAAS,EAAE,IAChC,EAAE,YAAY,aAAa,CAAC,SAAS,EAAE,IACvC,EAAE,SAAS,aAAa,CAAC,SAAS,EAAE,IACpC,EAAE,YAAY,aAAa,CAAC,SAAS,EAAE,KACtC,EAAE,QAAQ,EAAE,EAAE,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,KACtD,EAAE,YAAY,EAAE,EAAE,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,CAC9D;AACD,MAAI,SAAS,UAAU,UAAa,QAAQ,SAAS,QAAQ,MAC3D,WAAU,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAE3C,SAAO,EACL,MAAM,QAAQ,KAAK,OAAO;GACxB,IAAI,EAAE;GACN,MAAM,QAAQ,cAAc,EAAE,KAAK;GACnC,SAAS,EAAE;GACX,MAAM,EAAE,MAAM,qBAAqB;GACpC,EAAE,EACJ;;CAKH,MACM,YAAY,MAA+C;AAC/D,SAAO;GACL,QAAQ;GACR,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,wBAAwB,KAAK,UAAU;IACxC,CAAC,KAAK,KAAK;GACb;;CAKH,MAWM,SAAS,KAA2C;EAExD,MAAM,aAAa,MAAM,KAAK,KAAK,IAAI,KAAK;AAC5C,MAAI,WAAW,KACb,QAAO,EAAE,MAAM,WAAW,MAAM;AAElC,QAAM,IAAI,iBAAiB,IAAI,KAAK;;;YAttBrC,KAAK,IAAI;YAuBT,KAAK,aAAa;YAelB,KAAK,mBAAmB;YAqBxB,KAAK,eAAe;YAWpB,KAAK,yBAAyB;YAc9B,KAAK,UAAU;YAWf,KAAK,+BAA+B;YAQpC,KAAK,eAAe;YAcpB,KAAK,qBAAqB;YAQ1B,KAAK,iCAAiC,EACtC,KAAK,6BAA6B;YASlC,KAAK,IAAI;YAUT,KAAK,aAAa;YAUlB,KAAK,mBAAmB;YAYxB,KAAK,iCAAiC;YAYtC,KAAK,6BAA6B;YA4ClC,KAAK,eAAe;YAUpB,KAAK,yBAAyB;YAY9B,KAAK,+BAA+B;YAepC,KAAK,UAAU;YAUf,KAAK,eAAe;YAYpB,KAAK,qBAAqB;YAe1B,KAAK,uBAAuB;YAuB5B,KAAK,IAAI;YAiBT,KAAK,aAAa;YAUlB,KAAK,mBAAmB;YAgBxB,KAAK,iCAAiC;YAYtC,KAAK,6BAA6B;YAYlC,KAAK,eAAe;YAUpB,KAAK,yBAAyB;YAY9B,KAAK,+BAA+B;YAepC,KAAK,UAAU;YAUf,KAAK,eAAe;YAYpB,KAAK,qBAAqB;YAe1B,QAAQ,IAAI;YA4BZ,QAAQ,KAAK,KAAK,SAAS;YAiD3B,QAAQ,mBAAmB;YA4B3B,KAAK,kCAAkC;YAsBvC,QAAQ,KAAK,oBAAoB,QAAQ;YAkEzC,OAAO,IAAI;YA+BX,QAAQ,UAAU;;CAwBlB,KAAK,IAAI;CACT,KAAK,aAAa;CAClB,KAAK,mBAAmB;CACxB,KAAK,iCAAiC;CACtC,KAAK,6BAA6B;CAClC,KAAK,eAAe;CACpB,KAAK,yBAAyB;CAC9B,KAAK,+BAA+B;CACpC,KAAK,UAAU;CACf,KAAK,eAAe;CACpB,KAAK,qBAAqB"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["scanInstalledProviders","lines"],"sources":["../src/index.ts"],"sourcesContent":["import {\n Actions,\n AFS_CATEGORIES,\n AFSBaseProvider,\n type AFSEntry,\n type AFSExecResult,\n type AFSExplainOptions,\n type AFSExplainResult,\n type AFSListOptions,\n type AFSListResult,\n AFSNotFoundError,\n type AFSReadOptions,\n type AFSReadResult,\n type AFSRoot,\n type AFSSearchOptions,\n type AFSSearchResult,\n type AFSStatOptions,\n type AFSStatResult,\n CAPABILITY_TAGS,\n Explain,\n List,\n Meta,\n Read,\n type RouteContext,\n Search,\n Stat,\n} from \"@aigne/afs\";\nimport { buildURI, getTemplateVariableNames } from \"@aigne/afs/utils/uri-template\";\nimport { joinURL } from \"ufo\";\n/**\n * A single provider manifest entry in the registry.\n *\n * Aligned with the core ProviderManifest (serialized form: schema as JSON Schema\n * instead of Zod, camelCase field names).\n */\nexport interface ProviderManifest {\n /** Registry entry type: provider (has bundle), recipe (MCP config), skill (lightweight) */\n type?: \"provider\" | \"recipe\" | \"skill\";\n name: string;\n description: string;\n category: string;\n /** URI template with {param} placeholders, e.g. \"s3://{bucket}/{prefix+?}\" */\n uriTemplate: string;\n /** JSON Schema describing provider parameters (serialized from Zod) */\n schema?: Record<string, unknown>;\n tags?: string[];\n /** Controlled capability tags from standard vocabulary */\n capabilityTags?: string[];\n useCases?: string[];\n /** Provider tree schema — static path structure declaration */\n treeSchema?: Record<string, unknown>;\n /** Inline AGENT.md content (for testing/static providers) */\n agentMd?: string;\n /** File path to .afs/AGENT.md — lazy-loaded on demand (from scanner) */\n agentMdPath?: string;\n}\n\n/**\n * Options for constructing an AFSRegistry provider.\n */\nexport interface AFSRegistryOptions {\n /** Static provider manifests (for testing). When provided, skips runtime scan. */\n providers?: ProviderManifest[];\n}\n\n/**\n * AFS Registry Provider — virtual file tree for discovering and mounting providers.\n *\n * File tree:\n * ```\n * /\n * ├── providers/{name}/manifest.json\n * ├── providers/{name}/README.md\n * ├── providers/{name}/.actions/mount\n * ├── by-category/{category}/{name}/\n * ├── by-tag/{tag}/{name}/\n * └── .actions/search\n * ```\n */\n/** Trim description to first sentence, max 120 chars. */\nfunction firstSentence(desc: string): string {\n const line = desc.split(\"\\n\")[0] ?? desc;\n const sentence = line.split(/\\.\\s/)[0] ?? line;\n if (sentence.length > 120) return `${sentence.slice(0, 117)}...`;\n return sentence.endsWith(\".\") ? sentence : `${sentence}.`;\n}\n\nexport class AFSRegistry extends AFSBaseProvider {\n readonly name = \"registry\";\n readonly description =\n \"AFS Provider Registry — discover and install available providers.\\n- Browse providers by name, category, or tag\\n- Read provider manifests, README docs, and configuration schemas\\n- Search providers by keyword (name, description, tags, use cases)\\n- Exec actions: `search` (full-text query), `mount` (per-provider, install to AFS)\\n- Path structure: `/providers/{name}/manifest.json`, `/by-category/{cat}`, `/by-tag/{tag}`\";\n readonly accessMode = \"readwrite\" as const;\n\n private providers: ProviderManifest[];\n private scanPromise?: Promise<void>;\n private loadProviderFn?: (\n uri: string,\n path: string,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n\n constructor(options: AFSRegistryOptions = {}) {\n super();\n if (options.providers && options.providers.length > 0) {\n this.providers = JSON.parse(JSON.stringify(options.providers));\n } else {\n this.providers = [];\n this.scanPromise = this.loadFromScan();\n }\n }\n\n private async loadFromScan(): Promise<void> {\n try {\n const { scanInstalledProviders } = await import(\"./scanner.js\");\n this.providers = await scanInstalledProviders();\n } catch {\n // Silent fallback — keep empty providers\n }\n }\n\n private async ensureLoaded(): Promise<void> {\n if (this.scanPromise) {\n await this.scanPromise;\n this.scanPromise = undefined;\n }\n }\n\n onMount(root: AFSRoot): void {\n this.loadProviderFn = (root as any).loadProvider;\n }\n\n // ── Async gate: ensure scan data is loaded before any operation ──\n\n override async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n await this.ensureLoaded();\n return super.list(path, options);\n }\n\n override async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n await this.ensureLoaded();\n return super.read(path, options);\n }\n\n override async stat(path: string, options?: AFSStatOptions): Promise<AFSStatResult> {\n await this.ensureLoaded();\n return super.stat(path, options);\n }\n\n override async search(\n path: string,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<AFSSearchResult> {\n await this.ensureLoaded();\n return super.search(path, query, options);\n }\n\n override async exec(\n path: string,\n args: Record<string, unknown>,\n options: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n await this.ensureLoaded();\n return super.exec(path, args, options);\n }\n\n override async explain(path: string, options?: AFSExplainOptions): Promise<AFSExplainResult> {\n await this.ensureLoaded();\n return super.explain(path, options);\n }\n\n // ── Indexes ──\n\n private buildByCategory(): Map<string, ProviderManifest[]> {\n const map = new Map<string, ProviderManifest[]>();\n for (const p of this.providers) {\n const list = map.get(p.category) || [];\n list.push(p);\n map.set(p.category, list);\n }\n return map;\n }\n\n private buildByTag(): Map<string, ProviderManifest[]> {\n const map = new Map<string, ProviderManifest[]>();\n for (const p of this.providers) {\n const tags = p.capabilityTags?.length ? p.capabilityTags : p.tags || [];\n for (const tag of tags) {\n const list = map.get(tag) || [];\n list.push(p);\n map.set(tag, list);\n }\n }\n return map;\n }\n\n private findProvider(name: string): ProviderManifest | undefined {\n return this.providers.find((p) => p.name === name);\n }\n\n private getRecipes(): ProviderManifest[] {\n return this.providers.filter((p) => p.type === \"recipe\");\n }\n\n private findRecipe(name: string): ProviderManifest | undefined {\n return this.getRecipes().find((p) => p.name === name);\n }\n\n /** Load AGENT.md content: inline first, then lazy-read from disk. */\n private loadAgentMd(provider: ProviderManifest): string | undefined {\n if (provider.agentMd) return provider.agentMd;\n if (!provider.agentMdPath) return undefined;\n try {\n const { readFileSync } = require(\"node:fs\") as typeof import(\"node:fs\");\n return readFileSync(provider.agentMdPath, \"utf-8\");\n } catch {\n return undefined;\n }\n }\n\n // ── List Routes ──\n\n @List(\"/\")\n async listRoot(_ctx: RouteContext) {\n return {\n data: [\n {\n id: \"providers\",\n path: \"/providers\",\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n },\n {\n id: \"by-category\",\n path: \"/by-category\",\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n },\n {\n id: \"by-tag\",\n path: \"/by-tag\",\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n },\n {\n id: \"recipes\",\n path: \"/recipes\",\n meta: { kind: \"afs:directory\", childrenCount: this.getRecipes().length },\n },\n {\n id: \".vocabulary\",\n path: \"/.vocabulary\",\n meta: { kind: \"afs:directory\", childrenCount: 2 },\n },\n ] as AFSEntry[],\n };\n }\n\n @List(\"/providers\")\n async listProviders(_ctx: RouteContext) {\n return {\n data: this.providers.map((p) => {\n // Count actual children: manifest.json, README.md, .actions (always), + optional AGENT.md, tree-schema.json\n let childrenCount = 3;\n if (p.agentMd || p.agentMdPath) childrenCount++;\n if (p.treeSchema) childrenCount++;\n\n const meta: Record<string, unknown> = {\n kind: p.type === \"recipe\" ? \"registry:recipe\" : \"registry:provider\",\n childrenCount,\n category: p.category,\n capabilityTags: p.capabilityTags,\n type: p.type || \"provider\",\n };\n\n // Surface treeSchema operations at L0 for agent filtering\n if (p.treeSchema && typeof p.treeSchema === \"object\" && \"operations\" in p.treeSchema) {\n meta.operations = (p.treeSchema as { operations: string[] }).operations;\n }\n // Surface auth type at L0 for agent filtering\n if (p.treeSchema && typeof p.treeSchema === \"object\" && \"auth\" in p.treeSchema) {\n const auth = (p.treeSchema as { auth?: { type?: string } }).auth;\n if (auth?.type) meta.authType = auth.type;\n }\n\n return {\n id: p.name,\n path: joinURL(\"/providers\", p.name),\n summary: firstSentence(p.description),\n meta,\n };\n }) as AFSEntry[],\n };\n }\n\n @List(\"/providers/:name\")\n async listProviderContents(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n const base = joinURL(\"/providers\", provider.name);\n const entries: AFSEntry[] = [\n {\n id: \"manifest.json\",\n path: joinURL(base, \"manifest.json\"),\n meta: { kind: \"afs:file\" },\n },\n {\n id: \"README.md\",\n path: joinURL(base, \"README.md\"),\n meta: { kind: \"afs:file\" },\n },\n ];\n if (provider.treeSchema) {\n entries.push({\n id: \"tree-schema.json\",\n path: joinURL(base, \"tree-schema.json\"),\n meta: { kind: \"afs:file\" },\n });\n }\n if (provider.agentMd || provider.agentMdPath) {\n entries.push({\n id: \"AGENT.md\",\n path: joinURL(base, \"AGENT.md\"),\n meta: { kind: \"afs:file\" },\n });\n }\n return { data: entries };\n }\n\n @List(\"/by-category\")\n async listCategories(_ctx: RouteContext) {\n return {\n data: Array.from(this.buildByCategory().entries()).map(([cat, providers]) => ({\n id: cat,\n path: joinURL(\"/by-category\", cat),\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-category/:category\")\n async listCategoryProviders(ctx: RouteContext<{ category: string }>) {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n data: providers.map((p) => ({\n id: p.name,\n path: joinURL(\"/by-category\", ctx.params.category, p.name),\n summary: p.description,\n meta: {\n kind: p.type === \"recipe\" ? \"registry:recipe\" : \"registry:provider\",\n childrenCount: 2,\n category: p.category,\n tags: p.tags,\n type: p.type || \"provider\",\n },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-tag\")\n async listTags(_ctx: RouteContext) {\n return {\n data: Array.from(this.buildByTag().entries()).map(([tag, providers]) => ({\n id: tag,\n path: joinURL(\"/by-tag\", tag),\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-category/:category/:name\")\n async listCategoryProviderChildren(ctx: RouteContext<{ category: string; name: string }>) {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/by-tag/:tag\")\n async listTagProviders(ctx: RouteContext<{ tag: string }>) {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n data: providers.map((p) => ({\n id: p.name,\n path: joinURL(\"/by-tag\", ctx.params.tag, p.name),\n summary: p.description,\n meta: {\n kind: p.type === \"recipe\" ? \"registry:recipe\" : \"registry:provider\",\n category: p.category,\n tags: p.tags,\n type: p.type || \"provider\",\n },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/by-tag/:tag/:name\")\n async listTagProviderChildren(ctx: RouteContext<{ tag: string; name: string }>) {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/providers/:name/manifest.json\")\n @List(\"/providers/:name/README.md\")\n @List(\"/providers/:name/tree-schema.json\")\n @List(\"/providers/:name/AGENT.md\")\n async listFileNode(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/recipes\")\n async listRecipes(_ctx: RouteContext) {\n const recipes = this.getRecipes();\n return {\n data: recipes.map((r) => ({\n id: r.name,\n path: joinURL(\"/recipes\", r.name),\n summary: r.description,\n meta: {\n kind: \"registry:recipe\",\n childrenCount: 2,\n },\n })) as AFSEntry[],\n };\n }\n\n @List(\"/recipes/:name\")\n async listRecipeContents(ctx: RouteContext<{ name: string }>) {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n const base = joinURL(\"/recipes\", recipe.name);\n return {\n data: [\n {\n id: \"manifest.json\",\n path: joinURL(base, \"manifest.json\"),\n meta: { kind: \"afs:file\" },\n },\n {\n id: \"README.md\",\n path: joinURL(base, \"README.md\"),\n meta: { kind: \"afs:file\" },\n },\n ] as AFSEntry[],\n };\n }\n\n @List(\"/recipes/:name/manifest.json\")\n @List(\"/recipes/:name/README.md\")\n async listRecipeFileNode(ctx: RouteContext<{ name: string }>) {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return { data: [] as AFSEntry[] };\n }\n\n // ── Read Routes ──\n\n @Read(\"/\")\n async readRoot(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"/\",\n path: \"/\",\n content: { type: \"registry\", providerCount: this.providers.length },\n meta: { kind: \"registry:root\", childrenCount: 5 },\n };\n }\n\n @Read(\"/providers\")\n async readProviders(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"providers\",\n path: \"/providers\",\n content: { type: \"directory\", count: this.providers.length },\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n };\n }\n\n @Read(\"/providers/:name\")\n async readProvider(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: joinURL(\"/providers\", provider.name),\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\", childrenCount: 2 },\n };\n }\n\n @Read(\"/providers/:name/manifest.json\")\n async readManifest(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \"manifest.json\",\n path: ctx.path,\n content: { ...provider },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/providers/:name/README.md\")\n async readReadme(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const lines = [\n `# ${provider.name}`,\n \"\",\n provider.description,\n \"\",\n `**Category:** ${provider.category}`,\n `**URI Template:** \\`${provider.uriTemplate}\\``,\n ];\n\n if (provider.schema) {\n const props = (provider.schema as any).properties as\n | Record<string, { type?: string; description?: string }>\n | undefined;\n const required = new Set(((provider.schema as any).required as string[]) ?? []);\n if (props) {\n lines.push(\"\", \"## Configuration\", \"\");\n for (const [key, val] of Object.entries(props)) {\n const req = required.has(key) ? \" **(required)**\" : \"\";\n lines.push(`- \\`${key}\\` (${val.type ?? \"string\"})${req} — ${val.description ?? \"\"}`);\n }\n }\n }\n\n if (provider.tags?.length) {\n lines.push(\"\", `**Tags:** ${provider.tags.join(\", \")}`);\n }\n if (provider.useCases?.length) {\n lines.push(\"\", `## Use Cases`, \"\", ...provider.useCases.map((u) => `- ${u}`));\n }\n lines.push(\"\");\n\n return {\n id: \"README.md\",\n path: ctx.path,\n content: lines.join(\"\\n\"),\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/providers/:name/tree-schema.json\")\n async readTreeSchema(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n if (!provider.treeSchema) throw new AFSNotFoundError(ctx.path);\n return {\n id: \"tree-schema.json\",\n path: ctx.path,\n content: provider.treeSchema,\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/providers/:name/AGENT.md\")\n async readAgentMd(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n const content = this.loadAgentMd(provider);\n if (!content) throw new AFSNotFoundError(ctx.path);\n return {\n id: \"AGENT.md\",\n path: ctx.path,\n content,\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/by-category\")\n async readByCategory(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"by-category\",\n path: \"/by-category\",\n content: { type: \"directory\", count: this.buildByCategory().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n };\n }\n\n @Read(\"/by-category/:category\")\n async readCategory(ctx: RouteContext<{ category: string }>): Promise<AFSEntry | undefined> {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: ctx.params.category,\n path: joinURL(\"/by-category\", ctx.params.category),\n content: { type: \"category\", count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Read(\"/by-category/:category/:name\")\n async readCategoryProvider(\n ctx: RouteContext<{ category: string; name: string }>,\n ): Promise<AFSEntry | undefined> {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: ctx.path,\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Read(\"/by-tag\")\n async readByTag(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"by-tag\",\n path: \"/by-tag\",\n content: { type: \"directory\", count: this.buildByTag().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n };\n }\n\n @Read(\"/by-tag/:tag\")\n async readTag(ctx: RouteContext<{ tag: string }>): Promise<AFSEntry | undefined> {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: ctx.params.tag,\n path: joinURL(\"/by-tag\", ctx.params.tag),\n content: { type: \"tag\", count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Read(\"/by-tag/:tag/:name\")\n async readTagProvider(\n ctx: RouteContext<{ tag: string; name: string }>,\n ): Promise<AFSEntry | undefined> {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: provider.name,\n path: ctx.path,\n content: { type: \"provider\", name: provider.name, description: provider.description },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Read(\"/recipes\")\n async readRecipes(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const recipes = this.getRecipes();\n return {\n id: \"recipes\",\n path: \"/recipes\",\n content: { type: \"directory\", count: recipes.length },\n meta: { kind: \"afs:directory\", childrenCount: recipes.length },\n };\n }\n\n @Read(\"/recipes/:name\")\n async readRecipe(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return {\n id: recipe.name,\n path: joinURL(\"/recipes\", recipe.name),\n content: { type: \"recipe\", name: recipe.name, description: recipe.description },\n meta: { kind: \"registry:recipe\", childrenCount: 2 },\n };\n }\n\n @Read(\"/recipes/:name/manifest.json\")\n async readRecipeManifest(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return {\n id: \"manifest.json\",\n path: ctx.path,\n content: { ...recipe },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/recipes/:name/README.md\")\n async readRecipeReadme(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n\n const lines = [\n `# ${recipe.name}`,\n \"\",\n recipe.description,\n \"\",\n `**Category:** ${recipe.category}`,\n `**URI:** \\`${recipe.uriTemplate}\\``,\n ];\n if (recipe.tags?.length) {\n lines.push(\"\", `**Tags:** ${recipe.tags.join(\", \")}`);\n }\n lines.push(\"\");\n\n return {\n id: \"README.md\",\n path: ctx.path,\n content: lines.join(\"\\n\"),\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: {\n operations: {\n list: true,\n read: true,\n write: false,\n delete: false,\n exec: true,\n stat: true,\n explain: true,\n search: true,\n },\n },\n meta: { kind: \"afs:capabilities\" },\n };\n }\n\n // ── Vocabulary Routes ──\n\n @List(\"/.vocabulary/categories\")\n @List(\"/.vocabulary/tags\")\n async listVocabularyLeaf(_ctx: RouteContext) {\n return { data: [] as AFSEntry[] };\n }\n\n @List(\"/.vocabulary\")\n async listVocabulary(_ctx: RouteContext) {\n return {\n data: [\n {\n id: \"categories\",\n path: \"/.vocabulary/categories\",\n meta: { kind: \"registry:vocabulary\", childrenCount: AFS_CATEGORIES.length },\n },\n {\n id: \"tags\",\n path: \"/.vocabulary/tags\",\n meta: { kind: \"registry:vocabulary\", childrenCount: CAPABILITY_TAGS.length },\n },\n ] as AFSEntry[],\n };\n }\n\n @Read(\"/.vocabulary\")\n async readVocabulary(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n return {\n id: \".vocabulary\",\n path: \"/.vocabulary\",\n content:\n \"# AFS Controlled Vocabulary\\n\\n- categories — provider classification (single-select)\\n- tags — capability tags (multi-select)\\n\",\n meta: { kind: \"afs:directory\", childrenCount: 2 },\n };\n }\n\n @Read(\"/.vocabulary/categories\")\n async readVocabularyCategories(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const lines = AFS_CATEGORIES.map((c) => `- ${c}`).join(\"\\n\");\n return {\n id: \"categories\",\n path: \"/.vocabulary/categories\",\n content: `# AFS Provider Categories\\n\\nControlled vocabulary — single-select per provider.\\n\\n${lines}\\n`,\n meta: { kind: \"registry:vocabulary\" },\n };\n }\n\n @Read(\"/.vocabulary/tags\")\n async readVocabularyTags(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const lines = CAPABILITY_TAGS.map((t) => `- ${t}`).join(\"\\n\");\n return {\n id: \"tags\",\n path: \"/.vocabulary/tags\",\n content: `# AFS Capability Tags\\n\\nControlled vocabulary — multi-select per provider.\\n\\n${lines}\\n`,\n meta: { kind: \"registry:vocabulary\" },\n };\n }\n\n // ── Meta Routes ──\n\n @Meta(\"/\")\n async rootMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/.meta\",\n content: {\n providerCount: this.providers.length,\n categories: Array.from(this.buildByCategory().keys()),\n tags: Array.from(this.buildByTag().keys()),\n },\n meta: {\n kind: \"registry:root\",\n childrenCount: 5,\n },\n };\n }\n\n @Meta(\"/recipes\")\n async recipesMeta(_ctx: RouteContext): Promise<AFSEntry> {\n const recipes = this.getRecipes();\n return {\n id: \".meta\",\n path: \"/recipes/.meta\",\n content: { count: recipes.length },\n meta: { kind: \"afs:directory\", childrenCount: recipes.length },\n };\n }\n\n @Meta(\"/recipes/:name\")\n async recipeMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/recipes\", recipe.name, \".meta\"),\n content: { name: recipe.name, category: recipe.category },\n meta: { kind: \"registry:recipe\", childrenCount: 2 },\n };\n }\n\n @Meta(\"/recipes/:name/manifest.json\")\n async recipeManifestMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/recipes\", recipe.name, \"manifest.json\", \".meta\"),\n content: { format: \"json\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/recipes/:name/README.md\")\n async recipeReadmeMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/recipes\", recipe.name, \"README.md\", \".meta\"),\n content: { format: \"markdown\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/providers\")\n async providersMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/providers/.meta\",\n content: { count: this.providers.length },\n meta: { kind: \"afs:directory\", childrenCount: this.providers.length },\n };\n }\n\n @Meta(\"/providers/:name\")\n async providerMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \".meta\"),\n content: {\n name: provider.name,\n category: provider.category,\n uriTemplate: provider.uriTemplate,\n },\n meta: { kind: \"registry:provider\", childrenCount: 2 },\n };\n }\n\n @Meta(\"/providers/:name/manifest.json\")\n async manifestMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"manifest.json\", \".meta\"),\n content: { format: \"json\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/providers/:name/README.md\")\n async readmeMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"README.md\", \".meta\"),\n content: { format: \"markdown\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/providers/:name/tree-schema.json\")\n async treeSchemaJsonMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"tree-schema.json\", \".meta\"),\n content: { format: \"json\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/providers/:name/AGENT.md\")\n async agentMdMeta(ctx: RouteContext<{ name: string }>): Promise<AFSEntry> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/providers\", provider.name, \"AGENT.md\", \".meta\"),\n content: { format: \"markdown\" },\n meta: { kind: \"afs:file\" },\n };\n }\n\n @Meta(\"/by-category\")\n async byCategoryMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/by-category/.meta\",\n content: { count: this.buildByCategory().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByCategory().size },\n };\n }\n\n @Meta(\"/by-category/:category\")\n async categoryMeta(ctx: RouteContext<{ category: string }>): Promise<AFSEntry> {\n const providers = this.buildByCategory().get(ctx.params.category);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-category\", ctx.params.category, \".meta\"),\n content: { category: ctx.params.category, count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Meta(\"/by-category/:category/:name\")\n async categoryProviderMeta(\n ctx: RouteContext<{ category: string; name: string }>,\n ): Promise<AFSEntry> {\n const providers = this.buildByCategory().get(ctx.params.category);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-category\", ctx.params.category, provider.name, \".meta\"),\n content: { name: provider.name },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Meta(\"/by-tag\")\n async byTagMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/by-tag/.meta\",\n content: { count: this.buildByTag().size },\n meta: { kind: \"afs:directory\", childrenCount: this.buildByTag().size },\n };\n }\n\n @Meta(\"/by-tag/:tag\")\n async tagMeta(ctx: RouteContext<{ tag: string }>): Promise<AFSEntry> {\n const providers = this.buildByTag().get(ctx.params.tag);\n if (!providers) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-tag\", ctx.params.tag, \".meta\"),\n content: { tag: ctx.params.tag, count: providers.length },\n meta: { kind: \"afs:directory\", childrenCount: providers.length },\n };\n }\n\n @Meta(\"/by-tag/:tag/:name\")\n async tagProviderMeta(ctx: RouteContext<{ tag: string; name: string }>): Promise<AFSEntry> {\n const providers = this.buildByTag().get(ctx.params.tag);\n const provider = providers?.find((p) => p.name === ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n return {\n id: \".meta\",\n path: joinURL(\"/by-tag\", ctx.params.tag, provider.name, \".meta\"),\n content: { name: provider.name },\n meta: { kind: \"registry:provider\" },\n };\n }\n\n @Meta(\"/.vocabulary\")\n async vocabularyMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/.vocabulary/.meta\",\n content: { childrenCount: 2 },\n meta: { kind: \"afs:directory\" },\n };\n }\n\n @Meta(\"/.vocabulary/categories\")\n async vocabularyCategoriesMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/.vocabulary/categories/.meta\",\n content: { count: AFS_CATEGORIES.length },\n meta: { kind: \"registry:vocabulary\" },\n };\n }\n\n @Meta(\"/.vocabulary/tags\")\n async vocabularyTagsMeta(_ctx: RouteContext): Promise<AFSEntry> {\n return {\n id: \".meta\",\n path: \"/.vocabulary/tags/.meta\",\n content: { count: CAPABILITY_TAGS.length },\n meta: { kind: \"registry:vocabulary\" },\n };\n }\n\n // ── Actions Routes ──\n\n @Actions(\"/\")\n async listRootActions(_ctx: RouteContext) {\n return {\n data: [\n {\n id: \"search\",\n path: \"/.actions/search\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n },\n actions: [\n {\n name: \"search\",\n description:\n \"Search for providers. Use category/tags for structured filtering, query for full-text search.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Full-text search across name, description, tags\",\n },\n category: {\n type: \"string\",\n description: \"Exact category match (e.g. storage, database, messaging)\",\n },\n tags: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Filter by tags — providers must have ALL specified tags\",\n },\n type: {\n type: \"string\",\n enum: [\"provider\", \"recipe\"],\n description: \"Filter by entry type\",\n },\n },\n },\n },\n ],\n },\n ] as AFSEntry[],\n };\n }\n\n @Actions.Exec(\"/\", \"search\")\n async searchProviders(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult> {\n const query = (args.query as string) || \"\";\n const filterCategory = args.category as string | undefined;\n const filterTags = args.tags as string[] | undefined;\n const filterType = args.type as string | undefined;\n\n let matched = [...this.providers];\n\n // Structured filters (exact match)\n if (filterCategory) {\n matched = matched.filter((p) => p.category === filterCategory);\n }\n if (filterTags && filterTags.length > 0) {\n matched = matched.filter((p) => {\n const caps = p.capabilityTags || [];\n return filterTags.every((t) => caps.includes(t));\n });\n }\n if (filterType) {\n matched = matched.filter((p) => (p.type || \"provider\") === filterType);\n }\n\n // Full-text search on remaining results\n if (query) {\n const q = query.toLowerCase();\n matched = matched.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.category.toLowerCase().includes(q) ||\n (p.tags || []).some((t) => t.toLowerCase().includes(q)) ||\n (p.capabilityTags || []).some((t) => t.toLowerCase().includes(q)) ||\n (p.useCases || []).some((u) => u.toLowerCase().includes(q)),\n );\n }\n\n return {\n success: true,\n data: {\n query,\n ...(filterCategory ? { category: filterCategory } : {}),\n ...(filterTags ? { tags: filterTags } : {}),\n ...(filterType ? { type: filterType } : {}),\n count: matched.length,\n providers: matched.map((p) => ({\n name: p.name,\n category: p.category,\n capabilityTags: p.capabilityTags,\n type: p.type || \"provider\",\n description: firstSentence(p.description),\n })),\n },\n };\n }\n\n /**\n * Build mount action inputSchema for a provider\n */\n private buildMountSchema(provider: ProviderManifest): Record<string, unknown> {\n return {\n type: \"object\",\n properties: {\n path: { type: \"string\", description: \"Mount path (default: /{provider-name})\" },\n uri: {\n type: \"string\",\n description: `Full provider URI (overrides template). Template: ${provider.uriTemplate}`,\n },\n accessMode: {\n type: \"string\",\n enum: [\"readonly\", \"readwrite\"],\n description: \"Access mode (default: readonly)\",\n },\n auth: { type: \"string\", description: \"Authentication token\" },\n description: { type: \"string\", description: \"Human-readable description\" },\n scope: {\n type: \"string\",\n enum: [\"cwd\", \"project\", \"user\"],\n description:\n \"Where to persist the mount config. 'cwd' (default) = current directory, 'project' = project root (.git), 'user' = user home\",\n },\n sensitiveArgs: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Field names that should be treated as sensitive credentials (stored in credentials.toml instead of config.toml)\",\n },\n ...((provider.schema as any)?.properties ?? {}),\n },\n required: [...((provider.schema as any)?.required ?? [])],\n };\n }\n\n @Actions(\"/recipes/:name\")\n async listRecipeActions(ctx: RouteContext<{ name: string }>) {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description: `Mount path (default: /modules/${recipe.name})`,\n },\n uri: {\n type: \"string\",\n description: `Full MCP URI (default: ${recipe.uriTemplate})`,\n },\n accessMode: {\n type: \"string\",\n enum: [\"readonly\", \"readwrite\"],\n description: \"Access mode (default: readonly)\",\n },\n description: { type: \"string\", description: \"Human-readable description\" },\n },\n };\n\n return {\n data: [\n {\n id: \"mount\",\n path: joinURL(\"/recipes\", recipe.name, \".actions\", \"mount\"),\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n description: `Mount the ${recipe.name} recipe`,\n inputSchema: mountSchema,\n },\n actions: [\n {\n name: \"mount\",\n description: `Mount the ${recipe.name} recipe`,\n inputSchema: mountSchema,\n },\n ],\n },\n ] as AFSEntry[],\n };\n }\n\n @Read(\"/recipes/:name/.actions/mount\")\n async readRecipeMountAction(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = {\n type: \"object\",\n properties: {\n path: {\n type: \"string\",\n description: `Mount path (default: /modules/${recipe.name})`,\n },\n uri: {\n type: \"string\",\n description: `Full MCP URI (default: ${recipe.uriTemplate})`,\n },\n },\n };\n\n return {\n id: \"mount\",\n path: joinURL(\"/recipes\", recipe.name, \".actions\", \"mount\"),\n content: {\n description: `Mount the ${recipe.name} recipe`,\n inputSchema: mountSchema,\n },\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n description: `Mount the ${recipe.name} recipe`,\n inputSchema: mountSchema,\n },\n };\n }\n\n @Actions.Exec(\"/recipes/:name\", \"mount\")\n async mountRecipe(\n ctx: RouteContext<{ name: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n\n if (!this.loadProviderFn) {\n throw new Error(\"loadProvider not configured — Registry was not mounted on an AFS instance\");\n }\n\n const mountPath =\n typeof args.path === \"string\" && args.path.trim() !== \"\"\n ? args.path.trim()\n : `/modules/${recipe.name}`;\n const uri =\n typeof args.uri === \"string\" && args.uri.trim() !== \"\" ? args.uri.trim() : recipe.uriTemplate;\n\n const { path: _path, uri: _uri, ...options } = args;\n\n await this.loadProviderFn(\n uri,\n mountPath,\n Object.keys(options).length > 0 ? options : undefined,\n );\n\n return {\n success: true,\n data: {\n recipe: recipe.name,\n uri,\n path: mountPath,\n },\n };\n }\n\n @Actions(\"/providers/:name\")\n async listProviderActions(ctx: RouteContext<{ name: string }>) {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = this.buildMountSchema(provider);\n\n return {\n data: [\n {\n id: \"mount\",\n path: joinURL(\"/providers\", provider.name, \".actions\", \"mount\"),\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n actions: [\n {\n name: \"mount\",\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n ],\n },\n ] as AFSEntry[],\n };\n }\n\n @Read(\"/providers/:name/.actions/mount\")\n async readMountAction(ctx: RouteContext<{ name: string }>): Promise<AFSEntry | undefined> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n const mountSchema = this.buildMountSchema(provider);\n return {\n id: \"mount\",\n path: joinURL(\"/providers\", provider.name, \".actions\", \"mount\"),\n content: {\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n description: `Mount the ${provider.name} provider`,\n inputSchema: mountSchema,\n },\n };\n }\n\n @Actions.Exec(\"/providers/:name\", \"mount\")\n async mountProvider(\n ctx: RouteContext<{ name: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n if (!this.loadProviderFn) {\n throw new Error(\"loadProvider not configured — Registry was not mounted on an AFS instance\");\n }\n\n // Default path to /{provider.name} if not provided\n const mountPath =\n typeof args.path === \"string\" && args.path.trim() !== \"\"\n ? args.path.trim()\n : `/${provider.name}`;\n let uri = args.uri as string | undefined;\n\n if (!uri) {\n // Build URI from template using provided args.\n // Missing optional vars are omitted; missing required vars produce\n // a partial URI (e.g. \"cloudflare://\") that the credential resolver\n // will complete after interactive collection.\n const varNames = getTemplateVariableNames(provider.uriTemplate);\n const vars: Record<string, string | undefined> = {};\n for (const name of varNames) {\n const value = args[name];\n vars[name] = value != null ? String(value) : undefined;\n }\n try {\n uri = buildURI(provider.uriTemplate, vars);\n } catch {\n // Required vars missing — build a minimal scheme:// URI\n // so the credential resolver can still identify the provider\n const scheme = provider.uriTemplate.split(\"://\")[0];\n uri = `${scheme}://`;\n }\n }\n\n // Pass all args except path/uri as options (includes accessMode, auth, description, and provider-specific params)\n const { path: _path, uri: _uri, sensitiveArgs, ...options } = args;\n // Attach _sensitiveArgs annotation so credential resolver can build ad-hoc schema\n if (Array.isArray(sensitiveArgs) && sensitiveArgs.length > 0) {\n options._sensitiveArgs = sensitiveArgs;\n }\n\n await this.loadProviderFn(\n uri,\n mountPath,\n Object.keys(options).length > 0 ? options : undefined,\n );\n\n return {\n success: true,\n data: {\n provider: provider.name,\n uri,\n path: mountPath,\n },\n };\n }\n\n // ── Search Route ──\n\n @Search(\"/\")\n async searchRoot(\n _ctx: RouteContext,\n query: string,\n options?: { limit?: number },\n ): Promise<AFSSearchResult> {\n const q = query.toLowerCase();\n let matched = this.providers.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.category.toLowerCase().includes(q) ||\n p.uriTemplate.toLowerCase().includes(q) ||\n (p.tags || []).some((t) => t.toLowerCase().includes(q)) ||\n (p.capabilityTags || []).some((t) => t.toLowerCase().includes(q)) ||\n (p.useCases || []).some((u) => u.toLowerCase().includes(q)),\n );\n if (options?.limit !== undefined && matched.length > options.limit) {\n matched = matched.slice(0, options.limit);\n }\n return {\n data: matched.map((p) => ({\n id: p.name,\n path: joinURL(\"/providers\", p.name),\n summary: firstSentence(p.description),\n meta: { kind: \"registry:provider\", category: p.category, capabilityTags: p.capabilityTags },\n })),\n };\n }\n\n // ── Explain Routes ──\n\n @Explain(\"/providers/:name\")\n async explainProvider(ctx: RouteContext<{ name: string }>): Promise<AFSExplainResult> {\n const provider = this.findProvider(ctx.params.name);\n if (!provider) throw new AFSNotFoundError(ctx.path);\n\n // If AGENT.md exists, use it as the primary explain content (agent-optimized)\n const agentMd = this.loadAgentMd(provider);\n if (agentMd) {\n const lines = [agentMd];\n\n // Append configuration section if schema exists (not in AGENT.md)\n if (provider.schema) {\n const props = (provider.schema as any).properties as\n | Record<string, { type?: string; description?: string }>\n | undefined;\n const required = new Set(((provider.schema as any).required as string[]) ?? []);\n if (props) {\n lines.push(\"\", \"## Configuration\", \"\");\n for (const [key, val] of Object.entries(props)) {\n const req = required.has(key) ? \" **(required)**\" : \"\";\n lines.push(`- \\`${key}\\` (${val.type ?? \"string\"})${req} — ${val.description ?? \"\"}`);\n }\n }\n }\n\n lines.push(\"\", \"## Actions\", \"\", \"- `mount` — Mount this provider into AFS\");\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // Fallback: generate explain from manifest metadata\n const lines = [\n `# ${provider.name}`,\n \"\",\n provider.description,\n \"\",\n `**Category:** ${provider.category}`,\n `**URI Template:** \\`${provider.uriTemplate}\\``,\n `**Type:** ${provider.type || \"provider\"}`,\n ];\n\n if (provider.tags?.length) {\n lines.push(`**Tags:** ${provider.tags.join(\", \")}`);\n }\n if (provider.useCases?.length) {\n lines.push(\"\", \"## Use Cases\", \"\", ...provider.useCases.map((u) => `- ${u}`));\n }\n\n if (provider.schema) {\n const props = (provider.schema as any).properties as\n | Record<string, { type?: string; description?: string }>\n | undefined;\n const required = new Set(((provider.schema as any).required as string[]) ?? []);\n if (props) {\n lines.push(\"\", \"## Configuration\", \"\");\n for (const [key, val] of Object.entries(props)) {\n const req = required.has(key) ? \" **(required)**\" : \"\";\n lines.push(`- \\`${key}\\` (${val.type ?? \"string\"})${req} — ${val.description ?? \"\"}`);\n }\n }\n }\n\n lines.push(\"\", \"## Actions\", \"\", \"- `mount` — Mount this provider into AFS\");\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n @Explain(\"/recipes/:name\")\n async explainRecipe(ctx: RouteContext<{ name: string }>): Promise<AFSExplainResult> {\n const recipe = this.findRecipe(ctx.params.name);\n if (!recipe) throw new AFSNotFoundError(ctx.path);\n\n const lines = [\n `# ${recipe.name} (recipe)`,\n \"\",\n recipe.description,\n \"\",\n `**Category:** ${recipe.category}`,\n `**URI:** \\`${recipe.uriTemplate}\\``,\n `**Type:** recipe`,\n ];\n\n if (recipe.tags?.length) {\n lines.push(`**Tags:** ${recipe.tags.join(\", \")}`);\n }\n\n lines.push(\n \"\",\n \"## Actions\",\n \"\",\n \"- `mount` — Mount this recipe as an MCP provider\",\n \"\",\n \"*Note: Recipe capabilities depend on the external MCP server and cannot be verified until mounted.*\",\n );\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n @Explain(\"/:path*\")\n async explainFallback(ctx: RouteContext): Promise<AFSExplainResult> {\n // Root path — return registry overview\n if (ctx.path === \"/\" || ctx.path === \"\") {\n const categories = Array.from(this.buildByCategory().keys()).sort();\n return {\n format: \"markdown\",\n content: [\n \"# AFS Provider Registry\",\n \"\",\n \"Virtual file tree for discovering and mounting AFS providers.\",\n \"\",\n \"## Structure\",\n \"- `/providers/{name}/` — Provider details (manifest.json, README.md, .actions/mount)\",\n \"- `/by-category/{category}/` — Browse by category\",\n \"- `/by-tag/{tag}/` — Browse by tag\",\n \"- `/recipes/{name}/` — MCP recipe details\",\n \"- `/.actions/search` — Search with structured filters (category, tags, query)\",\n \"\",\n `**Providers:** ${this.providers.filter((p) => (p.type || \"provider\") === \"provider\").length}`,\n `**Recipes:** ${this.getRecipes().length}`,\n `**Categories:** ${categories.join(\", \")}`,\n ].join(\"\\n\"),\n };\n }\n\n return {\n format: \"markdown\",\n content: [\n \"# AFS Provider Registry\",\n \"\",\n \"Use `explain /registry/providers/{name}` for provider-specific information.\",\n \"Use `search` action with `category` or `tags` params for structured discovery.\",\n ].join(\"\\n\"),\n };\n }\n\n // ── Stat Route ──\n\n @Stat(\"/\")\n @Stat(\"/providers\")\n @Stat(\"/providers/:name\")\n @Stat(\"/providers/:name/manifest.json\")\n @Stat(\"/providers/:name/README.md\")\n @Stat(\"/providers/:name/tree-schema.json\")\n @Stat(\"/providers/:name/AGENT.md\")\n @Stat(\"/by-category\")\n @Stat(\"/by-category/:category\")\n @Stat(\"/by-category/:category/:name\")\n @Stat(\"/by-tag\")\n @Stat(\"/by-tag/:tag\")\n @Stat(\"/by-tag/:tag/:name\")\n @Stat(\"/recipes\")\n @Stat(\"/recipes/:name\")\n @Stat(\"/recipes/:name/manifest.json\")\n @Stat(\"/recipes/:name/README.md\")\n @Stat(\"/recipes/:name/.actions/mount\")\n @Stat(\"/.vocabulary\")\n @Stat(\"/.vocabulary/categories\")\n @Stat(\"/.vocabulary/tags\")\n async statPath(ctx: RouteContext): Promise<AFSStatResult> {\n // Delegate to read to get actual entry data\n const readResult = await this.read(ctx.path);\n if (readResult.data) {\n return { data: readResult.data };\n }\n throw new AFSNotFoundError(ctx.path);\n }\n}\n\nexport { clearScanCache, scanInstalledProviders } from \"./scanner.js\";\n"],"mappings":"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"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
//#region rolldown:runtime
|
|
4
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/scanner.ts
|
|
8
|
+
/** Packages that are NOT providers (infrastructure, tooling). */
|
|
9
|
+
const EXCLUDED_PACKAGES = new Set([
|
|
10
|
+
"@aigne/afs",
|
|
11
|
+
"@aigne/afs-testing",
|
|
12
|
+
"@aigne/afs-explorer",
|
|
13
|
+
"@aigne/afs-registry",
|
|
14
|
+
"@aigne/afs-http",
|
|
15
|
+
"@aigne/afs-cli",
|
|
16
|
+
"@aigne/afs-mapping",
|
|
17
|
+
"@aigne/afs-compute-abstraction",
|
|
18
|
+
"@aigne/afs-world-mapping",
|
|
19
|
+
"@aigne/afs-domain-action",
|
|
20
|
+
"@aigne/afs-session"
|
|
21
|
+
]);
|
|
22
|
+
/** Cached scan result — populated after first successful scan. */
|
|
23
|
+
let cachedResult;
|
|
24
|
+
/** Disk cache file name. */
|
|
25
|
+
const CACHE_FILE = "scan-cache.json";
|
|
26
|
+
/**
|
|
27
|
+
* Scan installed @aigne/afs-* packages and collect their manifests.
|
|
28
|
+
*
|
|
29
|
+
* Resolution strategies (tried in order):
|
|
30
|
+
* 1. Workspace mode: find pnpm-workspace.yaml, scan providers/ and packages/ dirs
|
|
31
|
+
* 2. node_modules mode: find @aigne scope dir in node_modules, scan afs-* subdirs
|
|
32
|
+
*
|
|
33
|
+
* Results are cached in memory + on disk. Disk cache is invalidated when
|
|
34
|
+
* the lockfile (pnpm-lock.yaml or package-lock.json) changes.
|
|
35
|
+
*/
|
|
36
|
+
async function scanInstalledProviders() {
|
|
37
|
+
if (cachedResult) return cachedResult;
|
|
38
|
+
const diskHit = readDiskCache();
|
|
39
|
+
if (diskHit) {
|
|
40
|
+
cachedResult = diskHit;
|
|
41
|
+
return diskHit;
|
|
42
|
+
}
|
|
43
|
+
const results = [];
|
|
44
|
+
const packageDirs = findAignePackages();
|
|
45
|
+
for (const { packageName, packageDir } of packageDirs) {
|
|
46
|
+
if (EXCLUDED_PACKAGES.has(packageName)) continue;
|
|
47
|
+
try {
|
|
48
|
+
const manifests = await importAndExtractManifests(packageDir);
|
|
49
|
+
for (const m of manifests) results.push({
|
|
50
|
+
type: m.type ?? "provider",
|
|
51
|
+
name: m.name,
|
|
52
|
+
description: m.description,
|
|
53
|
+
category: m.category,
|
|
54
|
+
uriTemplate: m.uriTemplate,
|
|
55
|
+
tags: m.tags,
|
|
56
|
+
capabilityTags: m.capabilityTags,
|
|
57
|
+
useCases: m.useCases,
|
|
58
|
+
schema: convertZodToJsonSchema(m.schema),
|
|
59
|
+
treeSchema: m.treeSchema,
|
|
60
|
+
agentMdPath: m.agentMdPath
|
|
61
|
+
});
|
|
62
|
+
} catch {}
|
|
63
|
+
}
|
|
64
|
+
cachedResult = results;
|
|
65
|
+
writeDiskCache(results);
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Clear the cached scan result (memory + disk). Useful for testing or forced re-scan.
|
|
70
|
+
*/
|
|
71
|
+
function clearScanCache() {
|
|
72
|
+
cachedResult = void 0;
|
|
73
|
+
deleteDiskCache();
|
|
74
|
+
}
|
|
75
|
+
function getCacheDir() {
|
|
76
|
+
const { join } = __require("node:path");
|
|
77
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
78
|
+
if (!home) return void 0;
|
|
79
|
+
return join(home, ".afs-config");
|
|
80
|
+
}
|
|
81
|
+
function getLockfileMtime() {
|
|
82
|
+
const { statSync, existsSync } = __require("node:fs");
|
|
83
|
+
const { join, dirname } = __require("node:path");
|
|
84
|
+
let dir = process.cwd();
|
|
85
|
+
for (let i = 0; i < 10; i++) {
|
|
86
|
+
for (const name of [
|
|
87
|
+
"pnpm-lock.yaml",
|
|
88
|
+
"package-lock.json",
|
|
89
|
+
"yarn.lock"
|
|
90
|
+
]) {
|
|
91
|
+
const p = join(dir, name);
|
|
92
|
+
if (existsSync(p)) try {
|
|
93
|
+
return statSync(p).mtimeMs;
|
|
94
|
+
} catch {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const parent = dirname(dir);
|
|
99
|
+
if (parent === dir) break;
|
|
100
|
+
dir = parent;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function readDiskCache() {
|
|
104
|
+
const { existsSync, readFileSync } = __require("node:fs");
|
|
105
|
+
const { join } = __require("node:path");
|
|
106
|
+
const cacheDir = getCacheDir();
|
|
107
|
+
if (!cacheDir) return void 0;
|
|
108
|
+
const cachePath = join(cacheDir, CACHE_FILE);
|
|
109
|
+
if (!existsSync(cachePath)) return void 0;
|
|
110
|
+
try {
|
|
111
|
+
const data = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
112
|
+
const lockMtime = getLockfileMtime();
|
|
113
|
+
if (lockMtime !== void 0 && data.lockMtime === lockMtime && Array.isArray(data.providers)) return data.providers;
|
|
114
|
+
} catch {}
|
|
115
|
+
}
|
|
116
|
+
function writeDiskCache(providers) {
|
|
117
|
+
const { mkdirSync, writeFileSync } = __require("node:fs");
|
|
118
|
+
const { join } = __require("node:path");
|
|
119
|
+
const cacheDir = getCacheDir();
|
|
120
|
+
if (!cacheDir) return;
|
|
121
|
+
const lockMtime = getLockfileMtime();
|
|
122
|
+
if (lockMtime === void 0) return;
|
|
123
|
+
try {
|
|
124
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
125
|
+
const data = {
|
|
126
|
+
lockMtime,
|
|
127
|
+
providers
|
|
128
|
+
};
|
|
129
|
+
writeFileSync(join(cacheDir, CACHE_FILE), JSON.stringify(data), "utf-8");
|
|
130
|
+
} catch {}
|
|
131
|
+
}
|
|
132
|
+
function deleteDiskCache() {
|
|
133
|
+
const { unlinkSync, existsSync } = __require("node:fs");
|
|
134
|
+
const { join } = __require("node:path");
|
|
135
|
+
const cacheDir = getCacheDir();
|
|
136
|
+
if (!cacheDir) return;
|
|
137
|
+
const cachePath = join(cacheDir, CACHE_FILE);
|
|
138
|
+
try {
|
|
139
|
+
if (existsSync(cachePath)) unlinkSync(cachePath);
|
|
140
|
+
} catch {}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Find all @aigne/afs-* package directories.
|
|
144
|
+
* Tries workspace mode first, then falls back to node_modules scanning.
|
|
145
|
+
*/
|
|
146
|
+
function findAignePackages() {
|
|
147
|
+
const wsPackages = findWorkspacePackages();
|
|
148
|
+
if (wsPackages.length > 0) return wsPackages;
|
|
149
|
+
return findNodeModulesPackages();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Find @aigne/afs-* packages in a pnpm/npm workspace by walking up to find
|
|
153
|
+
* workspace root (pnpm-workspace.yaml or root package.json with workspaces),
|
|
154
|
+
* then scanning the listed workspace directories.
|
|
155
|
+
*/
|
|
156
|
+
function findWorkspacePackages() {
|
|
157
|
+
const { existsSync, readFileSync, readdirSync } = __require("node:fs");
|
|
158
|
+
const { join, dirname } = __require("node:path");
|
|
159
|
+
const results = [];
|
|
160
|
+
let dir = process.cwd();
|
|
161
|
+
let workspaceRoot;
|
|
162
|
+
for (let i = 0; i < 10; i++) {
|
|
163
|
+
if (existsSync(join(dir, "pnpm-workspace.yaml"))) {
|
|
164
|
+
workspaceRoot = dir;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
if (existsSync(join(dir, "package.json"))) try {
|
|
168
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf-8"));
|
|
169
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
170
|
+
workspaceRoot = dir;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
} catch {}
|
|
174
|
+
const parent = dirname(dir);
|
|
175
|
+
if (parent === dir) break;
|
|
176
|
+
dir = parent;
|
|
177
|
+
}
|
|
178
|
+
if (!workspaceRoot) return results;
|
|
179
|
+
for (const scanDir of ["providers", "packages"]) {
|
|
180
|
+
const fullDir = join(workspaceRoot, scanDir);
|
|
181
|
+
if (!existsSync(fullDir)) continue;
|
|
182
|
+
const entries = readdirSync(fullDir);
|
|
183
|
+
for (const entry of entries) {
|
|
184
|
+
const pkgJsonPath = join(fullDir, entry, "package.json");
|
|
185
|
+
if (!existsSync(pkgJsonPath)) continue;
|
|
186
|
+
try {
|
|
187
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
188
|
+
if (pkg.name?.startsWith("@aigne/afs-")) results.push({
|
|
189
|
+
packageName: pkg.name,
|
|
190
|
+
packageDir: join(fullDir, entry)
|
|
191
|
+
});
|
|
192
|
+
} catch {}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return results;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Find @aigne/afs-* packages by scanning node_modules/@aigne/ directory.
|
|
199
|
+
* Used in production when packages are installed as npm dependencies.
|
|
200
|
+
*/
|
|
201
|
+
function findNodeModulesPackages() {
|
|
202
|
+
const { existsSync, readdirSync } = __require("node:fs");
|
|
203
|
+
const { join, dirname } = __require("node:path");
|
|
204
|
+
const { createRequire: createRequire$1 } = __require("node:module");
|
|
205
|
+
const results = [];
|
|
206
|
+
const contexts = [join(process.cwd(), "__resolve__.js"), ...process.argv[1] ? [join(dirname(process.argv[1]), "__resolve__.js")] : []];
|
|
207
|
+
for (const context of contexts) try {
|
|
208
|
+
const aigneDir = dirname(dirname(createRequire$1(context).resolve("@aigne/afs/package.json")));
|
|
209
|
+
if (!existsSync(aigneDir)) continue;
|
|
210
|
+
const entries = readdirSync(aigneDir);
|
|
211
|
+
for (const entry of entries) {
|
|
212
|
+
if (!entry.startsWith("afs-")) continue;
|
|
213
|
+
const packageName = `@aigne/${entry}`;
|
|
214
|
+
const packageDir = join(aigneDir, entry);
|
|
215
|
+
if (existsSync(join(packageDir, "package.json"))) results.push({
|
|
216
|
+
packageName,
|
|
217
|
+
packageDir
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (results.length > 0) break;
|
|
221
|
+
} catch {}
|
|
222
|
+
return results;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Import a package and extract manifests from classes with static manifest().
|
|
226
|
+
*/
|
|
227
|
+
async function importAndExtractManifests(packageDir) {
|
|
228
|
+
const { existsSync, readFileSync } = __require("node:fs");
|
|
229
|
+
const { join } = __require("node:path");
|
|
230
|
+
let importPath = packageDir;
|
|
231
|
+
const pkgJsonPath = join(packageDir, "package.json");
|
|
232
|
+
if (existsSync(pkgJsonPath)) try {
|
|
233
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
234
|
+
const esmEntry = typeof pkg.exports === "object" && pkg.exports["."]?.import || pkg.module;
|
|
235
|
+
if (esmEntry) importPath = join(packageDir, esmEntry);
|
|
236
|
+
else if (pkg.main) importPath = join(packageDir, pkg.main);
|
|
237
|
+
} catch {}
|
|
238
|
+
const mod = await import(importPath);
|
|
239
|
+
const manifests = [];
|
|
240
|
+
const seen = /* @__PURE__ */ new Set();
|
|
241
|
+
for (const key of Object.keys(mod)) {
|
|
242
|
+
const val = mod[key];
|
|
243
|
+
if (typeof val !== "function") continue;
|
|
244
|
+
if (typeof val.manifest !== "function") continue;
|
|
245
|
+
const result = val.manifest();
|
|
246
|
+
const items = Array.isArray(result) ? result : [result];
|
|
247
|
+
for (const item of items) if (item?.name && !seen.has(item.name)) {
|
|
248
|
+
seen.add(item.name);
|
|
249
|
+
if (!item.treeSchema && typeof val.treeSchema === "function") try {
|
|
250
|
+
item.treeSchema = val.treeSchema();
|
|
251
|
+
} catch {}
|
|
252
|
+
if (!item.agentMdPath) {
|
|
253
|
+
const mdPath = join(packageDir, ".afs", "AGENT.md");
|
|
254
|
+
if (existsSync(mdPath)) item.agentMdPath = mdPath;
|
|
255
|
+
}
|
|
256
|
+
manifests.push(item);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return manifests;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Convert a Zod schema to JSON Schema (if it's a Zod type).
|
|
263
|
+
* Returns undefined if conversion fails or schema is not Zod.
|
|
264
|
+
*/
|
|
265
|
+
function convertZodToJsonSchema(schema) {
|
|
266
|
+
if (!schema) return void 0;
|
|
267
|
+
if (typeof schema === "object" && schema !== null && !("_def" in schema)) return schema;
|
|
268
|
+
try {
|
|
269
|
+
return __require("zod").z.toJSONSchema(schema);
|
|
270
|
+
} catch {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
//#endregion
|
|
276
|
+
export { scanInstalledProviders as n, __require as r, clearScanCache as t };
|
|
277
|
+
//# sourceMappingURL=scanner-CI1h9bn6.mjs.map
|