resourcexjs 2.5.0 → 2.5.2

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # resourcexjs
2
2
 
3
- ResourceX - Resource management protocol for AI Agents. Like npm for AI resources.
3
+ Resource management protocol for AI Agents. Like npm for AI resources (prompts, tools, agents, configs).
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,328 +10,459 @@ npm install resourcexjs
10
10
  bun add resourcexjs
11
11
  ```
12
12
 
13
+ **Requirements:** Node.js 22+ or Bun
14
+
13
15
  ## Quick Start
14
16
 
15
17
  ```typescript
16
- import { createRegistry, parseRXL, createRXM, createRXA } from "resourcexjs";
18
+ import { createResourceX } from "resourcexjs";
17
19
 
18
- // Create registry
19
- const registry = createRegistry();
20
+ const rx = createResourceX();
20
21
 
21
- // Prepare a resource
22
- const manifest = createRXM({
23
- name: "my-prompt",
24
- type: "text",
25
- version: "1.0.0",
26
- });
22
+ // Add a resource from local directory
23
+ await rx.add("./my-prompt");
27
24
 
28
- const rxr = {
29
- locator: parseRXL(manifest.toLocator()),
30
- manifest,
31
- archive: await createRXA({ content: "You are a helpful assistant." }),
32
- };
25
+ // Use and execute
26
+ const result = await rx.use("my-prompt:1.0.0");
27
+ const content = await result.execute();
28
+ console.log(content);
29
+ ```
30
+
31
+ ## Core Concepts
33
32
 
34
- // Add to registry
35
- await registry.add(rxr);
33
+ ResourceX uses four core primitives:
34
+
35
+ | Primitive | Description |
36
+ | --------- | --------------------------------------------------- |
37
+ | **RXL** | Resource Locator - unique identifier for a resource |
38
+ | **RXM** | Resource Manifest - metadata (name, type, version) |
39
+ | **RXA** | Resource Archive - content container (tar.gz) |
40
+ | **RXR** | Resource - complete object (RXL + RXM + RXA) |
41
+
42
+ ### Locator Format
43
+
44
+ ResourceX uses a Docker-style locator format:
36
45
 
37
- // Resolve and execute
38
- const resolved = await registry.resolve("localhost/my-prompt.text@1.0.0");
39
- const text = await resolved.execute();
40
- console.log(text); // "You are a helpful assistant."
46
+ ```
47
+ [registry/][path/]name[:tag]
41
48
  ```
42
49
 
43
- ## Core Concepts
50
+ - `name` - Resource name (required)
51
+ - `tag` - Version or label (optional, defaults to "latest")
52
+ - `registry` - Registry host (optional, e.g., `registry.example.com` or `localhost:3098`)
53
+ - `path` - Path within registry (optional)
44
54
 
45
- ### RXL - Resource Locator
55
+ Examples:
46
56
 
47
- Parse resource locator strings. Format: `[domain/path/]name[.type][@version]`
57
+ - `hello` - local resource with default tag "latest"
58
+ - `hello:1.0.0` - local resource with version
59
+ - `prompts/hello:1.0.0` - with path
60
+ - `registry.example.com/hello:1.0.0` - remote resource
61
+ - `localhost:3098/org/hello:latest` - with port and path
48
62
 
49
- ```typescript
50
- import { parseRXL } from "resourcexjs";
63
+ **Note:** The resource type (e.g., "text", "json") is specified in `resource.json`, not in the locator.
64
+
65
+ ### Resource Directory Structure
66
+
67
+ A resource directory contains:
68
+
69
+ ```
70
+ my-prompt/
71
+ ├── resource.json # Resource metadata (required)
72
+ └── content # Resource content (required for text/json/binary)
73
+ ```
74
+
75
+ Example `resource.json`:
76
+
77
+ ```json
78
+ {
79
+ "name": "my-prompt",
80
+ "type": "text",
81
+ "tag": "1.0.0"
82
+ }
83
+ ```
84
+
85
+ ### Storage Layout
51
86
 
52
- const rxl = parseRXL("deepractice.ai/sean/assistant.prompt@1.0.0");
87
+ Resources are stored in `~/.resourcex/`:
53
88
 
54
- rxl.domain; // "deepractice.ai"
55
- rxl.path; // "sean"
56
- rxl.name; // "assistant"
57
- rxl.type; // "prompt"
58
- rxl.version; // "1.0.0"
59
- rxl.toString(); // reconstructs the locator
60
89
  ```
90
+ ~/.resourcex/
91
+ ├── local/ # Local resources (no registry)
92
+ │ └── my-prompt/
93
+ │ └── 1.0.0/
94
+ │ ├── manifest.json
95
+ │ └── archive.tar.gz
96
+ ├── cache/ # Cached remote resources
97
+ │ └── registry.example.com/
98
+ │ └── hello/
99
+ │ └── 1.0.0/
100
+ └── linked/ # Development symlinks
101
+ └── dev-prompt/
102
+ └── 1.0.0 -> /path/to/dev
103
+ ```
104
+
105
+ ## API Reference
61
106
 
62
- ### RXM - Resource Manifest
107
+ ### createResourceX(config?)
63
108
 
64
- Create resource metadata:
109
+ Create a ResourceX client instance.
65
110
 
66
111
  ```typescript
67
- import { createRXM } from "resourcexjs";
68
-
69
- const manifest = createRXM({
70
- domain: "deepractice.ai", // optional, defaults to "localhost"
71
- path: "sean", // optional
72
- name: "assistant",
73
- type: "prompt",
74
- version: "1.0.0",
112
+ import { createResourceX } from "resourcexjs";
113
+
114
+ const rx = createResourceX({
115
+ path: "~/.resourcex", // Storage path (default: ~/.resourcex)
116
+ registry: "https://...", // Central registry URL (for push/pull)
117
+ types: [myCustomType], // Custom resource types
118
+ isolator: "none", // Sandbox: none | srt | cloudflare | e2b
75
119
  });
120
+ ```
121
+
122
+ ### Local Operations
123
+
124
+ #### rx.add(path)
76
125
 
77
- manifest.toLocator(); // "deepractice.ai/sean/assistant.prompt@1.0.0"
78
- manifest.toJSON(); // plain object
126
+ Add a resource from a local directory to local storage.
127
+
128
+ ```typescript
129
+ const resource = await rx.add("./my-prompt");
130
+ console.log(resource.locator); // "my-prompt:1.0.0"
79
131
  ```
80
132
 
81
- ### RXA - Resource Archive
133
+ #### rx.link(path)
82
134
 
83
- Archive container (tar.gz) for storage/transfer:
135
+ Link a directory for live development (symlink). Changes to the directory are immediately available.
84
136
 
85
137
  ```typescript
86
- import { createRXA } from "resourcexjs";
138
+ await rx.link("./dev-prompt");
139
+ ```
87
140
 
88
- // Single file
89
- const archive = await createRXA({ content: "Hello, World!" });
141
+ #### rx.unlink(locator)
90
142
 
91
- // Multiple files
92
- const archive = await createRXA({
93
- "index.ts": "export default 1",
94
- "styles.css": "body {}",
95
- });
143
+ Remove a development link.
96
144
 
97
- // Extract to package for file access
98
- const pkg = await archive.extract();
99
- const buffer = await pkg.file("content"); // Buffer
100
- const files = await pkg.files(); // Map<string, Buffer>
145
+ ```typescript
146
+ await rx.unlink("dev-prompt:1.0.0");
147
+ ```
148
+
149
+ #### rx.has(locator)
150
+
151
+ Check if a resource exists locally.
101
152
 
102
- // Archive methods
103
- const tarGzBuffer = await archive.buffer();
104
- const stream = archive.stream;
153
+ ```typescript
154
+ const exists = await rx.has("hello:1.0.0");
105
155
  ```
106
156
 
107
- ### RXR - Resource
157
+ #### rx.info(locator)
108
158
 
109
- Complete resource object (pure interface):
159
+ Get detailed resource information.
110
160
 
111
161
  ```typescript
112
- import type { RXR } from "resourcexjs";
162
+ const info = await rx.info("hello:1.0.0");
163
+ console.log(info);
164
+ // {
165
+ // locator: "hello:1.0.0",
166
+ // name: "hello",
167
+ // type: "text",
168
+ // tag: "1.0.0",
169
+ // files: ["content"]
170
+ // }
171
+ ```
113
172
 
114
- const rxr: RXR = {
115
- locator, // RXL
116
- manifest, // RXM
117
- archive, // RXA
118
- };
173
+ #### rx.remove(locator)
174
+
175
+ Remove a resource from local storage.
176
+
177
+ ```typescript
178
+ await rx.remove("hello:1.0.0");
119
179
  ```
120
180
 
121
- ### Registry
181
+ #### rx.use(locator)
122
182
 
123
- Resource storage and retrieval:
183
+ Load and prepare a resource for execution.
124
184
 
125
185
  ```typescript
126
- import { createRegistry, loadResource } from "resourcexjs";
186
+ const executable = await rx.use<string>("hello:1.0.0");
127
187
 
128
- const registry = createRegistry({
129
- path: "~/.resourcex", // optional
130
- types: [customType], // optional, defaults to built-in types
131
- isolator: "srt", // optional sandbox isolation
132
- });
188
+ // Execute with optional arguments
189
+ const content = await executable.execute();
133
190
 
134
- // Add from folder or RXR
135
- await registry.add("./my-prompt");
136
- await registry.add(rxr);
191
+ // Access schema (if defined by the type)
192
+ console.log(executable.schema);
193
+ ```
137
194
 
138
- // Link for development (symlink)
139
- await registry.link("./my-prompt");
195
+ Resolution order:
140
196
 
141
- // Resolve and execute
142
- const resolved = await registry.resolve("localhost/my-prompt.text@1.0.0");
143
- const text = await resolved.execute();
197
+ 1. Linked directories (development priority)
198
+ 2. Local storage
199
+ 3. Cache (previously pulled)
200
+ 4. Remote registry (auto-pull if configured)
144
201
 
145
- // Get raw RXR
146
- const rxr = await registry.get("localhost/my-prompt.text@1.0.0");
202
+ #### rx.search(query?)
147
203
 
148
- // Check existence
149
- const exists = await registry.exists("localhost/test.text@1.0.0");
204
+ Search local resources.
150
205
 
151
- // Delete
152
- await registry.delete("localhost/test.text@1.0.0");
206
+ ```typescript
207
+ // Search all
208
+ const all = await rx.search();
153
209
 
154
- // Search
155
- const results = await registry.search({ query: "assistant", limit: 10 });
210
+ // Search by keyword
211
+ const results = await rx.search("prompt");
212
+ // ["my-prompt:1.0.0", "system-prompt:2.0.0"]
156
213
  ```
157
214
 
158
- ### Resource Types
215
+ ### Remote Operations
216
+
217
+ #### rx.push(locator)
218
+
219
+ Push a local resource to the remote registry.
159
220
 
160
- Built-in types:
221
+ ```typescript
222
+ const rx = createResourceX({
223
+ registry: "https://registry.example.com",
224
+ });
161
225
 
162
- | Type | Aliases | Description |
163
- | -------- | ---------------- | -------------- |
164
- | `text` | txt, plaintext | Plain text |
165
- | `json` | config, manifest | JSON content |
166
- | `binary` | bin, blob, raw | Binary content |
226
+ await rx.add("./my-prompt");
227
+ await rx.push("my-prompt:1.0.0");
228
+ ```
167
229
 
168
- Custom types (requires bundling):
230
+ #### rx.pull(locator)
231
+
232
+ Pull a resource from the remote registry to local cache.
169
233
 
170
234
  ```typescript
171
- import { bundleResourceType, createRegistry } from "resourcexjs";
235
+ await rx.pull("hello:1.0.0");
236
+ // Resource is now cached locally
237
+ ```
238
+
239
+ ### Cache Operations
172
240
 
173
- // Bundle from source file
174
- const promptType = await bundleResourceType("./prompt.type.ts");
241
+ #### rx.clearCache(registry?)
175
242
 
176
- // Create registry with type
177
- const registry = createRegistry({
178
- types: [promptType],
243
+ Clear cached resources.
244
+
245
+ ```typescript
246
+ // Clear all cache
247
+ await rx.clearCache();
248
+
249
+ // Clear cache for specific registry
250
+ await rx.clearCache("registry.example.com");
251
+ ```
252
+
253
+ ### Extension
254
+
255
+ #### rx.supportType(type)
256
+
257
+ Add support for a custom resource type.
258
+
259
+ ```typescript
260
+ rx.supportType({
261
+ name: "prompt",
262
+ aliases: ["ai-prompt"],
263
+ description: "AI prompt template",
264
+ code: `({
265
+ async resolve(ctx) {
266
+ const template = new TextDecoder().decode(ctx.files["content"]);
267
+ return {
268
+ template,
269
+ render: (vars) => template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, k) => vars[k])
270
+ };
271
+ }
272
+ })`,
179
273
  });
274
+
275
+ const result = await rx.use("greeting:1.0.0");
276
+ const { template, render } = await result.execute();
277
+ console.log(render({ name: "World" }));
180
278
  ```
181
279
 
182
- ### Load Resources
280
+ ## Built-in Types
281
+
282
+ | Type | Aliases | Description | Output |
283
+ | -------- | ---------------- | ------------------ | ------------ |
284
+ | `text` | txt, plaintext | Plain text content | `string` |
285
+ | `json` | config, manifest | JSON content | `unknown` |
286
+ | `binary` | bin, blob, raw | Binary content | `Uint8Array` |
287
+
288
+ ## Core Primitives
183
289
 
184
- Load resources from folders:
290
+ For advanced use cases, you can work with core primitives directly:
185
291
 
186
292
  ```typescript
187
- import { loadResource, FolderLoader } from "resourcexjs";
293
+ import { parse, format, manifest, archive, resource, extract, wrap } from "resourcexjs";
188
294
 
189
- // Load from folder (uses FolderLoader by default)
190
- const rxr = await loadResource("./my-prompt");
295
+ // Parse locator string to RXL
296
+ const rxl = parse("hello:1.0.0");
297
+ console.log(rxl.name); // "hello"
298
+ console.log(rxl.tag); // "1.0.0"
191
299
 
192
- // Use custom loader
193
- const rxr = await loadResource("./my-prompt", {
194
- loader: new CustomLoader(),
300
+ // Format RXL back to string
301
+ const str = format(rxl); // "hello:1.0.0"
302
+
303
+ // Create manifest from definition
304
+ const rxm = manifest({
305
+ name: "hello",
306
+ type: "text",
307
+ tag: "1.0.0",
195
308
  });
309
+
310
+ // Create archive from files
311
+ const rxa = await archive({
312
+ content: Buffer.from("Hello, World!"),
313
+ });
314
+
315
+ // Create complete resource
316
+ const rxr = resource(rxm, rxa);
317
+
318
+ // Extract files from archive
319
+ const files = await extract(rxa); // Record<string, Buffer>
320
+
321
+ // Wrap raw buffer as archive
322
+ const wrapped = wrap(Buffer.from(tarGzData));
196
323
  ```
197
324
 
198
325
  ## ARP - Low-level I/O
199
326
 
200
- For direct file/network operations:
327
+ ResourceX includes ARP (Agent Resource Protocol) for direct file/network operations:
201
328
 
202
329
  ```typescript
203
330
  import { createARP } from "resourcexjs/arp";
204
331
 
205
- // createARP() includes rxr transport for ResourceX resources
206
332
  const arp = createARP();
207
333
 
208
- // Parse URL
209
- const arl = arp.parse("arp:text:file://./config.txt");
334
+ // File operations
335
+ const fileArl = arp.parse("arp:text:file:///path/to/file.txt");
336
+ const { content } = await fileArl.resolve();
337
+ await fileArl.deposit("new content");
338
+ await fileArl.exists();
339
+
340
+ // HTTP operations
341
+ const httpArl = arp.parse("arp:json:https://api.example.com/data");
342
+ const { content: data } = await httpArl.resolve();
343
+
344
+ // Access files inside resources (RXR transport)
345
+ const rxrArl = arp.parse("arp:text:rxr://hello:1.0.0/content");
346
+ const { content: fileContent } = await rxrArl.resolve();
347
+ ```
348
+
349
+ ## Configuration Options
350
+
351
+ ```typescript
352
+ interface ResourceXConfig {
353
+ /**
354
+ * Base path for local storage.
355
+ * Default: ~/.resourcex
356
+ */
357
+ path?: string;
358
+
359
+ /**
360
+ * Central registry URL for push/pull operations.
361
+ */
362
+ registry?: string;
363
+
364
+ /**
365
+ * Custom resource types to register.
366
+ */
367
+ types?: BundledType[];
368
+
369
+ /**
370
+ * Isolator type for resolver execution.
371
+ * - "none": No isolation (default, fastest)
372
+ * - "srt": OS-level isolation
373
+ * - "cloudflare": Container isolation
374
+ * - "e2b": MicroVM isolation
375
+ */
376
+ isolator?: IsolatorType;
377
+ }
378
+ ```
379
+
380
+ ## Types
210
381
 
211
- // Read
212
- const resource = await arl.resolve();
213
- console.log(resource.content); // string
382
+ ### Resource
214
383
 
215
- // Write
216
- await arl.deposit("hello world");
384
+ User-facing resource object returned by `add()` and `info()`.
217
385
 
218
- // Operations
219
- await arl.exists(); // boolean
220
- await arl.delete();
386
+ ```typescript
387
+ interface Resource {
388
+ locator: string; // Full locator string
389
+ registry?: string; // Registry host (if remote)
390
+ path?: string; // Path within registry
391
+ name: string; // Resource name
392
+ type: string; // Resource type
393
+ tag: string; // Version tag
394
+ files?: string[]; // Files in archive
395
+ }
396
+ ```
397
+
398
+ ### Executable
221
399
 
222
- // Access files inside resources
223
- const rxrArl = arp.parse("arp:text:rxr://localhost/my-prompt.text@1.0.0/content");
224
- const { content } = await rxrArl.resolve();
400
+ Result of `use()`.
401
+
402
+ ```typescript
403
+ interface Executable<T = unknown> {
404
+ execute: (args?: unknown) => Promise<T>;
405
+ schema?: unknown; // JSON schema for arguments
406
+ }
225
407
  ```
226
408
 
227
- ## Exports
409
+ ### BundledType
228
410
 
229
- ### Main Package (`resourcexjs`)
411
+ Custom resource type definition.
230
412
 
231
413
  ```typescript
232
- // Errors
233
- export { ResourceXError, LocatorError, ManifestError, ContentError };
234
- export { ResourceTypeError };
235
- export { RegistryError };
236
-
237
- // RXL (Locator)
238
- export { parseRXL };
239
- export type { RXL };
240
-
241
- // RXM (Manifest)
242
- export { createRXM };
243
- export type { RXM, ManifestData };
244
-
245
- // RXA (Archive) and RXP (Package)
246
- export { createRXA };
247
- export type { RXA, RXP, RXAInput, PathNode };
248
-
249
- // RXR (Resource)
250
- export type { RXR };
251
-
252
- // Type System
253
- export type {
254
- ResourceType,
255
- ResourceResolver,
256
- ResolvedResource,
257
- JSONSchema,
258
- BundledType,
259
- IsolatorType,
260
- };
261
- export { TypeHandlerChain, bundleResourceType };
262
- export { textType, jsonType, binaryType, builtinTypes };
263
-
264
- // Resource Loading
265
- export type { ResourceLoader, LoadResourceConfig };
266
- export { loadResource, FolderLoader };
267
-
268
- // Registry
269
- export type {
270
- Registry,
271
- RegistryConfig,
272
- ClientRegistryConfig,
273
- ServerRegistryConfig,
274
- CreateRegistryConfig,
275
- };
276
- export type { Storage, SearchOptions, DiscoveryResult, WellKnownResponse };
277
- export { DefaultRegistry, createRegistry, discoverRegistry, LocalStorage };
278
-
279
- // Middleware
280
- export { RegistryMiddleware, DomainValidation, withDomainValidation };
281
-
282
- // Version
283
- export const VERSION: string;
414
+ interface BundledType {
415
+ name: string; // Type name
416
+ aliases?: string[]; // Alternative names
417
+ description: string; // Human-readable description
418
+ schema?: JSONSchema; // Schema for resolver arguments
419
+ code: string; // Bundled resolver code
420
+ }
284
421
  ```
285
422
 
286
- ### ARP Package (`resourcexjs/arp`)
423
+ ## Error Handling
287
424
 
288
425
  ```typescript
289
- // Enhanced createARP with RxrTransport
290
- export { createARP, ARP, type ARPConfig };
291
- export { VERSION };
292
- export { ARPError, ParseError, TransportError, SemanticError };
293
- export type { ARI, ARL };
294
-
295
- // Transports
296
- export type { TransportHandler, TransportResult, TransportParams };
297
- export { FileTransportHandler, fileTransport };
298
- export { HttpTransportHandler, httpTransport, httpsTransport };
299
- export { RxrTransport, clearRegistryCache, type RxrTransportRegistry };
300
-
301
- // Semantics
302
- export type { Resource, SemanticHandler, ResourceMeta, SemanticContext };
303
- export type { TextResource, BinaryResource, BinaryInput };
304
- export { TextSemanticHandler, textSemantic };
305
- export { BinarySemanticHandler, binarySemantic };
426
+ import { RegistryError, ResourceTypeError } from "resourcexjs";
427
+
428
+ try {
429
+ await rx.use("unknown:1.0.0");
430
+ } catch (error) {
431
+ if (error instanceof RegistryError) {
432
+ console.error("Resource not found:", error.message);
433
+ }
434
+ }
306
435
  ```
307
436
 
308
- ## Error Hierarchy
437
+ Error hierarchy:
309
438
 
310
439
  ```
311
- Error
312
- ├── ResourceXError
313
- ├── LocatorError (RXL parsing)
314
- ├── ManifestError (RXM validation)
315
- └── ContentError (RXA/RXP operations)
316
- ├── ResourceTypeError (Type registration)
317
- ├── RegistryError (Registry operations)
318
- └── ARPError
319
- ├── ParseError (URL parsing)
320
- ├── TransportError (Transport operations)
321
- └── SemanticError (Semantic operations)
440
+ ResourceXError (base)
441
+ ├── LocatorError # RXL parsing errors
442
+ ├── ManifestError # RXM validation errors
443
+ ├── ContentError # RXA operations errors
444
+ └── DefinitionError # RXD validation errors
445
+
446
+ RegistryError # Registry operations
447
+ ResourceTypeError # Type not found
448
+
449
+ ARPError (base)
450
+ ├── ParseError # URL parsing
451
+ ├── TransportError # Transport operations
452
+ └── SemanticError # Semantic operations
322
453
  ```
323
454
 
324
- ## Packages
455
+ ## Related Packages
325
456
 
326
- | Package | Description |
327
- | ----------------------- | ----------------------------- |
328
- | `resourcexjs` | Main package (re-exports all) |
329
- | `@resourcexjs/core` | RXL, RXM, RXA, RXP, RXR |
330
- | `@resourcexjs/type` | Type system, bundler |
331
- | `@resourcexjs/loader` | Resource loading |
332
- | `@resourcexjs/registry` | Storage and retrieval |
333
- | `@resourcexjs/arp` | Low-level I/O protocol |
457
+ | Package | Description |
458
+ | ----------------------- | -------------------------------------- |
459
+ | `@resourcexjs/core` | Core primitives (RXL, RXM, RXA, RXR) |
460
+ | `@resourcexjs/type` | Type system and bundler |
461
+ | `@resourcexjs/storage` | Storage layer (FileSystem, Memory) |
462
+ | `@resourcexjs/registry` | Registry layer (Local, Mirror, Linked) |
463
+ | `@resourcexjs/loader` | Resource loading utilities |
464
+ | `@resourcexjs/arp` | Low-level I/O protocol |
334
465
 
335
466
  ## License
336
467
 
337
- MIT
468
+ Apache-2.0