@resourcexjs/core 2.4.1 → 2.5.1

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,8 +1,8 @@
1
1
  # @resourcexjs/core
2
2
 
3
- Core data structures for ResourceX.
3
+ Core primitives and types for ResourceX - the resource management protocol for AI Agents.
4
4
 
5
- > **Note**: For most use cases, use the main [`resourcexjs`](https://www.npmjs.com/package/resourcexjs) package. This package is for advanced usage.
5
+ > **Note**: For most use cases, use the main [`resourcexjs`](https://www.npmjs.com/package/resourcexjs) package. This package is for low-level operations.
6
6
 
7
7
  ## Installation
8
8
 
@@ -12,269 +12,370 @@ npm install @resourcexjs/core
12
12
  bun add @resourcexjs/core
13
13
  ```
14
14
 
15
- ## What's Inside
15
+ ## Core Concepts
16
16
 
17
- Core building blocks - pure data structures:
17
+ ResourceX uses a layered architecture with five core primitives:
18
18
 
19
- - **RXL** (Locator) - Resource locator string parser
20
- - **RXM** (Manifest) - Resource metadata
21
- - **RXA** (Archive) - Archive container for storage/transfer
22
- - **RXP** (Package) - Extracted files for runtime access
23
- - **RXR** (Resource) - Complete resource type
24
- - **Errors** - Error hierarchy
19
+ | Primitive | Description |
20
+ | --------- | -------------------------------------------------------- |
21
+ | **RXD** | Resource Definition - content of `resource.json` |
22
+ | **RXL** | Resource Locator - unique identifier for a resource |
23
+ | **RXM** | Resource Manifest - metadata stored within the resource |
24
+ | **RXA** | Resource Archive - tar.gz container for storage/transfer |
25
+ | **RXR** | Resource - complete resource (RXL + RXM + RXA) |
26
+
27
+ ### Locator Format
28
+
29
+ Docker-style format: `[registry/][path/]name[:tag]`
30
+
31
+ ```
32
+ hello -> name=hello, tag=latest
33
+ hello:1.0.0 -> name=hello, tag=1.0.0
34
+ prompts/hello:stable -> path=prompts, name=hello, tag=stable
35
+ localhost:3098/hello:1.0.0 -> registry=localhost:3098, name=hello, tag=1.0.0
36
+ registry.example.com/org/hello -> registry=registry.example.com, path=org, name=hello, tag=latest
37
+ ```
25
38
 
26
39
  ## API
27
40
 
28
- ### RXL - Resource Locator
41
+ ### `parse(locator: string): RXL`
29
42
 
30
- Parse resource locator strings. Format: `[domain/path/]name[.type][@version]`
43
+ Parse a locator string into an RXL object.
31
44
 
32
45
  ```typescript
33
- import { parseRXL } from "@resourcexjs/core";
46
+ import { parse } from "@resourcexjs/core";
47
+
48
+ const rxl = parse("registry.example.com/prompts/hello:1.0.0");
49
+ // {
50
+ // registry: "registry.example.com",
51
+ // path: "prompts",
52
+ // name: "hello",
53
+ // tag: "1.0.0"
54
+ // }
55
+
56
+ const simple = parse("hello");
57
+ // { registry: undefined, path: undefined, name: "hello", tag: "latest" }
58
+ ```
34
59
 
35
- const rxl = parseRXL("deepractice.ai/sean/assistant.prompt@1.0.0");
60
+ ### `format(rxl: RXL): string`
36
61
 
37
- rxl.domain; // "deepractice.ai"
38
- rxl.path; // "sean"
39
- rxl.name; // "assistant"
40
- rxl.type; // "prompt"
41
- rxl.version; // "1.0.0"
42
- rxl.toString(); // "deepractice.ai/sean/assistant.prompt@1.0.0"
62
+ Format an RXL object back to a locator string.
63
+
64
+ ```typescript
65
+ import { format } from "@resourcexjs/core";
66
+
67
+ format({ name: "hello", tag: "latest" });
68
+ // "hello"
69
+
70
+ format({ name: "hello", tag: "1.0.0" });
71
+ // "hello:1.0.0"
72
+
73
+ format({ registry: "localhost:3098", name: "hello", tag: "1.0.0" });
74
+ // "localhost:3098/hello:1.0.0"
43
75
  ```
44
76
 
45
- **Minimal locator:**
77
+ ### `define(input: unknown): RXD`
78
+
79
+ Parse and validate a resource definition (from `resource.json`).
46
80
 
47
81
  ```typescript
48
- parseRXL("name.text@1.0.0");
49
- // → domain: "localhost", path: undefined, name: "name", type: "text", version: "1.0.0"
82
+ import { define } from "@resourcexjs/core";
83
+
84
+ const rxd = define({
85
+ name: "my-prompt",
86
+ type: "text",
87
+ tag: "1.0.0",
88
+ description: "A helpful prompt",
89
+ author: "Alice",
90
+ });
91
+ // {
92
+ // name: "my-prompt",
93
+ // type: "text",
94
+ // tag: "1.0.0",
95
+ // description: "A helpful prompt",
96
+ // author: "Alice"
97
+ // }
50
98
  ```
51
99
 
52
- ### RXM - Resource Manifest
100
+ **Required fields**: `name`, `type`
101
+
102
+ **Optional fields**: `tag` (defaults to "latest"), `registry`, `path`, `description`, `author`, `license`, `keywords`, `repository`
103
+
104
+ > Note: `version` is accepted as an alias for `tag` for backward compatibility.
53
105
 
54
- Create and validate resource metadata:
106
+ ### `manifest(rxd: RXD): RXM`
107
+
108
+ Create a manifest from a definition. Extracts core metadata fields.
55
109
 
56
110
  ```typescript
57
- import { createRXM } from "@resourcexjs/core";
58
-
59
- const manifest = createRXM({
60
- domain: "deepractice.ai",
61
- path: "sean", // optional
62
- name: "assistant",
63
- type: "prompt",
64
- version: "1.0.0",
65
- description: "Optional description", // optional
66
- tags: ["optional", "tags"], // optional
111
+ import { define, manifest } from "@resourcexjs/core";
112
+
113
+ const rxd = define({
114
+ name: "my-prompt",
115
+ type: "text",
116
+ tag: "1.0.0",
117
+ description: "A helpful prompt", // not included in manifest
67
118
  });
68
119
 
69
- manifest.toLocator(); // → "deepractice.ai/sean/assistant.prompt@1.0.0"
70
- manifest.toJSON(); // plain object
120
+ const rxm = manifest(rxd);
121
+ // { name: "my-prompt", type: "text", tag: "1.0.0" }
71
122
  ```
72
123
 
73
- **Required fields**: `name`, `type`, `version`
124
+ ### `locate(rxm: RXM): RXL`
74
125
 
75
- **Optional fields**: `domain` (default: "localhost"), `path`, `description`, `tags`
126
+ Create a locator from a manifest.
76
127
 
77
- ### RXA - Resource Archive
128
+ ```typescript
129
+ import { locate } from "@resourcexjs/core";
130
+
131
+ const rxl = locate({
132
+ registry: "example.com",
133
+ path: "prompts",
134
+ name: "hello",
135
+ type: "text",
136
+ tag: "1.0.0",
137
+ });
138
+ // { registry: "example.com", path: "prompts", name: "hello", tag: "1.0.0" }
139
+ ```
78
140
 
79
- Archive container (tar.gz) for storage/transfer. Extract to RXP for file access:
141
+ ### `archive(files: Record<string, Buffer>): Promise<RXA>`
142
+
143
+ Create an archive from files. Output is in tar.gz format.
80
144
 
81
145
  ```typescript
82
- import { createRXA } from "@resourcexjs/core";
146
+ import { archive } from "@resourcexjs/core";
83
147
 
84
148
  // Single file
85
- const content = await createRXA({ content: "Hello, World!" });
149
+ const rxa = await archive({
150
+ content: Buffer.from("Hello, World!"),
151
+ });
86
152
 
87
153
  // Multiple files
88
- const content = await createRXA({
89
- "index.ts": "export default 1",
90
- "styles.css": "body {}",
154
+ const rxa = await archive({
155
+ "prompt.md": Buffer.from("# System Prompt\nYou are..."),
156
+ "config.json": Buffer.from('{"temperature": 0.7}'),
91
157
  });
92
158
 
93
159
  // Nested directories
94
- const content = await createRXA({
95
- "src/index.ts": "main code",
96
- "src/utils/helper.ts": "helper code",
160
+ const rxa = await archive({
161
+ "src/index.ts": Buffer.from("main code"),
162
+ "src/utils/helper.ts": Buffer.from("helper code"),
97
163
  });
98
164
 
99
- // From existing tar.gz buffer (for deserialization)
100
- const content = await createRXA({ buffer: tarGzBuffer });
101
-
102
- // Extract to package for file access
103
- const pkg = await content.extract();
104
- const buffer = await pkg.file("content"); // → Buffer
105
- const buffer = await pkg.file("src/index.ts"); // → Buffer
106
- const files = await pkg.files(); // → Map<string, Buffer>
107
- const paths = pkg.paths(); // → string[]
108
- const tree = pkg.tree(); // → PathNode[]
109
-
110
- // Archive methods
111
- const archiveBuffer = await content.buffer(); // → raw tar.gz Buffer
112
- const stream = content.stream; // → ReadableStream (tar.gz)
165
+ // Access raw archive data
166
+ const buffer = await rxa.buffer(); // tar.gz Buffer
167
+ const stream = rxa.stream; // ReadableStream<Uint8Array>
113
168
  ```
114
169
 
115
- ### RXR - Resource
170
+ ### `extract(rxa: RXA): Promise<Record<string, Buffer>>`
116
171
 
117
- Complete resource object (pure interface):
172
+ Extract files from an archive.
118
173
 
119
174
  ```typescript
120
- import type { RXR } from "@resourcexjs/core";
175
+ import { archive, extract } from "@resourcexjs/core";
121
176
 
122
- interface RXR {
123
- locator: RXL;
124
- manifest: RXM;
125
- archive: RXA;
126
- }
177
+ const rxa = await archive({
178
+ "hello.txt": Buffer.from("Hello!"),
179
+ "world.txt": Buffer.from("World!"),
180
+ });
127
181
 
128
- // Create from literals
129
- const rxr: RXR = { locator, manifest, archive };
182
+ const files = await extract(rxa);
183
+ // {
184
+ // "hello.txt": Buffer<...>,
185
+ // "world.txt": Buffer<...>
186
+ // }
130
187
  ```
131
188
 
132
- RXR is a pure DTO (Data Transfer Object) - no factory function needed.
189
+ ### `wrap(buffer: Buffer): RXA`
133
190
 
134
- ## Error Handling
191
+ Wrap an existing tar.gz buffer as an RXA. Useful for deserializing archives.
135
192
 
136
193
  ```typescript
137
- import { ResourceXError, LocatorError, ManifestError, ContentError } from "@resourcexjs/core";
194
+ import { wrap, extract } from "@resourcexjs/core";
138
195
 
139
- try {
140
- parseRXL("invalid-locator");
141
- } catch (error) {
142
- if (error instanceof LocatorError) {
143
- console.error("Invalid locator format");
144
- }
145
- }
196
+ // From storage or network
197
+ const tarGzBuffer = await fetchFromStorage();
146
198
 
147
- try {
148
- createRXM({ name: "test" }); // Missing required fields
149
- } catch (error) {
150
- if (error instanceof ManifestError) {
151
- console.error("Invalid manifest");
152
- }
153
- }
154
-
155
- try {
156
- const pkg = await archive.extract();
157
- await pkg.file("nonexistent");
158
- } catch (error) {
159
- if (error instanceof ContentError) {
160
- console.error("File not found in archive");
161
- }
162
- }
199
+ const rxa = wrap(tarGzBuffer);
200
+ const files = await extract(rxa);
163
201
  ```
164
202
 
165
- ### Error Hierarchy
203
+ ### `resource(rxm: RXM, rxa: RXA): RXR`
166
204
 
167
- ```
168
- ResourceXError (base)
169
- ├── LocatorError
170
- ├── ManifestError
171
- └── ContentError
205
+ Create a complete resource from manifest and archive.
206
+
207
+ ```typescript
208
+ import { define, manifest, archive, resource } from "@resourcexjs/core";
209
+
210
+ const rxd = define({ name: "hello", type: "text", tag: "1.0.0" });
211
+ const rxm = manifest(rxd);
212
+ const rxa = await archive({ content: Buffer.from("Hello!") });
213
+ const rxr = resource(rxm, rxa);
214
+ // {
215
+ // locator: { name: "hello", tag: "1.0.0" },
216
+ // manifest: { name: "hello", type: "text", tag: "1.0.0" },
217
+ // archive: RXA
218
+ // }
172
219
  ```
173
220
 
174
- ## Examples
221
+ ## Types
175
222
 
176
- ### Complete Resource Creation
223
+ ### RXD - Resource Definition
177
224
 
178
- ```typescript
179
- import { parseRXL, createRXM, createRXA } from "@resourcexjs/core";
180
- import type { RXR } from "@resourcexjs/core";
225
+ The content of `resource.json` file. Contains all metadata for a resource in development.
181
226
 
182
- // Create manifest
183
- const manifest = createRXM({
184
- domain: "deepractice.ai",
185
- name: "assistant",
186
- type: "prompt",
187
- version: "1.0.0",
188
- });
227
+ ```typescript
228
+ interface RXD {
229
+ readonly name: string; // Required
230
+ readonly type: string; // Required
231
+ readonly tag?: string; // Optional (defaults to "latest")
232
+ readonly registry?: string;
233
+ readonly path?: string;
234
+ readonly description?: string;
235
+ readonly author?: string;
236
+ readonly license?: string;
237
+ readonly keywords?: string[];
238
+ readonly repository?: string;
239
+ readonly [key: string]: unknown; // Additional fields allowed
240
+ }
241
+ ```
189
242
 
190
- // Create locator from manifest
191
- const locator = parseRXL(manifest.toLocator());
243
+ ### RXL - Resource Locator
192
244
 
193
- // Create archive (single file)
194
- const archive = await createRXA({ content: "You are a helpful assistant." });
245
+ Unique identifier for a resource.
195
246
 
196
- // Assemble RXR
197
- const rxr: RXR = {
198
- locator,
199
- manifest,
200
- archive,
201
- };
247
+ ```typescript
248
+ interface RXL {
249
+ readonly registry?: string; // e.g., "localhost:3098", "registry.example.com"
250
+ readonly path?: string; // e.g., "org", "prompts"
251
+ readonly name: string; // Resource name
252
+ readonly tag: string; // Tag (defaults to "latest")
253
+ }
202
254
  ```
203
255
 
204
- ### Multi-file Resource
256
+ ### RXM - Resource Manifest
257
+
258
+ Resource metadata stored within the resource.
205
259
 
206
260
  ```typescript
207
- import { createRXA } from "@resourcexjs/core";
261
+ interface RXM {
262
+ readonly registry?: string;
263
+ readonly path?: string;
264
+ readonly name: string;
265
+ readonly type: string;
266
+ readonly tag: string;
267
+ readonly files?: string[]; // Package file structure
268
+ }
269
+ ```
208
270
 
209
- // Create multi-file archive
210
- const archive = await createRXA({
211
- "prompt.md": "# System Prompt\nYou are...",
212
- "config.json": '{"temperature": 0.7}',
213
- });
271
+ ### RXA - Resource Archive
272
+
273
+ Archive container (tar.gz format) for storage and transfer.
274
+
275
+ ```typescript
276
+ interface RXA {
277
+ readonly stream: ReadableStream<Uint8Array>;
278
+ buffer(): Promise<Buffer>;
279
+ }
280
+ ```
214
281
 
215
- // Extract to package for file access
216
- const pkg = await archive.extract();
282
+ ### RXR - Resource
217
283
 
218
- // Read individual files
219
- const promptBuffer = await pkg.file("prompt.md");
220
- const configBuffer = await pkg.file("config.json");
284
+ Complete resource object combining locator, manifest, and archive.
221
285
 
222
- // Read all files
223
- const allFiles = await pkg.files();
224
- for (const [path, buffer] of allFiles) {
225
- console.log(path, buffer.toString());
286
+ ```typescript
287
+ interface RXR {
288
+ readonly locator: RXL;
289
+ readonly manifest: RXM;
290
+ readonly archive: RXA;
226
291
  }
227
292
  ```
228
293
 
229
- ### Manifest Serialization
294
+ ## Error Handling
230
295
 
231
296
  ```typescript
232
- const manifest = createRXM({
233
- name: "assistant",
234
- type: "prompt",
235
- version: "1.0.0",
236
- });
297
+ import {
298
+ ResourceXError,
299
+ LocatorError,
300
+ ManifestError,
301
+ ContentError,
302
+ DefinitionError,
303
+ } from "@resourcexjs/core";
237
304
 
238
- // To JSON (for storage)
239
- const json = manifest.toJSON();
240
- /*
241
- {
242
- "domain": "localhost",
243
- "name": "assistant",
244
- "type": "prompt",
245
- "version": "1.0.0"
305
+ try {
306
+ parse("invalid@locator");
307
+ } catch (error) {
308
+ if (error instanceof LocatorError) {
309
+ console.error("Invalid locator format:", error.message);
310
+ console.error("Locator:", error.locator);
311
+ }
246
312
  }
247
- */
248
313
 
249
- // To locator string
250
- const locator = manifest.toLocator();
251
- // "localhost/assistant.prompt@1.0.0"
314
+ try {
315
+ define({ name: "test" }); // Missing required 'type' field
316
+ } catch (error) {
317
+ if (error instanceof DefinitionError) {
318
+ console.error("Invalid definition:", error.message);
319
+ }
320
+ }
252
321
  ```
253
322
 
254
- ## Related Packages
323
+ ### Error Hierarchy
255
324
 
256
- This package provides only data structures. For full functionality:
325
+ ```
326
+ ResourceXError (base)
327
+ ├── LocatorError - RXL parsing errors
328
+ ├── ManifestError - RXM validation errors
329
+ ├── ContentError - RXA operations errors
330
+ └── DefinitionError - RXD validation errors
331
+ ```
332
+
333
+ ## Complete Example
257
334
 
258
- - **[@resourcexjs/type](../type)** - Type system and handlers
259
- - **[@resourcexjs/loader](../loader)** - Resource loading
260
- - **[@resourcexjs/registry](../registry)** - Storage and retrieval
261
- - **[@resourcexjs/arp](../arp)** - Low-level I/O
262
- - **[resourcexjs](../resourcex)** - Main package (all-in-one)
335
+ ```typescript
336
+ import { define, manifest, archive, resource, extract, format, parse } from "@resourcexjs/core";
337
+ import type { RXR } from "@resourcexjs/core";
263
338
 
264
- ## Type Safety
339
+ // 1. Define resource metadata
340
+ const rxd = define({
341
+ name: "assistant-prompt",
342
+ type: "text",
343
+ tag: "1.0.0",
344
+ description: "A helpful AI assistant prompt",
345
+ author: "Example Team",
346
+ });
265
347
 
266
- All types are fully typed with TypeScript:
348
+ // 2. Create manifest from definition
349
+ const rxm = manifest(rxd);
267
350
 
268
- ```typescript
269
- import type { RXL, RXM, RXA, RXP, RXR } from "@resourcexjs/core";
270
- import { parseRXL, createRXM, createRXA } from "@resourcexjs/core";
351
+ // 3. Create archive from files
352
+ const rxa = await archive({
353
+ content: Buffer.from("You are a helpful AI assistant."),
354
+ });
355
+
356
+ // 4. Combine into complete resource
357
+ const rxr: RXR = resource(rxm, rxa);
358
+
359
+ // 5. Access locator string
360
+ const locatorStr = format(rxr.locator);
361
+ console.log(locatorStr); // "assistant-prompt:1.0.0"
271
362
 
272
- const locator: RXL = parseRXL("localhost/test.text@1.0.0");
273
- const manifest: RXM = createRXM({ name: "test", type: "text", version: "1.0.0" });
274
- const archive: RXA = await createRXA({ content: "Hello" });
275
- const resource: RXR = { locator, manifest, archive };
363
+ // 6. Extract files when needed
364
+ const files = await extract(rxr.archive);
365
+ console.log(files.content.toString()); // "You are a helpful AI assistant."
276
366
  ```
277
367
 
368
+ ## Related Packages
369
+
370
+ | Package | Description |
371
+ | ---------------------------------------------------------------------------- | -------------------------- |
372
+ | [resourcexjs](https://www.npmjs.com/package/resourcexjs) | Main package (recommended) |
373
+ | [@resourcexjs/storage](https://www.npmjs.com/package/@resourcexjs/storage) | Storage layer |
374
+ | [@resourcexjs/registry](https://www.npmjs.com/package/@resourcexjs/registry) | Registry layer |
375
+ | [@resourcexjs/type](https://www.npmjs.com/package/@resourcexjs/type) | Type system |
376
+ | [@resourcexjs/loader](https://www.npmjs.com/package/@resourcexjs/loader) | Resource loading |
377
+ | [@resourcexjs/arp](https://www.npmjs.com/package/@resourcexjs/arp) | Low-level I/O |
378
+
278
379
  ## License
279
380
 
280
- MIT
381
+ Apache-2.0