@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
CHANGED
|
@@ -1,519 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as scanInstalledProviders, r as __require, t as clearScanCache } from "./scanner-CI1h9bn6.mjs";
|
|
2
|
+
import { AFSBaseProvider, AFSNotFoundError, AFS_CATEGORIES, Actions, CAPABILITY_TAGS, Explain, List, Meta, Read, Search, Stat } from "@aigne/afs";
|
|
2
3
|
import { buildURI, getTemplateVariableNames } from "@aigne/afs/utils/uri-template";
|
|
3
4
|
import { joinURL } from "ufo";
|
|
4
5
|
|
|
5
|
-
//#region schema/providers.json
|
|
6
|
-
var providers = [
|
|
7
|
-
{
|
|
8
|
-
"name": "fs",
|
|
9
|
-
"description": "Local filesystem directory access.\n- Browse directories, read/write files, search content by pattern\n- Exec actions: `archive` (create tar.gz/zip), `checksum` (MD5/SHA)\n- Path structure: direct filesystem paths (e.g., `/docs/guide.md`)",
|
|
10
|
-
"category": "storage",
|
|
11
|
-
"uriTemplate": "fs://{localPath+}",
|
|
12
|
-
"schema": {
|
|
13
|
-
"type": "object",
|
|
14
|
-
"properties": { "localPath": {
|
|
15
|
-
"type": "string",
|
|
16
|
-
"description": "Local directory path"
|
|
17
|
-
} },
|
|
18
|
-
"required": ["localPath"]
|
|
19
|
-
},
|
|
20
|
-
"tags": ["local", "filesystem"],
|
|
21
|
-
"useCases": [
|
|
22
|
-
"source code access",
|
|
23
|
-
"local data files",
|
|
24
|
-
"project navigation"
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"name": "git",
|
|
29
|
-
"description": "Git repository browser with branch-based access.\n- Browse branches, read files at any ref, search across repository\n- Exec actions (readwrite): `diff`, `create-branch`, `commit`, `merge`\n- Virtual `.log/` tree exposes commit history per branch\n- Path structure: `/{branch}/{file-path}` (branch `/` encoded as `~`)",
|
|
30
|
-
"category": "version-control",
|
|
31
|
-
"uriTemplate": "git://{localPath+}",
|
|
32
|
-
"schema": {
|
|
33
|
-
"type": "object",
|
|
34
|
-
"properties": {
|
|
35
|
-
"localPath": {
|
|
36
|
-
"type": "string",
|
|
37
|
-
"description": "Local git repository path"
|
|
38
|
-
},
|
|
39
|
-
"branch": {
|
|
40
|
-
"type": "string",
|
|
41
|
-
"description": "Branch name (default: current branch)"
|
|
42
|
-
},
|
|
43
|
-
"remoteUrl": {
|
|
44
|
-
"type": "string",
|
|
45
|
-
"description": "Remote URL for cloning"
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
"required": ["localPath"]
|
|
49
|
-
},
|
|
50
|
-
"tags": ["git", "version-control"],
|
|
51
|
-
"useCases": [
|
|
52
|
-
"code review",
|
|
53
|
-
"version history",
|
|
54
|
-
"branch comparison"
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"name": "sqlite",
|
|
59
|
-
"description": "SQLite database — tables as directories, rows as nodes.\n- Browse tables and rows, full-text search (FTS5), schema introspection\n- Exec actions: `insert`, `update`, `delete` at table/row level, custom SQL\n- Path structure: `/{table}/{primary-key}`",
|
|
60
|
-
"category": "database",
|
|
61
|
-
"uriTemplate": "sqlite://{localPath+}",
|
|
62
|
-
"schema": {
|
|
63
|
-
"type": "object",
|
|
64
|
-
"properties": { "localPath": {
|
|
65
|
-
"type": "string",
|
|
66
|
-
"description": "Path to SQLite database file"
|
|
67
|
-
} },
|
|
68
|
-
"required": ["localPath"]
|
|
69
|
-
},
|
|
70
|
-
"tags": ["sqlite", "database"],
|
|
71
|
-
"useCases": [
|
|
72
|
-
"structured data",
|
|
73
|
-
"application state",
|
|
74
|
-
"data analysis"
|
|
75
|
-
]
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"name": "json",
|
|
79
|
-
"description": "JSON or YAML file — navigate and edit structured data as a tree.\n- Objects and arrays become directories, primitives become leaf nodes\n- Read/write individual values, search across structure\n- Path structure: `/{key}/{nested-key}` (arrays indexed by position)",
|
|
80
|
-
"category": "structured-data",
|
|
81
|
-
"uriTemplate": "json://{localPath+}",
|
|
82
|
-
"schema": {
|
|
83
|
-
"type": "object",
|
|
84
|
-
"properties": { "localPath": {
|
|
85
|
-
"type": "string",
|
|
86
|
-
"description": "Path to JSON or YAML file"
|
|
87
|
-
} },
|
|
88
|
-
"required": ["localPath"]
|
|
89
|
-
},
|
|
90
|
-
"tags": [
|
|
91
|
-
"json",
|
|
92
|
-
"yaml",
|
|
93
|
-
"structured-data"
|
|
94
|
-
],
|
|
95
|
-
"useCases": [
|
|
96
|
-
"configuration files",
|
|
97
|
-
"data inspection",
|
|
98
|
-
"API response exploration"
|
|
99
|
-
]
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"name": "toml",
|
|
103
|
-
"description": "TOML config file — navigate and edit structured data as a tree.\n- Tables become directories, values become leaf nodes\n- Supports TOML-specific types (datetime, array of tables)\n- Path structure: `/{table}/{key}`",
|
|
104
|
-
"category": "structured-data",
|
|
105
|
-
"uriTemplate": "toml://{localPath+}",
|
|
106
|
-
"schema": {
|
|
107
|
-
"type": "object",
|
|
108
|
-
"properties": { "localPath": {
|
|
109
|
-
"type": "string",
|
|
110
|
-
"description": "Path to TOML file"
|
|
111
|
-
} },
|
|
112
|
-
"required": ["localPath"]
|
|
113
|
-
},
|
|
114
|
-
"tags": ["toml", "structured-data"],
|
|
115
|
-
"useCases": ["configuration files", "Cargo.toml inspection"]
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
"name": "sandbox",
|
|
119
|
-
"description": "Sandboxed JavaScript execution environment for LLM-generated code.\n- Create, run, and manage scripts with version history\n- Execution history tracking with metrics (duration, CPU, memory)\n- Rate limiting and audit logging for safe agent operation",
|
|
120
|
-
"category": "compute",
|
|
121
|
-
"uriTemplate": "sandbox://",
|
|
122
|
-
"schema": {
|
|
123
|
-
"type": "object",
|
|
124
|
-
"properties": {}
|
|
125
|
-
},
|
|
126
|
-
"tags": [
|
|
127
|
-
"sandbox",
|
|
128
|
-
"compute",
|
|
129
|
-
"javascript"
|
|
130
|
-
],
|
|
131
|
-
"useCases": [
|
|
132
|
-
"code execution",
|
|
133
|
-
"data transformation",
|
|
134
|
-
"scripting"
|
|
135
|
-
]
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
"name": "workspace",
|
|
139
|
-
"description": "Workspace container — groups multiple providers under one mount.\n- Configuration-driven sub-mounts with shared access control\n- Delegates all operations to appropriate sub-provider by path",
|
|
140
|
-
"category": "composite",
|
|
141
|
-
"uriTemplate": "workspace://{localPath+}",
|
|
142
|
-
"schema": {
|
|
143
|
-
"type": "object",
|
|
144
|
-
"properties": { "localPath": {
|
|
145
|
-
"type": "string",
|
|
146
|
-
"description": "Workspace directory path"
|
|
147
|
-
} },
|
|
148
|
-
"required": ["localPath"]
|
|
149
|
-
},
|
|
150
|
-
"tags": ["workspace", "composite"],
|
|
151
|
-
"useCases": [
|
|
152
|
-
"project organization",
|
|
153
|
-
"multi-source access",
|
|
154
|
-
"monorepo navigation"
|
|
155
|
-
]
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"name": "github",
|
|
159
|
-
"description": "GitHub repository — issues, pull requests, and workflow runs.\n- Browse, create, comment on, and close issues and PRs\n- Read workflow run status and logs\n- Path structure: `/issues/{number}`, `/pulls/{number}`",
|
|
160
|
-
"category": "integration",
|
|
161
|
-
"uriTemplate": "github://{owner}/{repo}",
|
|
162
|
-
"schema": {
|
|
163
|
-
"type": "object",
|
|
164
|
-
"properties": {
|
|
165
|
-
"owner": {
|
|
166
|
-
"type": "string",
|
|
167
|
-
"description": "GitHub organization or user"
|
|
168
|
-
},
|
|
169
|
-
"repo": {
|
|
170
|
-
"type": "string",
|
|
171
|
-
"description": "Repository name"
|
|
172
|
-
},
|
|
173
|
-
"token": {
|
|
174
|
-
"type": "string",
|
|
175
|
-
"description": "GitHub personal access token"
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
"required": ["owner", "repo"]
|
|
179
|
-
},
|
|
180
|
-
"tags": [
|
|
181
|
-
"github",
|
|
182
|
-
"git",
|
|
183
|
-
"integration"
|
|
184
|
-
],
|
|
185
|
-
"useCases": [
|
|
186
|
-
"issue tracking",
|
|
187
|
-
"PR review",
|
|
188
|
-
"CI/CD monitoring"
|
|
189
|
-
]
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
"name": "http",
|
|
193
|
-
"description": "Remote AFS instance — proxy all operations to another AFS server over HTTP.\n- Transparently forwards read, write, search, exec, and all other operations\n- Supports bearer token authentication and configurable retry/timeout",
|
|
194
|
-
"category": "integration",
|
|
195
|
-
"uriTemplate": "http://{host+}",
|
|
196
|
-
"schema": {
|
|
197
|
-
"type": "object",
|
|
198
|
-
"properties": {
|
|
199
|
-
"host": {
|
|
200
|
-
"type": "string",
|
|
201
|
-
"description": "Server host and path"
|
|
202
|
-
},
|
|
203
|
-
"token": {
|
|
204
|
-
"type": "string",
|
|
205
|
-
"description": "Authentication token"
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
"required": ["host"]
|
|
209
|
-
},
|
|
210
|
-
"tags": [
|
|
211
|
-
"http",
|
|
212
|
-
"remote",
|
|
213
|
-
"integration"
|
|
214
|
-
]
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
"name": "https",
|
|
218
|
-
"description": "Remote AFS instance — proxy all operations to another AFS server over HTTPS.\n- Transparently forwards read, write, search, exec, and all other operations\n- Supports bearer token authentication and configurable retry/timeout",
|
|
219
|
-
"category": "integration",
|
|
220
|
-
"uriTemplate": "https://{host+}",
|
|
221
|
-
"schema": {
|
|
222
|
-
"type": "object",
|
|
223
|
-
"properties": {
|
|
224
|
-
"host": {
|
|
225
|
-
"type": "string",
|
|
226
|
-
"description": "Server host and path"
|
|
227
|
-
},
|
|
228
|
-
"token": {
|
|
229
|
-
"type": "string",
|
|
230
|
-
"description": "Authentication token"
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
"required": ["host"]
|
|
234
|
-
},
|
|
235
|
-
"tags": [
|
|
236
|
-
"https",
|
|
237
|
-
"remote",
|
|
238
|
-
"integration"
|
|
239
|
-
]
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
"name": "mcp-stdio",
|
|
243
|
-
"description": "MCP (Model Context Protocol) server — access external tools and resources via stdio.\n- Discover and execute tools exposed by the MCP server\n- Browse resources as virtual files, access prompt templates\n- Path structure: `/tools/{name}`, `/resources/{uri}`, `/prompts/{name}`",
|
|
244
|
-
"category": "integration",
|
|
245
|
-
"uriTemplate": "mcp+stdio://{command+}",
|
|
246
|
-
"schema": {
|
|
247
|
-
"type": "object",
|
|
248
|
-
"properties": {
|
|
249
|
-
"command": {
|
|
250
|
-
"type": "string",
|
|
251
|
-
"description": "Command to run the MCP server"
|
|
252
|
-
},
|
|
253
|
-
"args": {
|
|
254
|
-
"type": "array",
|
|
255
|
-
"items": { "type": "string" },
|
|
256
|
-
"description": "Command arguments"
|
|
257
|
-
},
|
|
258
|
-
"env": {
|
|
259
|
-
"type": "object",
|
|
260
|
-
"description": "Environment variables"
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
"required": ["command"]
|
|
264
|
-
},
|
|
265
|
-
"tags": [
|
|
266
|
-
"mcp",
|
|
267
|
-
"stdio",
|
|
268
|
-
"integration"
|
|
269
|
-
]
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
"name": "mcp-http",
|
|
273
|
-
"description": "MCP (Model Context Protocol) server — access external tools and resources via HTTP.\n- Discover and execute tools exposed by the MCP server\n- Browse resources as virtual files, access prompt templates\n- Path structure: `/tools/{name}`, `/resources/{uri}`, `/prompts/{name}`",
|
|
274
|
-
"category": "integration",
|
|
275
|
-
"uriTemplate": "mcp+http://{url+}",
|
|
276
|
-
"schema": {
|
|
277
|
-
"type": "object",
|
|
278
|
-
"properties": { "url": {
|
|
279
|
-
"type": "string",
|
|
280
|
-
"description": "HTTP URL of the MCP server"
|
|
281
|
-
} },
|
|
282
|
-
"required": ["url"]
|
|
283
|
-
},
|
|
284
|
-
"tags": [
|
|
285
|
-
"mcp",
|
|
286
|
-
"http",
|
|
287
|
-
"integration"
|
|
288
|
-
]
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
"name": "mcp-sse",
|
|
292
|
-
"description": "MCP (Model Context Protocol) server — access external tools and resources via SSE.\n- Discover and execute tools exposed by the MCP server\n- Browse resources as virtual files, access prompt templates\n- Path structure: `/tools/{name}`, `/resources/{uri}`, `/prompts/{name}`",
|
|
293
|
-
"category": "integration",
|
|
294
|
-
"uriTemplate": "mcp+sse://{url+}",
|
|
295
|
-
"schema": {
|
|
296
|
-
"type": "object",
|
|
297
|
-
"properties": { "url": {
|
|
298
|
-
"type": "string",
|
|
299
|
-
"description": "SSE URL of the MCP server"
|
|
300
|
-
} },
|
|
301
|
-
"required": ["url"]
|
|
302
|
-
},
|
|
303
|
-
"tags": [
|
|
304
|
-
"mcp",
|
|
305
|
-
"sse",
|
|
306
|
-
"integration"
|
|
307
|
-
]
|
|
308
|
-
},
|
|
309
|
-
{
|
|
310
|
-
"name": "s3",
|
|
311
|
-
"description": "AWS S3 and S3-compatible object storage (MinIO, R2, B2).\n- Browse, read, write, and delete objects; search by key prefix\n- Exec actions: `presign-download`, `presign-upload`, `multipart-upload`, `select` (SQL on objects)\n- Path structure: `/{key-prefix}/{object-key}`",
|
|
312
|
-
"category": "cloud-storage",
|
|
313
|
-
"uriTemplate": "s3://{bucket}/{prefix+?}",
|
|
314
|
-
"schema": {
|
|
315
|
-
"type": "object",
|
|
316
|
-
"properties": {
|
|
317
|
-
"bucket": {
|
|
318
|
-
"type": "string",
|
|
319
|
-
"description": "S3 bucket name"
|
|
320
|
-
},
|
|
321
|
-
"prefix": {
|
|
322
|
-
"type": "string",
|
|
323
|
-
"description": "Object key prefix"
|
|
324
|
-
},
|
|
325
|
-
"region": {
|
|
326
|
-
"type": "string",
|
|
327
|
-
"description": "AWS region"
|
|
328
|
-
},
|
|
329
|
-
"accessKeyId": {
|
|
330
|
-
"type": "string",
|
|
331
|
-
"description": "AWS access key ID"
|
|
332
|
-
},
|
|
333
|
-
"secretAccessKey": {
|
|
334
|
-
"type": "string",
|
|
335
|
-
"description": "AWS secret access key"
|
|
336
|
-
},
|
|
337
|
-
"endpoint": {
|
|
338
|
-
"type": "string",
|
|
339
|
-
"description": "Custom S3 endpoint URL"
|
|
340
|
-
},
|
|
341
|
-
"profile": {
|
|
342
|
-
"type": "string",
|
|
343
|
-
"description": "AWS CLI profile name"
|
|
344
|
-
}
|
|
345
|
-
},
|
|
346
|
-
"required": ["bucket"]
|
|
347
|
-
},
|
|
348
|
-
"tags": [
|
|
349
|
-
"aws",
|
|
350
|
-
"s3",
|
|
351
|
-
"cloud",
|
|
352
|
-
"storage"
|
|
353
|
-
],
|
|
354
|
-
"useCases": [
|
|
355
|
-
"cloud file storage",
|
|
356
|
-
"data lake access",
|
|
357
|
-
"backup management"
|
|
358
|
-
]
|
|
359
|
-
},
|
|
360
|
-
{
|
|
361
|
-
"name": "gcs",
|
|
362
|
-
"description": "Google Cloud Storage bucket.\n- Browse, read, write, and delete objects; search by key prefix\n- Exec actions: `presign-download`, `presign-upload`, `compose` (concatenate objects), `rewrite` (copy with transform)\n- Path structure: `/{key-prefix}/{object-key}`",
|
|
363
|
-
"category": "cloud-storage",
|
|
364
|
-
"uriTemplate": "gcs://{bucket}/{prefix+?}",
|
|
365
|
-
"schema": {
|
|
366
|
-
"type": "object",
|
|
367
|
-
"properties": {
|
|
368
|
-
"bucket": {
|
|
369
|
-
"type": "string",
|
|
370
|
-
"description": "GCS bucket name"
|
|
371
|
-
},
|
|
372
|
-
"prefix": {
|
|
373
|
-
"type": "string",
|
|
374
|
-
"description": "Object key prefix"
|
|
375
|
-
},
|
|
376
|
-
"projectId": {
|
|
377
|
-
"type": "string",
|
|
378
|
-
"description": "Google Cloud project ID"
|
|
379
|
-
},
|
|
380
|
-
"keyFilename": {
|
|
381
|
-
"type": "string",
|
|
382
|
-
"description": "Path to service account key file"
|
|
383
|
-
}
|
|
384
|
-
},
|
|
385
|
-
"required": ["bucket"]
|
|
386
|
-
},
|
|
387
|
-
"tags": [
|
|
388
|
-
"gcp",
|
|
389
|
-
"gcs",
|
|
390
|
-
"cloud",
|
|
391
|
-
"storage"
|
|
392
|
-
],
|
|
393
|
-
"useCases": [
|
|
394
|
-
"cloud file storage",
|
|
395
|
-
"data lake access",
|
|
396
|
-
"ML training data"
|
|
397
|
-
]
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
"name": "ec2",
|
|
401
|
-
"description": "AWS EC2 compute instances in a region.\n- List and inspect instances, view metadata, tags, and security groups\n- Exec actions: `start`, `stop`, `reboot`, `terminate`, `run-instances`\n- Path structure: `/instances/{instance-id}`, `/by-state/{state}/{instance-id}`",
|
|
402
|
-
"category": "cloud-compute",
|
|
403
|
-
"uriTemplate": "ec2://{region?}",
|
|
404
|
-
"schema": {
|
|
405
|
-
"type": "object",
|
|
406
|
-
"properties": {
|
|
407
|
-
"region": {
|
|
408
|
-
"type": "string",
|
|
409
|
-
"description": "AWS region"
|
|
410
|
-
},
|
|
411
|
-
"profile": {
|
|
412
|
-
"type": "string",
|
|
413
|
-
"description": "AWS CLI profile name"
|
|
414
|
-
},
|
|
415
|
-
"endpoint": {
|
|
416
|
-
"type": "string",
|
|
417
|
-
"description": "Custom EC2 endpoint URL"
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
"tags": [
|
|
422
|
-
"aws",
|
|
423
|
-
"ec2",
|
|
424
|
-
"cloud",
|
|
425
|
-
"compute"
|
|
426
|
-
],
|
|
427
|
-
"useCases": [
|
|
428
|
-
"instance management",
|
|
429
|
-
"cloud operations",
|
|
430
|
-
"infrastructure monitoring"
|
|
431
|
-
]
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
"name": "gce",
|
|
435
|
-
"description": "Google Compute Engine VM instances in a project/zone.\n- List and inspect instances, view metadata, labels, and network config\n- Exec actions: `start`, `stop`, `restart`, `delete`\n- Path structure: `/instances/{instance-name}`",
|
|
436
|
-
"category": "cloud-compute",
|
|
437
|
-
"uriTemplate": "gce://{project}/{zone}",
|
|
438
|
-
"schema": {
|
|
439
|
-
"type": "object",
|
|
440
|
-
"properties": {
|
|
441
|
-
"project": {
|
|
442
|
-
"type": "string",
|
|
443
|
-
"description": "Google Cloud project ID"
|
|
444
|
-
},
|
|
445
|
-
"zone": {
|
|
446
|
-
"type": "string",
|
|
447
|
-
"description": "Compute zone"
|
|
448
|
-
},
|
|
449
|
-
"keyFilename": {
|
|
450
|
-
"type": "string",
|
|
451
|
-
"description": "Path to service account key file"
|
|
452
|
-
}
|
|
453
|
-
},
|
|
454
|
-
"required": ["project", "zone"]
|
|
455
|
-
},
|
|
456
|
-
"tags": [
|
|
457
|
-
"gcp",
|
|
458
|
-
"gce",
|
|
459
|
-
"cloud",
|
|
460
|
-
"compute"
|
|
461
|
-
],
|
|
462
|
-
"useCases": [
|
|
463
|
-
"instance management",
|
|
464
|
-
"cloud operations",
|
|
465
|
-
"infrastructure monitoring"
|
|
466
|
-
]
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
"name": "dns",
|
|
470
|
-
"description": "DNS zone management — Route53 and Google Cloud DNS.\n- List, create, update, and delete DNS records (A, AAAA, CNAME, MX, TXT, etc.)\n- Audit logging and rate limiting for safe zone modifications\n- Path structure: `/{zone}/{record-name}`",
|
|
471
|
-
"category": "cloud-dns",
|
|
472
|
-
"uriTemplate": "dns://{zone}",
|
|
473
|
-
"schema": {
|
|
474
|
-
"type": "object",
|
|
475
|
-
"properties": { "zone": {
|
|
476
|
-
"type": "string",
|
|
477
|
-
"description": "DNS zone name"
|
|
478
|
-
} },
|
|
479
|
-
"required": ["zone"]
|
|
480
|
-
},
|
|
481
|
-
"tags": ["dns", "cloud"],
|
|
482
|
-
"useCases": ["DNS record management", "domain configuration"]
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
"name": "cloudflare",
|
|
486
|
-
"description": "Cloudflare account — Workers, KV namespaces, and Pages projects.\n- Manage Workers: create, deploy, rollback, delete\n- Manage KV: create/delete namespaces, read/write keys\n- Manage Pages: create, deploy, rollback, configure bindings",
|
|
487
|
-
"category": "cloud-platform",
|
|
488
|
-
"uriTemplate": "cloudflare://{accountId}",
|
|
489
|
-
"schema": {
|
|
490
|
-
"type": "object",
|
|
491
|
-
"properties": {
|
|
492
|
-
"accountId": {
|
|
493
|
-
"type": "string",
|
|
494
|
-
"description": "Cloudflare account ID"
|
|
495
|
-
},
|
|
496
|
-
"apiToken": {
|
|
497
|
-
"type": "string",
|
|
498
|
-
"description": "Cloudflare API token"
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
},
|
|
502
|
-
"tags": [
|
|
503
|
-
"cloudflare",
|
|
504
|
-
"cloud",
|
|
505
|
-
"workers",
|
|
506
|
-
"kv"
|
|
507
|
-
],
|
|
508
|
-
"useCases": [
|
|
509
|
-
"edge computing",
|
|
510
|
-
"KV storage",
|
|
511
|
-
"CDN management"
|
|
512
|
-
]
|
|
513
|
-
}
|
|
514
|
-
];
|
|
515
|
-
|
|
516
|
-
//#endregion
|
|
517
6
|
//#region \0@oxc-project+runtime@0.108.0/helpers/decorate.js
|
|
518
7
|
function __decorate(decorators, target, key, desc) {
|
|
519
8
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -538,47 +27,38 @@ function __decorate(decorators, target, key, desc) {
|
|
|
538
27
|
* └── .actions/search
|
|
539
28
|
* ```
|
|
540
29
|
*/
|
|
30
|
+
/** Trim description to first sentence, max 120 chars. */
|
|
31
|
+
function firstSentence(desc) {
|
|
32
|
+
const line = desc.split("\n")[0] ?? desc;
|
|
33
|
+
const sentence = line.split(/\.\s/)[0] ?? line;
|
|
34
|
+
if (sentence.length > 120) return `${sentence.slice(0, 117)}...`;
|
|
35
|
+
return sentence.endsWith(".") ? sentence : `${sentence}.`;
|
|
36
|
+
}
|
|
541
37
|
var AFSRegistry = class extends AFSBaseProvider {
|
|
542
38
|
name = "registry";
|
|
543
39
|
description = "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}`";
|
|
544
40
|
accessMode = "readwrite";
|
|
545
41
|
providers;
|
|
546
|
-
|
|
547
|
-
fetchPromise;
|
|
42
|
+
scanPromise;
|
|
548
43
|
loadProviderFn;
|
|
549
44
|
constructor(options = {}) {
|
|
550
45
|
super();
|
|
551
46
|
if (options.providers && options.providers.length > 0) this.providers = JSON.parse(JSON.stringify(options.providers));
|
|
552
47
|
else {
|
|
553
|
-
this.providers =
|
|
554
|
-
this.
|
|
555
|
-
if (this.remoteUrl) this.fetchPromise = this.fetchRemoteProviders(this.remoteUrl);
|
|
48
|
+
this.providers = [];
|
|
49
|
+
this.scanPromise = this.loadFromScan();
|
|
556
50
|
}
|
|
557
51
|
}
|
|
558
|
-
async
|
|
52
|
+
async loadFromScan() {
|
|
559
53
|
try {
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
const data = await response.json();
|
|
563
|
-
if (Array.isArray(data?.providers) && data.providers.length > 0) this.providers = data.providers.map((p) => {
|
|
564
|
-
const entry = { ...p };
|
|
565
|
-
if (!entry.uriTemplate && entry.uri) {
|
|
566
|
-
entry.uriTemplate = entry.uri;
|
|
567
|
-
delete entry.uri;
|
|
568
|
-
}
|
|
569
|
-
if (!entry.useCases && entry.use_cases) {
|
|
570
|
-
entry.useCases = entry.use_cases;
|
|
571
|
-
delete entry.use_cases;
|
|
572
|
-
}
|
|
573
|
-
delete entry.capabilities_summary;
|
|
574
|
-
return entry;
|
|
575
|
-
});
|
|
54
|
+
const { scanInstalledProviders: scanInstalledProviders$1 } = await import("./scanner-LVTipem0.mjs");
|
|
55
|
+
this.providers = await scanInstalledProviders$1();
|
|
576
56
|
} catch {}
|
|
577
57
|
}
|
|
578
58
|
async ensureLoaded() {
|
|
579
|
-
if (this.
|
|
580
|
-
await this.
|
|
581
|
-
this.
|
|
59
|
+
if (this.scanPromise) {
|
|
60
|
+
await this.scanPromise;
|
|
61
|
+
this.scanPromise = void 0;
|
|
582
62
|
}
|
|
583
63
|
}
|
|
584
64
|
onMount(root) {
|
|
@@ -619,16 +99,36 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
619
99
|
}
|
|
620
100
|
buildByTag() {
|
|
621
101
|
const map = /* @__PURE__ */ new Map();
|
|
622
|
-
for (const p of this.providers)
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
102
|
+
for (const p of this.providers) {
|
|
103
|
+
const tags = p.capabilityTags?.length ? p.capabilityTags : p.tags || [];
|
|
104
|
+
for (const tag of tags) {
|
|
105
|
+
const list = map.get(tag) || [];
|
|
106
|
+
list.push(p);
|
|
107
|
+
map.set(tag, list);
|
|
108
|
+
}
|
|
626
109
|
}
|
|
627
110
|
return map;
|
|
628
111
|
}
|
|
629
112
|
findProvider(name) {
|
|
630
113
|
return this.providers.find((p) => p.name === name);
|
|
631
114
|
}
|
|
115
|
+
getRecipes() {
|
|
116
|
+
return this.providers.filter((p) => p.type === "recipe");
|
|
117
|
+
}
|
|
118
|
+
findRecipe(name) {
|
|
119
|
+
return this.getRecipes().find((p) => p.name === name);
|
|
120
|
+
}
|
|
121
|
+
/** Load AGENT.md content: inline first, then lazy-read from disk. */
|
|
122
|
+
loadAgentMd(provider) {
|
|
123
|
+
if (provider.agentMd) return provider.agentMd;
|
|
124
|
+
if (!provider.agentMdPath) return void 0;
|
|
125
|
+
try {
|
|
126
|
+
const { readFileSync } = __require("node:fs");
|
|
127
|
+
return readFileSync(provider.agentMdPath, "utf-8");
|
|
128
|
+
} catch {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
632
132
|
async listRoot(_ctx) {
|
|
633
133
|
return { data: [
|
|
634
134
|
{
|
|
@@ -654,25 +154,55 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
654
154
|
kind: "afs:directory",
|
|
655
155
|
childrenCount: this.buildByTag().size
|
|
656
156
|
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: "recipes",
|
|
160
|
+
path: "/recipes",
|
|
161
|
+
meta: {
|
|
162
|
+
kind: "afs:directory",
|
|
163
|
+
childrenCount: this.getRecipes().length
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: ".vocabulary",
|
|
168
|
+
path: "/.vocabulary",
|
|
169
|
+
meta: {
|
|
170
|
+
kind: "afs:directory",
|
|
171
|
+
childrenCount: 2
|
|
172
|
+
}
|
|
657
173
|
}
|
|
658
174
|
] };
|
|
659
175
|
}
|
|
660
176
|
async listProviders(_ctx) {
|
|
661
|
-
return { data: this.providers.map((p) =>
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
meta
|
|
666
|
-
kind: "registry:provider",
|
|
667
|
-
childrenCount
|
|
177
|
+
return { data: this.providers.map((p) => {
|
|
178
|
+
let childrenCount = 3;
|
|
179
|
+
if (p.agentMd || p.agentMdPath) childrenCount++;
|
|
180
|
+
if (p.treeSchema) childrenCount++;
|
|
181
|
+
const meta = {
|
|
182
|
+
kind: p.type === "recipe" ? "registry:recipe" : "registry:provider",
|
|
183
|
+
childrenCount,
|
|
184
|
+
category: p.category,
|
|
185
|
+
capabilityTags: p.capabilityTags,
|
|
186
|
+
type: p.type || "provider"
|
|
187
|
+
};
|
|
188
|
+
if (p.treeSchema && typeof p.treeSchema === "object" && "operations" in p.treeSchema) meta.operations = p.treeSchema.operations;
|
|
189
|
+
if (p.treeSchema && typeof p.treeSchema === "object" && "auth" in p.treeSchema) {
|
|
190
|
+
const auth = p.treeSchema.auth;
|
|
191
|
+
if (auth?.type) meta.authType = auth.type;
|
|
668
192
|
}
|
|
669
|
-
|
|
193
|
+
return {
|
|
194
|
+
id: p.name,
|
|
195
|
+
path: joinURL("/providers", p.name),
|
|
196
|
+
summary: firstSentence(p.description),
|
|
197
|
+
meta
|
|
198
|
+
};
|
|
199
|
+
}) };
|
|
670
200
|
}
|
|
671
201
|
async listProviderContents(ctx) {
|
|
672
202
|
const provider = this.findProvider(ctx.params.name);
|
|
673
203
|
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
674
204
|
const base = joinURL("/providers", provider.name);
|
|
675
|
-
|
|
205
|
+
const entries = [{
|
|
676
206
|
id: "manifest.json",
|
|
677
207
|
path: joinURL(base, "manifest.json"),
|
|
678
208
|
meta: { kind: "afs:file" }
|
|
@@ -680,38 +210,52 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
680
210
|
id: "README.md",
|
|
681
211
|
path: joinURL(base, "README.md"),
|
|
682
212
|
meta: { kind: "afs:file" }
|
|
683
|
-
}]
|
|
213
|
+
}];
|
|
214
|
+
if (provider.treeSchema) entries.push({
|
|
215
|
+
id: "tree-schema.json",
|
|
216
|
+
path: joinURL(base, "tree-schema.json"),
|
|
217
|
+
meta: { kind: "afs:file" }
|
|
218
|
+
});
|
|
219
|
+
if (provider.agentMd || provider.agentMdPath) entries.push({
|
|
220
|
+
id: "AGENT.md",
|
|
221
|
+
path: joinURL(base, "AGENT.md"),
|
|
222
|
+
meta: { kind: "afs:file" }
|
|
223
|
+
});
|
|
224
|
+
return { data: entries };
|
|
684
225
|
}
|
|
685
226
|
async listCategories(_ctx) {
|
|
686
|
-
return { data: Array.from(this.buildByCategory().entries()).map(([cat, providers
|
|
227
|
+
return { data: Array.from(this.buildByCategory().entries()).map(([cat, providers]) => ({
|
|
687
228
|
id: cat,
|
|
688
229
|
path: joinURL("/by-category", cat),
|
|
689
230
|
meta: {
|
|
690
231
|
kind: "afs:directory",
|
|
691
|
-
childrenCount: providers
|
|
232
|
+
childrenCount: providers.length
|
|
692
233
|
}
|
|
693
234
|
})) };
|
|
694
235
|
}
|
|
695
236
|
async listCategoryProviders(ctx) {
|
|
696
|
-
const providers
|
|
697
|
-
if (!providers
|
|
698
|
-
return { data: providers
|
|
237
|
+
const providers = this.buildByCategory().get(ctx.params.category);
|
|
238
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
239
|
+
return { data: providers.map((p) => ({
|
|
699
240
|
id: p.name,
|
|
700
241
|
path: joinURL("/by-category", ctx.params.category, p.name),
|
|
701
242
|
summary: p.description,
|
|
702
243
|
meta: {
|
|
703
|
-
kind: "registry:provider",
|
|
704
|
-
childrenCount: 2
|
|
244
|
+
kind: p.type === "recipe" ? "registry:recipe" : "registry:provider",
|
|
245
|
+
childrenCount: 2,
|
|
246
|
+
category: p.category,
|
|
247
|
+
tags: p.tags,
|
|
248
|
+
type: p.type || "provider"
|
|
705
249
|
}
|
|
706
250
|
})) };
|
|
707
251
|
}
|
|
708
252
|
async listTags(_ctx) {
|
|
709
|
-
return { data: Array.from(this.buildByTag().entries()).map(([tag, providers
|
|
253
|
+
return { data: Array.from(this.buildByTag().entries()).map(([tag, providers]) => ({
|
|
710
254
|
id: tag,
|
|
711
255
|
path: joinURL("/by-tag", tag),
|
|
712
256
|
meta: {
|
|
713
257
|
kind: "afs:directory",
|
|
714
|
-
childrenCount: providers
|
|
258
|
+
childrenCount: providers.length
|
|
715
259
|
}
|
|
716
260
|
})) };
|
|
717
261
|
}
|
|
@@ -720,13 +264,18 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
720
264
|
return { data: [] };
|
|
721
265
|
}
|
|
722
266
|
async listTagProviders(ctx) {
|
|
723
|
-
const providers
|
|
724
|
-
if (!providers
|
|
725
|
-
return { data: providers
|
|
267
|
+
const providers = this.buildByTag().get(ctx.params.tag);
|
|
268
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
269
|
+
return { data: providers.map((p) => ({
|
|
726
270
|
id: p.name,
|
|
727
271
|
path: joinURL("/by-tag", ctx.params.tag, p.name),
|
|
728
272
|
summary: p.description,
|
|
729
|
-
meta: {
|
|
273
|
+
meta: {
|
|
274
|
+
kind: p.type === "recipe" ? "registry:recipe" : "registry:provider",
|
|
275
|
+
category: p.category,
|
|
276
|
+
tags: p.tags,
|
|
277
|
+
type: p.type || "provider"
|
|
278
|
+
}
|
|
730
279
|
})) };
|
|
731
280
|
}
|
|
732
281
|
async listTagProviderChildren(ctx) {
|
|
@@ -737,6 +286,35 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
737
286
|
if (!this.findProvider(ctx.params.name)) throw new AFSNotFoundError(ctx.path);
|
|
738
287
|
return { data: [] };
|
|
739
288
|
}
|
|
289
|
+
async listRecipes(_ctx) {
|
|
290
|
+
return { data: this.getRecipes().map((r) => ({
|
|
291
|
+
id: r.name,
|
|
292
|
+
path: joinURL("/recipes", r.name),
|
|
293
|
+
summary: r.description,
|
|
294
|
+
meta: {
|
|
295
|
+
kind: "registry:recipe",
|
|
296
|
+
childrenCount: 2
|
|
297
|
+
}
|
|
298
|
+
})) };
|
|
299
|
+
}
|
|
300
|
+
async listRecipeContents(ctx) {
|
|
301
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
302
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
303
|
+
const base = joinURL("/recipes", recipe.name);
|
|
304
|
+
return { data: [{
|
|
305
|
+
id: "manifest.json",
|
|
306
|
+
path: joinURL(base, "manifest.json"),
|
|
307
|
+
meta: { kind: "afs:file" }
|
|
308
|
+
}, {
|
|
309
|
+
id: "README.md",
|
|
310
|
+
path: joinURL(base, "README.md"),
|
|
311
|
+
meta: { kind: "afs:file" }
|
|
312
|
+
}] };
|
|
313
|
+
}
|
|
314
|
+
async listRecipeFileNode(ctx) {
|
|
315
|
+
if (!this.findRecipe(ctx.params.name)) throw new AFSNotFoundError(ctx.path);
|
|
316
|
+
return { data: [] };
|
|
317
|
+
}
|
|
740
318
|
async readRoot(_ctx) {
|
|
741
319
|
return {
|
|
742
320
|
id: "/",
|
|
@@ -747,7 +325,7 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
747
325
|
},
|
|
748
326
|
meta: {
|
|
749
327
|
kind: "registry:root",
|
|
750
|
-
childrenCount:
|
|
328
|
+
childrenCount: 5
|
|
751
329
|
}
|
|
752
330
|
};
|
|
753
331
|
}
|
|
@@ -824,6 +402,29 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
824
402
|
meta: { kind: "afs:file" }
|
|
825
403
|
};
|
|
826
404
|
}
|
|
405
|
+
async readTreeSchema(ctx) {
|
|
406
|
+
const provider = this.findProvider(ctx.params.name);
|
|
407
|
+
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
408
|
+
if (!provider.treeSchema) throw new AFSNotFoundError(ctx.path);
|
|
409
|
+
return {
|
|
410
|
+
id: "tree-schema.json",
|
|
411
|
+
path: ctx.path,
|
|
412
|
+
content: provider.treeSchema,
|
|
413
|
+
meta: { kind: "afs:file" }
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
async readAgentMd(ctx) {
|
|
417
|
+
const provider = this.findProvider(ctx.params.name);
|
|
418
|
+
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
419
|
+
const content = this.loadAgentMd(provider);
|
|
420
|
+
if (!content) throw new AFSNotFoundError(ctx.path);
|
|
421
|
+
return {
|
|
422
|
+
id: "AGENT.md",
|
|
423
|
+
path: ctx.path,
|
|
424
|
+
content,
|
|
425
|
+
meta: { kind: "afs:file" }
|
|
426
|
+
};
|
|
427
|
+
}
|
|
827
428
|
async readByCategory(_ctx) {
|
|
828
429
|
return {
|
|
829
430
|
id: "by-category",
|
|
@@ -839,18 +440,18 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
839
440
|
};
|
|
840
441
|
}
|
|
841
442
|
async readCategory(ctx) {
|
|
842
|
-
const providers
|
|
843
|
-
if (!providers
|
|
443
|
+
const providers = this.buildByCategory().get(ctx.params.category);
|
|
444
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
844
445
|
return {
|
|
845
446
|
id: ctx.params.category,
|
|
846
447
|
path: joinURL("/by-category", ctx.params.category),
|
|
847
448
|
content: {
|
|
848
449
|
type: "category",
|
|
849
|
-
count: providers
|
|
450
|
+
count: providers.length
|
|
850
451
|
},
|
|
851
452
|
meta: {
|
|
852
453
|
kind: "afs:directory",
|
|
853
|
-
childrenCount: providers
|
|
454
|
+
childrenCount: providers.length
|
|
854
455
|
}
|
|
855
456
|
};
|
|
856
457
|
}
|
|
@@ -883,18 +484,18 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
883
484
|
};
|
|
884
485
|
}
|
|
885
486
|
async readTag(ctx) {
|
|
886
|
-
const providers
|
|
887
|
-
if (!providers
|
|
487
|
+
const providers = this.buildByTag().get(ctx.params.tag);
|
|
488
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
888
489
|
return {
|
|
889
490
|
id: ctx.params.tag,
|
|
890
491
|
path: joinURL("/by-tag", ctx.params.tag),
|
|
891
492
|
content: {
|
|
892
493
|
type: "tag",
|
|
893
|
-
count: providers
|
|
494
|
+
count: providers.length
|
|
894
495
|
},
|
|
895
496
|
meta: {
|
|
896
497
|
kind: "afs:directory",
|
|
897
|
-
childrenCount: providers
|
|
498
|
+
childrenCount: providers.length
|
|
898
499
|
}
|
|
899
500
|
};
|
|
900
501
|
}
|
|
@@ -912,6 +513,68 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
912
513
|
meta: { kind: "registry:provider" }
|
|
913
514
|
};
|
|
914
515
|
}
|
|
516
|
+
async readRecipes(_ctx) {
|
|
517
|
+
const recipes = this.getRecipes();
|
|
518
|
+
return {
|
|
519
|
+
id: "recipes",
|
|
520
|
+
path: "/recipes",
|
|
521
|
+
content: {
|
|
522
|
+
type: "directory",
|
|
523
|
+
count: recipes.length
|
|
524
|
+
},
|
|
525
|
+
meta: {
|
|
526
|
+
kind: "afs:directory",
|
|
527
|
+
childrenCount: recipes.length
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
async readRecipe(ctx) {
|
|
532
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
533
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
534
|
+
return {
|
|
535
|
+
id: recipe.name,
|
|
536
|
+
path: joinURL("/recipes", recipe.name),
|
|
537
|
+
content: {
|
|
538
|
+
type: "recipe",
|
|
539
|
+
name: recipe.name,
|
|
540
|
+
description: recipe.description
|
|
541
|
+
},
|
|
542
|
+
meta: {
|
|
543
|
+
kind: "registry:recipe",
|
|
544
|
+
childrenCount: 2
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
async readRecipeManifest(ctx) {
|
|
549
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
550
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
551
|
+
return {
|
|
552
|
+
id: "manifest.json",
|
|
553
|
+
path: ctx.path,
|
|
554
|
+
content: { ...recipe },
|
|
555
|
+
meta: { kind: "afs:file" }
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
async readRecipeReadme(ctx) {
|
|
559
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
560
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
561
|
+
const lines = [
|
|
562
|
+
`# ${recipe.name}`,
|
|
563
|
+
"",
|
|
564
|
+
recipe.description,
|
|
565
|
+
"",
|
|
566
|
+
`**Category:** ${recipe.category}`,
|
|
567
|
+
`**URI:** \`${recipe.uriTemplate}\``
|
|
568
|
+
];
|
|
569
|
+
if (recipe.tags?.length) lines.push("", `**Tags:** ${recipe.tags.join(", ")}`);
|
|
570
|
+
lines.push("");
|
|
571
|
+
return {
|
|
572
|
+
id: "README.md",
|
|
573
|
+
path: ctx.path,
|
|
574
|
+
content: lines.join("\n"),
|
|
575
|
+
meta: { kind: "afs:file" }
|
|
576
|
+
};
|
|
577
|
+
}
|
|
915
578
|
async readCapabilities(_ctx) {
|
|
916
579
|
return {
|
|
917
580
|
id: "/.meta/.capabilities",
|
|
@@ -929,6 +592,53 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
929
592
|
meta: { kind: "afs:capabilities" }
|
|
930
593
|
};
|
|
931
594
|
}
|
|
595
|
+
async listVocabularyLeaf(_ctx) {
|
|
596
|
+
return { data: [] };
|
|
597
|
+
}
|
|
598
|
+
async listVocabulary(_ctx) {
|
|
599
|
+
return { data: [{
|
|
600
|
+
id: "categories",
|
|
601
|
+
path: "/.vocabulary/categories",
|
|
602
|
+
meta: {
|
|
603
|
+
kind: "registry:vocabulary",
|
|
604
|
+
childrenCount: AFS_CATEGORIES.length
|
|
605
|
+
}
|
|
606
|
+
}, {
|
|
607
|
+
id: "tags",
|
|
608
|
+
path: "/.vocabulary/tags",
|
|
609
|
+
meta: {
|
|
610
|
+
kind: "registry:vocabulary",
|
|
611
|
+
childrenCount: CAPABILITY_TAGS.length
|
|
612
|
+
}
|
|
613
|
+
}] };
|
|
614
|
+
}
|
|
615
|
+
async readVocabulary(_ctx) {
|
|
616
|
+
return {
|
|
617
|
+
id: ".vocabulary",
|
|
618
|
+
path: "/.vocabulary",
|
|
619
|
+
content: "# AFS Controlled Vocabulary\n\n- categories — provider classification (single-select)\n- tags — capability tags (multi-select)\n",
|
|
620
|
+
meta: {
|
|
621
|
+
kind: "afs:directory",
|
|
622
|
+
childrenCount: 2
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
async readVocabularyCategories(_ctx) {
|
|
627
|
+
return {
|
|
628
|
+
id: "categories",
|
|
629
|
+
path: "/.vocabulary/categories",
|
|
630
|
+
content: `# AFS Provider Categories\n\nControlled vocabulary — single-select per provider.\n\n${AFS_CATEGORIES.map((c) => `- ${c}`).join("\n")}\n`,
|
|
631
|
+
meta: { kind: "registry:vocabulary" }
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
async readVocabularyTags(_ctx) {
|
|
635
|
+
return {
|
|
636
|
+
id: "tags",
|
|
637
|
+
path: "/.vocabulary/tags",
|
|
638
|
+
content: `# AFS Capability Tags\n\nControlled vocabulary — multi-select per provider.\n\n${CAPABILITY_TAGS.map((t) => `- ${t}`).join("\n")}\n`,
|
|
639
|
+
meta: { kind: "registry:vocabulary" }
|
|
640
|
+
};
|
|
641
|
+
}
|
|
932
642
|
async rootMeta(_ctx) {
|
|
933
643
|
return {
|
|
934
644
|
id: ".meta",
|
|
@@ -940,10 +650,58 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
940
650
|
},
|
|
941
651
|
meta: {
|
|
942
652
|
kind: "registry:root",
|
|
943
|
-
childrenCount:
|
|
653
|
+
childrenCount: 5
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
async recipesMeta(_ctx) {
|
|
658
|
+
const recipes = this.getRecipes();
|
|
659
|
+
return {
|
|
660
|
+
id: ".meta",
|
|
661
|
+
path: "/recipes/.meta",
|
|
662
|
+
content: { count: recipes.length },
|
|
663
|
+
meta: {
|
|
664
|
+
kind: "afs:directory",
|
|
665
|
+
childrenCount: recipes.length
|
|
944
666
|
}
|
|
945
667
|
};
|
|
946
668
|
}
|
|
669
|
+
async recipeMeta(ctx) {
|
|
670
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
671
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
672
|
+
return {
|
|
673
|
+
id: ".meta",
|
|
674
|
+
path: joinURL("/recipes", recipe.name, ".meta"),
|
|
675
|
+
content: {
|
|
676
|
+
name: recipe.name,
|
|
677
|
+
category: recipe.category
|
|
678
|
+
},
|
|
679
|
+
meta: {
|
|
680
|
+
kind: "registry:recipe",
|
|
681
|
+
childrenCount: 2
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
async recipeManifestMeta(ctx) {
|
|
686
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
687
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
688
|
+
return {
|
|
689
|
+
id: ".meta",
|
|
690
|
+
path: joinURL("/recipes", recipe.name, "manifest.json", ".meta"),
|
|
691
|
+
content: { format: "json" },
|
|
692
|
+
meta: { kind: "afs:file" }
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
async recipeReadmeMeta(ctx) {
|
|
696
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
697
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
698
|
+
return {
|
|
699
|
+
id: ".meta",
|
|
700
|
+
path: joinURL("/recipes", recipe.name, "README.md", ".meta"),
|
|
701
|
+
content: { format: "markdown" },
|
|
702
|
+
meta: { kind: "afs:file" }
|
|
703
|
+
};
|
|
704
|
+
}
|
|
947
705
|
async providersMeta(_ctx) {
|
|
948
706
|
return {
|
|
949
707
|
id: ".meta",
|
|
@@ -992,6 +750,26 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
992
750
|
meta: { kind: "afs:file" }
|
|
993
751
|
};
|
|
994
752
|
}
|
|
753
|
+
async treeSchemaJsonMeta(ctx) {
|
|
754
|
+
const provider = this.findProvider(ctx.params.name);
|
|
755
|
+
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
756
|
+
return {
|
|
757
|
+
id: ".meta",
|
|
758
|
+
path: joinURL("/providers", provider.name, "tree-schema.json", ".meta"),
|
|
759
|
+
content: { format: "json" },
|
|
760
|
+
meta: { kind: "afs:file" }
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
async agentMdMeta(ctx) {
|
|
764
|
+
const provider = this.findProvider(ctx.params.name);
|
|
765
|
+
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
766
|
+
return {
|
|
767
|
+
id: ".meta",
|
|
768
|
+
path: joinURL("/providers", provider.name, "AGENT.md", ".meta"),
|
|
769
|
+
content: { format: "markdown" },
|
|
770
|
+
meta: { kind: "afs:file" }
|
|
771
|
+
};
|
|
772
|
+
}
|
|
995
773
|
async byCategoryMeta(_ctx) {
|
|
996
774
|
return {
|
|
997
775
|
id: ".meta",
|
|
@@ -1004,18 +782,18 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1004
782
|
};
|
|
1005
783
|
}
|
|
1006
784
|
async categoryMeta(ctx) {
|
|
1007
|
-
const providers
|
|
1008
|
-
if (!providers
|
|
785
|
+
const providers = this.buildByCategory().get(ctx.params.category);
|
|
786
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
1009
787
|
return {
|
|
1010
788
|
id: ".meta",
|
|
1011
789
|
path: joinURL("/by-category", ctx.params.category, ".meta"),
|
|
1012
790
|
content: {
|
|
1013
791
|
category: ctx.params.category,
|
|
1014
|
-
count: providers
|
|
792
|
+
count: providers.length
|
|
1015
793
|
},
|
|
1016
794
|
meta: {
|
|
1017
795
|
kind: "afs:directory",
|
|
1018
|
-
childrenCount: providers
|
|
796
|
+
childrenCount: providers.length
|
|
1019
797
|
}
|
|
1020
798
|
};
|
|
1021
799
|
}
|
|
@@ -1041,18 +819,18 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1041
819
|
};
|
|
1042
820
|
}
|
|
1043
821
|
async tagMeta(ctx) {
|
|
1044
|
-
const providers
|
|
1045
|
-
if (!providers
|
|
822
|
+
const providers = this.buildByTag().get(ctx.params.tag);
|
|
823
|
+
if (!providers) throw new AFSNotFoundError(ctx.path);
|
|
1046
824
|
return {
|
|
1047
825
|
id: ".meta",
|
|
1048
826
|
path: joinURL("/by-tag", ctx.params.tag, ".meta"),
|
|
1049
827
|
content: {
|
|
1050
828
|
tag: ctx.params.tag,
|
|
1051
|
-
count: providers
|
|
829
|
+
count: providers.length
|
|
1052
830
|
},
|
|
1053
831
|
meta: {
|
|
1054
832
|
kind: "afs:directory",
|
|
1055
|
-
childrenCount: providers
|
|
833
|
+
childrenCount: providers.length
|
|
1056
834
|
}
|
|
1057
835
|
};
|
|
1058
836
|
}
|
|
@@ -1066,6 +844,30 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1066
844
|
meta: { kind: "registry:provider" }
|
|
1067
845
|
};
|
|
1068
846
|
}
|
|
847
|
+
async vocabularyMeta(_ctx) {
|
|
848
|
+
return {
|
|
849
|
+
id: ".meta",
|
|
850
|
+
path: "/.vocabulary/.meta",
|
|
851
|
+
content: { childrenCount: 2 },
|
|
852
|
+
meta: { kind: "afs:directory" }
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
async vocabularyCategoriesMeta(_ctx) {
|
|
856
|
+
return {
|
|
857
|
+
id: ".meta",
|
|
858
|
+
path: "/.vocabulary/categories/.meta",
|
|
859
|
+
content: { count: AFS_CATEGORIES.length },
|
|
860
|
+
meta: { kind: "registry:vocabulary" }
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
async vocabularyTagsMeta(_ctx) {
|
|
864
|
+
return {
|
|
865
|
+
id: ".meta",
|
|
866
|
+
path: "/.vocabulary/tags/.meta",
|
|
867
|
+
content: { count: CAPABILITY_TAGS.length },
|
|
868
|
+
meta: { kind: "registry:vocabulary" }
|
|
869
|
+
};
|
|
870
|
+
}
|
|
1069
871
|
async listRootActions(_ctx) {
|
|
1070
872
|
return { data: [{
|
|
1071
873
|
id: "search",
|
|
@@ -1076,23 +878,64 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1076
878
|
},
|
|
1077
879
|
actions: [{
|
|
1078
880
|
name: "search",
|
|
1079
|
-
description: "Search for providers
|
|
881
|
+
description: "Search for providers. Use category/tags for structured filtering, query for full-text search.",
|
|
1080
882
|
inputSchema: {
|
|
1081
883
|
type: "object",
|
|
1082
|
-
properties: {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
884
|
+
properties: {
|
|
885
|
+
query: {
|
|
886
|
+
type: "string",
|
|
887
|
+
description: "Full-text search across name, description, tags"
|
|
888
|
+
},
|
|
889
|
+
category: {
|
|
890
|
+
type: "string",
|
|
891
|
+
description: "Exact category match (e.g. storage, database, messaging)"
|
|
892
|
+
},
|
|
893
|
+
tags: {
|
|
894
|
+
type: "array",
|
|
895
|
+
items: { type: "string" },
|
|
896
|
+
description: "Filter by tags — providers must have ALL specified tags"
|
|
897
|
+
},
|
|
898
|
+
type: {
|
|
899
|
+
type: "string",
|
|
900
|
+
enum: ["provider", "recipe"],
|
|
901
|
+
description: "Filter by entry type"
|
|
902
|
+
}
|
|
903
|
+
}
|
|
1086
904
|
}
|
|
1087
905
|
}]
|
|
1088
906
|
}] };
|
|
1089
907
|
}
|
|
1090
908
|
async searchProviders(_ctx, args) {
|
|
909
|
+
const query = args.query || "";
|
|
910
|
+
const filterCategory = args.category;
|
|
911
|
+
const filterTags = args.tags;
|
|
912
|
+
const filterType = args.type;
|
|
913
|
+
let matched = [...this.providers];
|
|
914
|
+
if (filterCategory) matched = matched.filter((p) => p.category === filterCategory);
|
|
915
|
+
if (filterTags && filterTags.length > 0) matched = matched.filter((p) => {
|
|
916
|
+
const caps = p.capabilityTags || [];
|
|
917
|
+
return filterTags.every((t) => caps.includes(t));
|
|
918
|
+
});
|
|
919
|
+
if (filterType) matched = matched.filter((p) => (p.type || "provider") === filterType);
|
|
920
|
+
if (query) {
|
|
921
|
+
const q = query.toLowerCase();
|
|
922
|
+
matched = matched.filter((p) => p.name.toLowerCase().includes(q) || p.description.toLowerCase().includes(q) || p.category.toLowerCase().includes(q) || (p.tags || []).some((t) => t.toLowerCase().includes(q)) || (p.capabilityTags || []).some((t) => t.toLowerCase().includes(q)) || (p.useCases || []).some((u) => u.toLowerCase().includes(q)));
|
|
923
|
+
}
|
|
1091
924
|
return {
|
|
1092
925
|
success: true,
|
|
1093
926
|
data: {
|
|
1094
|
-
query
|
|
1095
|
-
|
|
927
|
+
query,
|
|
928
|
+
...filterCategory ? { category: filterCategory } : {},
|
|
929
|
+
...filterTags ? { tags: filterTags } : {},
|
|
930
|
+
...filterType ? { type: filterType } : {},
|
|
931
|
+
count: matched.length,
|
|
932
|
+
providers: matched.map((p) => ({
|
|
933
|
+
name: p.name,
|
|
934
|
+
category: p.category,
|
|
935
|
+
capabilityTags: p.capabilityTags,
|
|
936
|
+
type: p.type || "provider",
|
|
937
|
+
description: firstSentence(p.description)
|
|
938
|
+
}))
|
|
1096
939
|
}
|
|
1097
940
|
};
|
|
1098
941
|
}
|
|
@@ -1105,7 +948,7 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1105
948
|
properties: {
|
|
1106
949
|
path: {
|
|
1107
950
|
type: "string",
|
|
1108
|
-
description: "Mount path"
|
|
951
|
+
description: "Mount path (default: /{provider-name})"
|
|
1109
952
|
},
|
|
1110
953
|
uri: {
|
|
1111
954
|
type: "string",
|
|
@@ -1140,7 +983,96 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1140
983
|
},
|
|
1141
984
|
...provider.schema?.properties ?? {}
|
|
1142
985
|
},
|
|
1143
|
-
required: [
|
|
986
|
+
required: [...provider.schema?.required ?? []]
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
async listRecipeActions(ctx) {
|
|
990
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
991
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
992
|
+
const mountSchema = {
|
|
993
|
+
type: "object",
|
|
994
|
+
properties: {
|
|
995
|
+
path: {
|
|
996
|
+
type: "string",
|
|
997
|
+
description: `Mount path (default: /modules/${recipe.name})`
|
|
998
|
+
},
|
|
999
|
+
uri: {
|
|
1000
|
+
type: "string",
|
|
1001
|
+
description: `Full MCP URI (default: ${recipe.uriTemplate})`
|
|
1002
|
+
},
|
|
1003
|
+
accessMode: {
|
|
1004
|
+
type: "string",
|
|
1005
|
+
enum: ["readonly", "readwrite"],
|
|
1006
|
+
description: "Access mode (default: readonly)"
|
|
1007
|
+
},
|
|
1008
|
+
description: {
|
|
1009
|
+
type: "string",
|
|
1010
|
+
description: "Human-readable description"
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
return { data: [{
|
|
1015
|
+
id: "mount",
|
|
1016
|
+
path: joinURL("/recipes", recipe.name, ".actions", "mount"),
|
|
1017
|
+
meta: {
|
|
1018
|
+
kind: "afs:executable",
|
|
1019
|
+
kinds: ["afs:executable", "afs:node"],
|
|
1020
|
+
description: `Mount the ${recipe.name} recipe`,
|
|
1021
|
+
inputSchema: mountSchema
|
|
1022
|
+
},
|
|
1023
|
+
actions: [{
|
|
1024
|
+
name: "mount",
|
|
1025
|
+
description: `Mount the ${recipe.name} recipe`,
|
|
1026
|
+
inputSchema: mountSchema
|
|
1027
|
+
}]
|
|
1028
|
+
}] };
|
|
1029
|
+
}
|
|
1030
|
+
async readRecipeMountAction(ctx) {
|
|
1031
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
1032
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
1033
|
+
const mountSchema = {
|
|
1034
|
+
type: "object",
|
|
1035
|
+
properties: {
|
|
1036
|
+
path: {
|
|
1037
|
+
type: "string",
|
|
1038
|
+
description: `Mount path (default: /modules/${recipe.name})`
|
|
1039
|
+
},
|
|
1040
|
+
uri: {
|
|
1041
|
+
type: "string",
|
|
1042
|
+
description: `Full MCP URI (default: ${recipe.uriTemplate})`
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
return {
|
|
1047
|
+
id: "mount",
|
|
1048
|
+
path: joinURL("/recipes", recipe.name, ".actions", "mount"),
|
|
1049
|
+
content: {
|
|
1050
|
+
description: `Mount the ${recipe.name} recipe`,
|
|
1051
|
+
inputSchema: mountSchema
|
|
1052
|
+
},
|
|
1053
|
+
meta: {
|
|
1054
|
+
kind: "afs:executable",
|
|
1055
|
+
kinds: ["afs:executable", "afs:node"],
|
|
1056
|
+
description: `Mount the ${recipe.name} recipe`,
|
|
1057
|
+
inputSchema: mountSchema
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
async mountRecipe(ctx, args) {
|
|
1062
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
1063
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
1064
|
+
if (!this.loadProviderFn) throw new Error("loadProvider not configured — Registry was not mounted on an AFS instance");
|
|
1065
|
+
const mountPath = typeof args.path === "string" && args.path.trim() !== "" ? args.path.trim() : `/modules/${recipe.name}`;
|
|
1066
|
+
const uri = typeof args.uri === "string" && args.uri.trim() !== "" ? args.uri.trim() : recipe.uriTemplate;
|
|
1067
|
+
const { path: _path, uri: _uri, ...options } = args;
|
|
1068
|
+
await this.loadProviderFn(uri, mountPath, Object.keys(options).length > 0 ? options : void 0);
|
|
1069
|
+
return {
|
|
1070
|
+
success: true,
|
|
1071
|
+
data: {
|
|
1072
|
+
recipe: recipe.name,
|
|
1073
|
+
uri,
|
|
1074
|
+
path: mountPath
|
|
1075
|
+
}
|
|
1144
1076
|
};
|
|
1145
1077
|
}
|
|
1146
1078
|
async listProviderActions(ctx) {
|
|
@@ -1152,7 +1084,9 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1152
1084
|
path: joinURL("/providers", provider.name, ".actions", "mount"),
|
|
1153
1085
|
meta: {
|
|
1154
1086
|
kind: "afs:executable",
|
|
1155
|
-
kinds: ["afs:executable", "afs:node"]
|
|
1087
|
+
kinds: ["afs:executable", "afs:node"],
|
|
1088
|
+
description: `Mount the ${provider.name} provider`,
|
|
1089
|
+
inputSchema: mountSchema
|
|
1156
1090
|
},
|
|
1157
1091
|
actions: [{
|
|
1158
1092
|
name: "mount",
|
|
@@ -1184,8 +1118,7 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1184
1118
|
const provider = this.findProvider(ctx.params.name);
|
|
1185
1119
|
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
1186
1120
|
if (!this.loadProviderFn) throw new Error("loadProvider not configured — Registry was not mounted on an AFS instance");
|
|
1187
|
-
|
|
1188
|
-
const mountPath = args.path;
|
|
1121
|
+
const mountPath = typeof args.path === "string" && args.path.trim() !== "" ? args.path.trim() : `/${provider.name}`;
|
|
1189
1122
|
let uri = args.uri;
|
|
1190
1123
|
if (!uri) {
|
|
1191
1124
|
const varNames = getTemplateVariableNames(provider.uriTemplate);
|
|
@@ -1214,32 +1147,119 @@ var AFSRegistry = class extends AFSBaseProvider {
|
|
|
1214
1147
|
}
|
|
1215
1148
|
async searchRoot(_ctx, query, options) {
|
|
1216
1149
|
const q = query.toLowerCase();
|
|
1217
|
-
let matched = this.providers.filter((p) => p.name.toLowerCase().includes(q) || p.description.toLowerCase().includes(q) || p.category.toLowerCase().includes(q) || p.uriTemplate.toLowerCase().includes(q) || (p.tags || []).some((t) => t.toLowerCase().includes(q)) || (p.useCases || []).some((u) => u.toLowerCase().includes(q)));
|
|
1150
|
+
let matched = this.providers.filter((p) => p.name.toLowerCase().includes(q) || p.description.toLowerCase().includes(q) || p.category.toLowerCase().includes(q) || p.uriTemplate.toLowerCase().includes(q) || (p.tags || []).some((t) => t.toLowerCase().includes(q)) || (p.capabilityTags || []).some((t) => t.toLowerCase().includes(q)) || (p.useCases || []).some((u) => u.toLowerCase().includes(q)));
|
|
1218
1151
|
if (options?.limit !== void 0 && matched.length > options.limit) matched = matched.slice(0, options.limit);
|
|
1219
1152
|
return { data: matched.map((p) => ({
|
|
1220
1153
|
id: p.name,
|
|
1221
1154
|
path: joinURL("/providers", p.name),
|
|
1222
|
-
summary: p.description,
|
|
1223
|
-
meta: {
|
|
1155
|
+
summary: firstSentence(p.description),
|
|
1156
|
+
meta: {
|
|
1157
|
+
kind: "registry:provider",
|
|
1158
|
+
category: p.category,
|
|
1159
|
+
capabilityTags: p.capabilityTags
|
|
1160
|
+
}
|
|
1224
1161
|
})) };
|
|
1225
1162
|
}
|
|
1226
|
-
async
|
|
1163
|
+
async explainProvider(ctx) {
|
|
1164
|
+
const provider = this.findProvider(ctx.params.name);
|
|
1165
|
+
if (!provider) throw new AFSNotFoundError(ctx.path);
|
|
1166
|
+
const agentMd = this.loadAgentMd(provider);
|
|
1167
|
+
if (agentMd) {
|
|
1168
|
+
const lines$1 = [agentMd];
|
|
1169
|
+
if (provider.schema) {
|
|
1170
|
+
const props = provider.schema.properties;
|
|
1171
|
+
const required = new Set(provider.schema.required ?? []);
|
|
1172
|
+
if (props) {
|
|
1173
|
+
lines$1.push("", "## Configuration", "");
|
|
1174
|
+
for (const [key, val] of Object.entries(props)) {
|
|
1175
|
+
const req = required.has(key) ? " **(required)**" : "";
|
|
1176
|
+
lines$1.push(`- \`${key}\` (${val.type ?? "string"})${req} — ${val.description ?? ""}`);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
lines$1.push("", "## Actions", "", "- `mount` — Mount this provider into AFS");
|
|
1181
|
+
return {
|
|
1182
|
+
format: "markdown",
|
|
1183
|
+
content: lines$1.join("\n")
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
const lines = [
|
|
1187
|
+
`# ${provider.name}`,
|
|
1188
|
+
"",
|
|
1189
|
+
provider.description,
|
|
1190
|
+
"",
|
|
1191
|
+
`**Category:** ${provider.category}`,
|
|
1192
|
+
`**URI Template:** \`${provider.uriTemplate}\``,
|
|
1193
|
+
`**Type:** ${provider.type || "provider"}`
|
|
1194
|
+
];
|
|
1195
|
+
if (provider.tags?.length) lines.push(`**Tags:** ${provider.tags.join(", ")}`);
|
|
1196
|
+
if (provider.useCases?.length) lines.push("", "## Use Cases", "", ...provider.useCases.map((u) => `- ${u}`));
|
|
1197
|
+
if (provider.schema) {
|
|
1198
|
+
const props = provider.schema.properties;
|
|
1199
|
+
const required = new Set(provider.schema.required ?? []);
|
|
1200
|
+
if (props) {
|
|
1201
|
+
lines.push("", "## Configuration", "");
|
|
1202
|
+
for (const [key, val] of Object.entries(props)) {
|
|
1203
|
+
const req = required.has(key) ? " **(required)**" : "";
|
|
1204
|
+
lines.push(`- \`${key}\` (${val.type ?? "string"})${req} — ${val.description ?? ""}`);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
lines.push("", "## Actions", "", "- `mount` — Mount this provider into AFS");
|
|
1209
|
+
return {
|
|
1210
|
+
format: "markdown",
|
|
1211
|
+
content: lines.join("\n")
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
async explainRecipe(ctx) {
|
|
1215
|
+
const recipe = this.findRecipe(ctx.params.name);
|
|
1216
|
+
if (!recipe) throw new AFSNotFoundError(ctx.path);
|
|
1217
|
+
const lines = [
|
|
1218
|
+
`# ${recipe.name} (recipe)`,
|
|
1219
|
+
"",
|
|
1220
|
+
recipe.description,
|
|
1221
|
+
"",
|
|
1222
|
+
`**Category:** ${recipe.category}`,
|
|
1223
|
+
`**URI:** \`${recipe.uriTemplate}\``,
|
|
1224
|
+
`**Type:** recipe`
|
|
1225
|
+
];
|
|
1226
|
+
if (recipe.tags?.length) lines.push(`**Tags:** ${recipe.tags.join(", ")}`);
|
|
1227
|
+
lines.push("", "## Actions", "", "- `mount` — Mount this recipe as an MCP provider", "", "*Note: Recipe capabilities depend on the external MCP server and cannot be verified until mounted.*");
|
|
1228
|
+
return {
|
|
1229
|
+
format: "markdown",
|
|
1230
|
+
content: lines.join("\n")
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
async explainFallback(ctx) {
|
|
1234
|
+
if (ctx.path === "/" || ctx.path === "") {
|
|
1235
|
+
const categories = Array.from(this.buildByCategory().keys()).sort();
|
|
1236
|
+
return {
|
|
1237
|
+
format: "markdown",
|
|
1238
|
+
content: [
|
|
1239
|
+
"# AFS Provider Registry",
|
|
1240
|
+
"",
|
|
1241
|
+
"Virtual file tree for discovering and mounting AFS providers.",
|
|
1242
|
+
"",
|
|
1243
|
+
"## Structure",
|
|
1244
|
+
"- `/providers/{name}/` — Provider details (manifest.json, README.md, .actions/mount)",
|
|
1245
|
+
"- `/by-category/{category}/` — Browse by category",
|
|
1246
|
+
"- `/by-tag/{tag}/` — Browse by tag",
|
|
1247
|
+
"- `/recipes/{name}/` — MCP recipe details",
|
|
1248
|
+
"- `/.actions/search` — Search with structured filters (category, tags, query)",
|
|
1249
|
+
"",
|
|
1250
|
+
`**Providers:** ${this.providers.filter((p) => (p.type || "provider") === "provider").length}`,
|
|
1251
|
+
`**Recipes:** ${this.getRecipes().length}`,
|
|
1252
|
+
`**Categories:** ${categories.join(", ")}`
|
|
1253
|
+
].join("\n")
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1227
1256
|
return {
|
|
1228
1257
|
format: "markdown",
|
|
1229
1258
|
content: [
|
|
1230
1259
|
"# AFS Provider Registry",
|
|
1231
1260
|
"",
|
|
1232
|
-
"
|
|
1233
|
-
""
|
|
1234
|
-
"## Structure",
|
|
1235
|
-
"- `/providers/{name}/manifest.json` — Provider metadata",
|
|
1236
|
-
"- `/providers/{name}/README.md` — Human-readable description",
|
|
1237
|
-
"- `/providers/{name}/.actions/mount` — Mount action",
|
|
1238
|
-
"- `/by-category/{category}/` — Browse by category",
|
|
1239
|
-
"- `/by-tag/{tag}/` — Browse by tag",
|
|
1240
|
-
"- `/.actions/search` — Full-text search across providers",
|
|
1241
|
-
"",
|
|
1242
|
-
`**Total providers:** ${this.providers.length}`
|
|
1261
|
+
"Use `explain /registry/providers/{name}` for provider-specific information.",
|
|
1262
|
+
"Use `search` action with `category` or `tags` params for structured discovery."
|
|
1243
1263
|
].join("\n")
|
|
1244
1264
|
};
|
|
1245
1265
|
}
|
|
@@ -1258,51 +1278,94 @@ __decorate([List("/by-tag")], AFSRegistry.prototype, "listTags", null);
|
|
|
1258
1278
|
__decorate([List("/by-category/:category/:name")], AFSRegistry.prototype, "listCategoryProviderChildren", null);
|
|
1259
1279
|
__decorate([List("/by-tag/:tag")], AFSRegistry.prototype, "listTagProviders", null);
|
|
1260
1280
|
__decorate([List("/by-tag/:tag/:name")], AFSRegistry.prototype, "listTagProviderChildren", null);
|
|
1261
|
-
__decorate([
|
|
1281
|
+
__decorate([
|
|
1282
|
+
List("/providers/:name/manifest.json"),
|
|
1283
|
+
List("/providers/:name/README.md"),
|
|
1284
|
+
List("/providers/:name/tree-schema.json"),
|
|
1285
|
+
List("/providers/:name/AGENT.md")
|
|
1286
|
+
], AFSRegistry.prototype, "listFileNode", null);
|
|
1287
|
+
__decorate([List("/recipes")], AFSRegistry.prototype, "listRecipes", null);
|
|
1288
|
+
__decorate([List("/recipes/:name")], AFSRegistry.prototype, "listRecipeContents", null);
|
|
1289
|
+
__decorate([List("/recipes/:name/manifest.json"), List("/recipes/:name/README.md")], AFSRegistry.prototype, "listRecipeFileNode", null);
|
|
1262
1290
|
__decorate([Read("/")], AFSRegistry.prototype, "readRoot", null);
|
|
1263
1291
|
__decorate([Read("/providers")], AFSRegistry.prototype, "readProviders", null);
|
|
1264
1292
|
__decorate([Read("/providers/:name")], AFSRegistry.prototype, "readProvider", null);
|
|
1265
1293
|
__decorate([Read("/providers/:name/manifest.json")], AFSRegistry.prototype, "readManifest", null);
|
|
1266
1294
|
__decorate([Read("/providers/:name/README.md")], AFSRegistry.prototype, "readReadme", null);
|
|
1295
|
+
__decorate([Read("/providers/:name/tree-schema.json")], AFSRegistry.prototype, "readTreeSchema", null);
|
|
1296
|
+
__decorate([Read("/providers/:name/AGENT.md")], AFSRegistry.prototype, "readAgentMd", null);
|
|
1267
1297
|
__decorate([Read("/by-category")], AFSRegistry.prototype, "readByCategory", null);
|
|
1268
1298
|
__decorate([Read("/by-category/:category")], AFSRegistry.prototype, "readCategory", null);
|
|
1269
1299
|
__decorate([Read("/by-category/:category/:name")], AFSRegistry.prototype, "readCategoryProvider", null);
|
|
1270
1300
|
__decorate([Read("/by-tag")], AFSRegistry.prototype, "readByTag", null);
|
|
1271
1301
|
__decorate([Read("/by-tag/:tag")], AFSRegistry.prototype, "readTag", null);
|
|
1272
1302
|
__decorate([Read("/by-tag/:tag/:name")], AFSRegistry.prototype, "readTagProvider", null);
|
|
1303
|
+
__decorate([Read("/recipes")], AFSRegistry.prototype, "readRecipes", null);
|
|
1304
|
+
__decorate([Read("/recipes/:name")], AFSRegistry.prototype, "readRecipe", null);
|
|
1305
|
+
__decorate([Read("/recipes/:name/manifest.json")], AFSRegistry.prototype, "readRecipeManifest", null);
|
|
1306
|
+
__decorate([Read("/recipes/:name/README.md")], AFSRegistry.prototype, "readRecipeReadme", null);
|
|
1273
1307
|
__decorate([Read("/.meta/.capabilities")], AFSRegistry.prototype, "readCapabilities", null);
|
|
1308
|
+
__decorate([List("/.vocabulary/categories"), List("/.vocabulary/tags")], AFSRegistry.prototype, "listVocabularyLeaf", null);
|
|
1309
|
+
__decorate([List("/.vocabulary")], AFSRegistry.prototype, "listVocabulary", null);
|
|
1310
|
+
__decorate([Read("/.vocabulary")], AFSRegistry.prototype, "readVocabulary", null);
|
|
1311
|
+
__decorate([Read("/.vocabulary/categories")], AFSRegistry.prototype, "readVocabularyCategories", null);
|
|
1312
|
+
__decorate([Read("/.vocabulary/tags")], AFSRegistry.prototype, "readVocabularyTags", null);
|
|
1274
1313
|
__decorate([Meta("/")], AFSRegistry.prototype, "rootMeta", null);
|
|
1314
|
+
__decorate([Meta("/recipes")], AFSRegistry.prototype, "recipesMeta", null);
|
|
1315
|
+
__decorate([Meta("/recipes/:name")], AFSRegistry.prototype, "recipeMeta", null);
|
|
1316
|
+
__decorate([Meta("/recipes/:name/manifest.json")], AFSRegistry.prototype, "recipeManifestMeta", null);
|
|
1317
|
+
__decorate([Meta("/recipes/:name/README.md")], AFSRegistry.prototype, "recipeReadmeMeta", null);
|
|
1275
1318
|
__decorate([Meta("/providers")], AFSRegistry.prototype, "providersMeta", null);
|
|
1276
1319
|
__decorate([Meta("/providers/:name")], AFSRegistry.prototype, "providerMeta", null);
|
|
1277
1320
|
__decorate([Meta("/providers/:name/manifest.json")], AFSRegistry.prototype, "manifestMeta", null);
|
|
1278
1321
|
__decorate([Meta("/providers/:name/README.md")], AFSRegistry.prototype, "readmeMeta", null);
|
|
1322
|
+
__decorate([Meta("/providers/:name/tree-schema.json")], AFSRegistry.prototype, "treeSchemaJsonMeta", null);
|
|
1323
|
+
__decorate([Meta("/providers/:name/AGENT.md")], AFSRegistry.prototype, "agentMdMeta", null);
|
|
1279
1324
|
__decorate([Meta("/by-category")], AFSRegistry.prototype, "byCategoryMeta", null);
|
|
1280
1325
|
__decorate([Meta("/by-category/:category")], AFSRegistry.prototype, "categoryMeta", null);
|
|
1281
1326
|
__decorate([Meta("/by-category/:category/:name")], AFSRegistry.prototype, "categoryProviderMeta", null);
|
|
1282
1327
|
__decorate([Meta("/by-tag")], AFSRegistry.prototype, "byTagMeta", null);
|
|
1283
1328
|
__decorate([Meta("/by-tag/:tag")], AFSRegistry.prototype, "tagMeta", null);
|
|
1284
1329
|
__decorate([Meta("/by-tag/:tag/:name")], AFSRegistry.prototype, "tagProviderMeta", null);
|
|
1330
|
+
__decorate([Meta("/.vocabulary")], AFSRegistry.prototype, "vocabularyMeta", null);
|
|
1331
|
+
__decorate([Meta("/.vocabulary/categories")], AFSRegistry.prototype, "vocabularyCategoriesMeta", null);
|
|
1332
|
+
__decorate([Meta("/.vocabulary/tags")], AFSRegistry.prototype, "vocabularyTagsMeta", null);
|
|
1285
1333
|
__decorate([Actions("/")], AFSRegistry.prototype, "listRootActions", null);
|
|
1286
1334
|
__decorate([Actions.Exec("/", "search")], AFSRegistry.prototype, "searchProviders", null);
|
|
1335
|
+
__decorate([Actions("/recipes/:name")], AFSRegistry.prototype, "listRecipeActions", null);
|
|
1336
|
+
__decorate([Read("/recipes/:name/.actions/mount")], AFSRegistry.prototype, "readRecipeMountAction", null);
|
|
1337
|
+
__decorate([Actions.Exec("/recipes/:name", "mount")], AFSRegistry.prototype, "mountRecipe", null);
|
|
1287
1338
|
__decorate([Actions("/providers/:name")], AFSRegistry.prototype, "listProviderActions", null);
|
|
1288
1339
|
__decorate([Read("/providers/:name/.actions/mount")], AFSRegistry.prototype, "readMountAction", null);
|
|
1289
1340
|
__decorate([Actions.Exec("/providers/:name", "mount")], AFSRegistry.prototype, "mountProvider", null);
|
|
1290
1341
|
__decorate([Search("/")], AFSRegistry.prototype, "searchRoot", null);
|
|
1291
|
-
__decorate([Explain("/:
|
|
1342
|
+
__decorate([Explain("/providers/:name")], AFSRegistry.prototype, "explainProvider", null);
|
|
1343
|
+
__decorate([Explain("/recipes/:name")], AFSRegistry.prototype, "explainRecipe", null);
|
|
1344
|
+
__decorate([Explain("/:path*")], AFSRegistry.prototype, "explainFallback", null);
|
|
1292
1345
|
__decorate([
|
|
1293
1346
|
Stat("/"),
|
|
1294
1347
|
Stat("/providers"),
|
|
1295
1348
|
Stat("/providers/:name"),
|
|
1296
1349
|
Stat("/providers/:name/manifest.json"),
|
|
1297
1350
|
Stat("/providers/:name/README.md"),
|
|
1351
|
+
Stat("/providers/:name/tree-schema.json"),
|
|
1352
|
+
Stat("/providers/:name/AGENT.md"),
|
|
1298
1353
|
Stat("/by-category"),
|
|
1299
1354
|
Stat("/by-category/:category"),
|
|
1300
1355
|
Stat("/by-category/:category/:name"),
|
|
1301
1356
|
Stat("/by-tag"),
|
|
1302
1357
|
Stat("/by-tag/:tag"),
|
|
1303
|
-
Stat("/by-tag/:tag/:name")
|
|
1358
|
+
Stat("/by-tag/:tag/:name"),
|
|
1359
|
+
Stat("/recipes"),
|
|
1360
|
+
Stat("/recipes/:name"),
|
|
1361
|
+
Stat("/recipes/:name/manifest.json"),
|
|
1362
|
+
Stat("/recipes/:name/README.md"),
|
|
1363
|
+
Stat("/recipes/:name/.actions/mount"),
|
|
1364
|
+
Stat("/.vocabulary"),
|
|
1365
|
+
Stat("/.vocabulary/categories"),
|
|
1366
|
+
Stat("/.vocabulary/tags")
|
|
1304
1367
|
], AFSRegistry.prototype, "statPath", null);
|
|
1305
1368
|
|
|
1306
1369
|
//#endregion
|
|
1307
|
-
export { AFSRegistry };
|
|
1370
|
+
export { AFSRegistry, clearScanCache, scanInstalledProviders };
|
|
1308
1371
|
//# sourceMappingURL=index.mjs.map
|