UNPKG

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
/** * 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