mcard-js
Version:
MCard - Content-addressable storage with cryptographic hashing, handle resolution, and vector search for Node.js and browsers
296 lines • 11.6 kB
JavaScript
/**
* Bridgelet Universal Vehicle - Cross-Language Execution Abstraction
*
* The Bridgelet provides a universal interface for executing CLM logic across
* different language runtimes, enabling polyglot composition of PCards.
*
* ## Conceptual Foundation
*
* Bridgelet = Universal Vehicle for Cross-Language Execution
*
* Just as a physical bridge connects two lands, a Bridgelet connects two
* language runtimes, enabling data and control flow across the boundary.
*
* ## Architecture
*
* ```
* ┌─────────────────────────────────────────────────────────────────────┐
* │ Bridgelet Interface │
* │ invoke(pcard_hash, input_vcard) → output_vcard │
* └───────────────────────────┬─────────────────────────────────────────┘
* │
* ┌───────────────────┼───────────────────────┐
* ▼ ▼ ▼
* ┌────────┐ ┌────────┐ ┌────────┐
* │ JS │ │ Python │ │ WASM │
* │Runtime │ │(HTTP) │ │Runtime │
* └────────┘ └────────┘ └────────┘
* ```
*
* ## Protocol
*
* 1. Serialize input VCard to content-addressable format (MCard)
* 2. Invoke target runtime with PCard hash and input MCard hash
* 3. Receive output MCard hash
* 4. Deserialize output MCard to VCard
*
* All data crosses the bridge as immutable MCards (content-addressed),
* ensuring EOS (Experimental-Operational Symmetry).
*
* @see CLM_MCard_REPL_Implementation.md §10: Bridgelet Universal Vehicle
* @see PTR_MCard_CLM_Recent_Developments_Jan2026.md §5.3: Polyglot Execution
*/
import { parse } from 'yaml';
/**
* Supported runtime types for Bridgelet execution
*/
export var RuntimeType;
(function (RuntimeType) {
RuntimeType["JAVASCRIPT"] = "javascript";
RuntimeType["TYPESCRIPT"] = "typescript";
RuntimeType["PYTHON"] = "python";
RuntimeType["WASM"] = "wasm";
RuntimeType["LEAN"] = "lean";
RuntimeType["UNKNOWN"] = "unknown";
})(RuntimeType || (RuntimeType = {}));
/**
* JavaScript/TypeScript Bridgelet adapter.
*
* Executes PCards using the local JavaScript CLM runner.
*/
export class JavaScriptBridgeletAdapter {
collection;
constructor(collection) {
this.collection = collection;
}
getRuntimeType() {
return RuntimeType.JAVASCRIPT;
}
isAvailable() {
return true; // JS is always available in JS runtime
}
async invoke(invocation) {
const startTime = Date.now();
try {
// For JavaScript runtime, we execute via CLMRunner
// Note: Bridgelet operates on content hashes, but CLMRunner
// primarily works with file paths. This adapter bridges the gap.
// If we have a collection, we can try to resolve the PCard
if (this.collection) {
const pcard = await this.collection.get(invocation.pcardHash);
if (pcard) {
// Parse the CLM content
const { parse } = await import('yaml');
const content = typeof pcard.content === 'string'
? pcard.content
: new TextDecoder().decode(pcard.content);
const clm = parse(content);
// Execute via CLMRunner
const { CLMRunner } = await import('./node/CLMRunner.js');
const runner = new CLMRunner(process.cwd(), 5000, this.collection);
// Build execution context with input VCard hash
const input = {
...invocation.context,
input_vcard_hash: invocation.inputVCardHash
};
// Execute the CLM
const result = await runner.executeCLM(clm, process.cwd(), input);
const executionTimeMs = Date.now() - startTime;
if (result.success) {
// ExecutionResult uses 'result' not 'output'
// Generate a hash from the result for output tracking
const resultStr = JSON.stringify(result.result);
const outputHash = `result:${resultStr.length}:${Date.now()}`;
return {
success: true,
outputVCardHash: outputHash,
executionTimeMs,
executedBy: RuntimeType.JAVASCRIPT,
metadata: {
outputType: typeof result.result,
chapter: result.clm?.chapter
}
};
}
else {
return {
success: false,
error: result.error || 'Execution failed',
executionTimeMs,
executedBy: RuntimeType.JAVASCRIPT,
metadata: {}
};
}
}
}
// Fallback: No collection or PCard not found
const executionTimeMs = Date.now() - startTime;
return {
success: false,
error: `PCard not found in collection: ${invocation.pcardHash}`,
executionTimeMs,
executedBy: RuntimeType.JAVASCRIPT,
metadata: {}
};
}
catch (e) {
const executionTimeMs = Date.now() - startTime;
console.error(`JavaScript Bridgelet invocation failed: ${e.message}`);
return {
success: false,
error: e.message,
executionTimeMs,
executedBy: RuntimeType.JAVASCRIPT,
metadata: {}
};
}
}
}
/**
* Universal Vehicle for Cross-Language Execution.
*
* The Bridgelet manages a registry of runtime adapters and routes
* PCard execution requests to the appropriate runtime based on
* the PCard's declared runtime requirement.
*
* ## Usage
*
* ```typescript
* const bridgelet = new Bridgelet(collection);
* bridgelet.registerAdapter(new JavaScriptBridgeletAdapter());
* bridgelet.registerAdapter(new PythonHTTPBridgeletAdapter('http://localhost:8000'));
*
* const result = await bridgelet.invoke({
* pcardHash: "abc123",
* inputVCardHash: "def456",
* context: { param: "value" }
* });
* ```
*
* ## Cross-Language Composition
*
* The Bridgelet enables polyglot PCard composition:
*
* ```typescript
* jsPCard.andThen(pythonPCard).andThen(wasmPCard)
* ```
*
* Each transition crosses a runtime bridge, with data flowing
* as content-addressed MCards.
*/
export class Bridgelet {
collection;
adapters = new Map();
traceCounter = 0;
constructor(collection) {
this.collection = collection;
// Auto-register JavaScript adapter
this.registerAdapter(new JavaScriptBridgeletAdapter(collection));
}
/**
* Register a runtime adapter
*/
registerAdapter(adapter) {
const runtimeType = adapter.getRuntimeType();
this.adapters.set(runtimeType, adapter);
console.log(`Registered Bridgelet adapter for ${runtimeType}`);
}
/**
* Get list of available runtimes
*/
getAvailableRuntimes() {
return Array.from(this.adapters.entries())
.filter(([_, adapter]) => adapter.isAvailable())
.map(([rt, _]) => rt);
}
/**
* Generate a unique trace ID for observability
*/
generateTraceId() {
this.traceCounter++;
return `bridgelet-${Date.now()}-${this.traceCounter}`;
}
/**
* Detect the required runtime for a PCard
*/
async detectRuntime(pcardHash) {
if (!this.collection) {
return RuntimeType.JAVASCRIPT; // Default
}
try {
const pcard = await this.collection.get(pcardHash);
if (!pcard) {
return RuntimeType.JAVASCRIPT;
}
// Parse CLM content
const content = typeof pcard.content === 'string'
? pcard.content
: new TextDecoder().decode(pcard.content);
const clm = parse(content);
// Extract runtime from CLM
const runtimeStr = clm?.clm?.concrete?.runtime ||
clm?.concrete?.runtime ||
'javascript';
// Map string to RuntimeType
const runtimeMap = {
'python': RuntimeType.PYTHON,
'javascript': RuntimeType.JAVASCRIPT,
'typescript': RuntimeType.TYPESCRIPT,
'js': RuntimeType.JAVASCRIPT,
'ts': RuntimeType.TYPESCRIPT,
'wasm': RuntimeType.WASM,
'lean': RuntimeType.LEAN
};
return runtimeMap[runtimeStr.toLowerCase()] ?? RuntimeType.JAVASCRIPT;
}
catch (e) {
console.warn(`Failed to detect runtime for ${pcardHash}: ${e}`);
return RuntimeType.JAVASCRIPT;
}
}
/**
* Invoke a PCard across the appropriate runtime bridge
*/
async invoke(options) {
const { pcardHash, inputVCardHash, context = {}, targetRuntime } = options;
const traceId = this.generateTraceId();
// Detect or use specified runtime
const runtime = targetRuntime ?? await this.detectRuntime(pcardHash);
// Check if adapter is available
if (!this.adapters.has(runtime)) {
return {
success: false,
error: `No adapter registered for runtime: ${runtime}`,
executionTimeMs: 0,
executedBy: RuntimeType.UNKNOWN,
metadata: {}
};
}
const adapter = this.adapters.get(runtime);
if (!adapter.isAvailable()) {
return {
success: false,
error: `Runtime not available: ${runtime}`,
executionTimeMs: 0,
executedBy: RuntimeType.UNKNOWN,
metadata: {}
};
}
// Create invocation
const invocation = {
pcardHash,
inputVCardHash,
targetRuntime: runtime,
context,
traceId
};
console.log(`Bridgelet invoking ${pcardHash.substring(0, 8)}... via ${runtime} ` +
`(trace: ${traceId})`);
// Invoke through adapter
const result = await adapter.invoke(invocation);
console.log(`Bridgelet invocation complete: ${result.success ? 'success' : 'failed'} ` +
`(${result.executionTimeMs}ms)`);
return result;
}
}
//# sourceMappingURL=Bridgelet.js.map