@resourcexjs/registry
v1.1.0
Published
ResourceX Registry - Resource storage and retrieval
Readme
@resourcexjs/registry
Resource registry for ResourceX - storage and retrieval of resources.
Installation
bun add @resourcexjs/registryOverview
The @resourcexjs/registry package provides a Maven-style registry for storing and resolving resources locally.
Key Concepts
- Registry: Interface for resource storage and retrieval
- ARPRegistry: Implementation using ARP (Agent Resource Protocol) for I/O
- Local-first: Resources cached locally at
~/.resourcex - Maven-style: Organized by
domain/path/name.type@version
Usage
Create Registry
import { createRegistry } from "@resourcexjs/registry";
// Default configuration (~/.resourcex)
const registry = createRegistry();
// Custom path
const registry = createRegistry({
path: "./my-registry",
});
// With extension types
import { promptType } from "@my-org/types";
const registry = createRegistry({
types: [promptType],
});Link Resource
Link a resource to local registry for development or caching:
import { loadResource } from "@resourcexjs/loader";
import { createRegistry } from "@resourcexjs/registry";
// Load resource from folder
const rxr = await loadResource("./my-prompt");
// Link to registry
const registry = createRegistry();
await registry.link(rxr);
// Now available at: ~/.resourcex/localhost/[email protected]/Resolve Resource
Retrieve a resource by its locator:
const registry = createRegistry();
// Resolve by full locator
const rxr = await registry.resolve("localhost/[email protected]");
console.log(rxr.manifest.name); // "my-prompt"
console.log(await rxr.content.text()); // ContentCheck Existence
const registry = createRegistry();
if (await registry.exists("localhost/[email protected]")) {
console.log("Resource exists");
}Delete Resource
const registry = createRegistry();
await registry.delete("localhost/[email protected]");API Reference
createRegistry(config?)
Create a new registry instance.
Parameters:
config?: RegistryConfigpath?: string- Storage path (default:~/.resourcex)types?: ResourceType[]- Extension types to register globally
Returns: Registry
const registry = createRegistry({
path: "./custom-registry",
types: [promptType, toolType],
});Registry Interface
link(resource: RXR): Promise<void>
Link a resource to local registry.
Parameters:
resource: RXR- Complete resource object
await registry.link(rxr);resolve(locator: string): Promise<RXR>
Resolve a resource by locator.
Parameters:
locator: string- Full resource locator
Returns: Promise<RXR>
Throws: RegistryError if resource not found
const rxr = await registry.resolve("localhost/[email protected]");exists(locator: string): Promise<boolean>
Check if resource exists in registry.
Parameters:
locator: string- Full resource locator
Returns: Promise<boolean>
if (await registry.exists("localhost/[email protected]")) {
// Resource exists
}delete(locator: string): Promise<void>
Delete resource from local registry.
Parameters:
locator: string- Full resource locator
await registry.delete("localhost/[email protected]");publish(resource: RXR): Promise<void>
Publish resource to remote registry (TODO: not yet implemented).
search(query: string): Promise<RXL[]>
Search for resources (TODO: not yet implemented).
Storage Structure
Resources are stored in Maven-style structure:
~/.resourcex/
└── {domain}/
└── {path}/
└── {name}.{type}@{version}/
├── manifest.json # RXM metadata
└── content # Serialized contentExample
For resource deepractice.ai/prompts/[email protected]:
~/.resourcex/
└── deepractice.ai/
└── prompts/
└── [email protected]/
├── manifest.json
└── contentmanifest.json:
{
"domain": "deepractice.ai",
"path": "prompts",
"name": "assistant",
"type": "prompt",
"version": "1.0.0"
}content: (serialized by type's serializer)
Extension Types
Register extension types globally when creating registry:
import { createRegistry } from "@resourcexjs/registry";
import type { ResourceType } from "@resourcexjs/type";
const promptType: ResourceType<string> = {
name: "prompt",
description: "AI Prompt template",
serializer: {
async serialize(rxr) {
const text = await rxr.content.text();
return Buffer.from(text, "utf-8");
},
async deserialize(data, manifest) {
// ... implementation
},
},
resolver: {
async resolve(rxr) {
return rxr.content.text();
},
},
};
// Register when creating registry
const registry = createRegistry({
types: [promptType],
});
// Now can link/resolve prompt resourcesError Handling
import { RegistryError } from "@resourcexjs/registry";
try {
const rxr = await registry.resolve("localhost/[email protected]");
} catch (error) {
if (error instanceof RegistryError) {
console.error("Registry error:", error.message);
// "Resource not found: localhost/[email protected]"
}
}Common Errors
Resource not found:
RegistryError: Resource not found: localhost/[email protected]Unsupported type:
RegistryError: Unsupported resource type 'unknown'Examples
Complete Workflow
import { loadResource } from "@resourcexjs/loader";
import { createRegistry } from "@resourcexjs/registry";
// 1. Load resource from folder
const rxr = await loadResource("./my-prompts/assistant");
// 2. Create registry
const registry = createRegistry();
// 3. Link to local registry
await registry.link(rxr);
// 4. Resolve later
const resolved = await registry.resolve("localhost/[email protected]");
// 5. Use content
const text = await resolved.content.text();
console.log(text);Versioning
const registry = createRegistry();
// Link multiple versions
await registry.link(promptV1); // v1.0.0
await registry.link(promptV2); // v2.0.0
await registry.link(promptV3); // v3.0.0
// Resolve specific version
const v1 = await registry.resolve("localhost/[email protected]");
const v2 = await registry.resolve("localhost/[email protected]");
const latest = await registry.resolve("localhost/[email protected]");Custom Storage Path
// Project-local registry
const registry = createRegistry({
path: "./project-registry",
});
await registry.link(rxr);
// Stored at: ./project-registry/localhost/...With Custom Types
import { promptType, toolType, agentType } from "@my-org/ai-types";
const registry = createRegistry({
types: [promptType, toolType, agentType],
});
// Now can handle these custom types
await registry.link(promptResource);
await registry.link(toolResource);
await registry.link(agentResource);Resolution Strategy
- Check local registry (
~/.resourcexor custom path) - If not found: (TODO) Fetch from remote registry based on domain
- Cache locally after fetching
- Return resource
Currently only local resolution is implemented. Remote fetching is planned.
Architecture
┌─────────────────────────────────────┐
│ Registry Interface │
└──────────────┬──────────────────────┘
│
┌──────▼──────┐
│ARPRegistry │
│(implements) │
└──────┬──────┘
│
┌─────────┴─────────┐
│ │
┌────▼────┐ ┌──────▼──────┐
│ ARP │ │TypeHandler │
│(I/O) │ │Chain │
└─────────┘ └─────────────┘Type Safety
All operations are fully typed:
import type { RXR, Registry } from "@resourcexjs/registry";
const registry: Registry = createRegistry();
const rxr: RXR = await registry.resolve("localhost/[email protected]");License
MIT
