claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
393 lines • 14.8 kB
JavaScript
/**
* RVFA (RuVector Format Appliance) — Binary format reader/writer
* for self-contained Ruflo appliances.
*
* Binary layout:
* [4B magic "RVFA"] [4B version u32LE] [4B header_len u32LE]
* [header_len B JSON header] [section data ...] [32B SHA256 footer]
*/
import { createHash } from 'node:crypto';
import { gzipSync, gunzipSync } from 'node:zlib';
import { readFile } from 'node:fs/promises';
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
export const RVFA_MAGIC = Buffer.from('RVFA');
export const RVFA_VERSION = 1;
const MAGIC_SIZE = 4;
const VERSION_SIZE = 4;
const HEADER_LEN_SIZE = 4;
const PREAMBLE_SIZE = MAGIC_SIZE + VERSION_SIZE + HEADER_LEN_SIZE; // 12
const SHA256_SIZE = 32;
const MAX_HEADER_JSON_SIZE = 1024 * 1024; // 1 MB
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function sha256(data) {
return createHash('sha256').update(data).digest('hex');
}
function sha256Bytes(data) {
return createHash('sha256').update(data).digest();
}
/** Format bytes into a human-readable string (e.g. '2.3 GB'). */
export function formatSize(bytes) {
if (bytes < 0)
return '0 B';
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let idx = 0;
let value = bytes;
while (value >= 1024 && idx < units.length - 1) {
value /= 1024;
idx++;
}
return idx === 0 ? `${value} ${units[idx]}` : `${value.toFixed(1)} ${units[idx]}`;
}
/** Create a sensible default header for a given profile. */
export function createDefaultHeader(profile) {
const modelDefaults = {
cloud: { provider: 'api-vault', vaultEncryption: 'aes-256-gcm' },
hybrid: {
provider: 'hybrid',
engine: 'ruvllm-0.1.0',
models: ['phi-3-mini-q4'],
vaultEncryption: 'aes-256-gcm',
},
offline: {
provider: 'ruvllm',
engine: 'ruvllm-0.1.0',
models: ['phi-3-mini-q4'],
},
};
const capDefaults = {
cloud: ['mcp', 'swarm', 'memory', 'hooks', 'neural', 'api-vault'],
hybrid: ['mcp', 'swarm', 'memory', 'hooks', 'neural', 'ruvllm', 'api-vault'],
offline: ['mcp', 'swarm', 'memory', 'hooks', 'neural', 'ruvllm'],
};
return {
magic: 'RVFA',
version: RVFA_VERSION,
name: '',
appVersion: '3.5.0',
arch: 'x86_64',
platform: 'linux',
profile,
created: new Date().toISOString(),
sections: [],
boot: {
entrypoint: '/opt/ruflo/bin/ruflo',
args: ['--appliance'],
env: {},
isolation: profile === 'cloud' ? 'container' : 'native',
},
models: modelDefaults[profile],
capabilities: capDefaults[profile],
};
}
/** Type-guard that validates an unknown value is a well-formed RvfaHeader. */
export function validateHeader(header) {
if (typeof header !== 'object' || header === null)
return false;
const h = header;
const str = (v) => typeof v === 'string';
const obj = (v) => typeof v === 'object' && v !== null;
const oneOf = (v, vals) => vals.includes(v);
if (h.magic !== 'RVFA' || typeof h.version !== 'number' || h.version < 1)
return false;
if (!str(h.name) || !str(h.appVersion) || !str(h.arch) || !str(h.platform))
return false;
if (!oneOf(h.profile, ['cloud', 'hybrid', 'offline']))
return false;
if (!str(h.created) || !Array.isArray(h.sections) || !Array.isArray(h.capabilities))
return false;
if (!obj(h.boot))
return false;
const boot = h.boot;
if (!str(boot.entrypoint) || !Array.isArray(boot.args) || !obj(boot.env))
return false;
if (!oneOf(boot.isolation, ['container', 'microvm', 'native']))
return false;
if (!obj(h.models))
return false;
if (!oneOf(h.models.provider, ['ruvllm', 'api-vault', 'hybrid']))
return false;
for (const sec of h.sections) {
if (!obj(sec))
return false;
const s = sec;
if (!str(s.id) || !str(s.type) || !str(s.sha256))
return false;
if (typeof s.offset !== 'number' || typeof s.size !== 'number')
return false;
if (typeof s.originalSize !== 'number')
return false;
if (!oneOf(s.compression, ['none', 'gzip', 'zstd']))
return false;
}
return true;
}
export class RvfaWriter {
header;
staged = [];
constructor(partial) {
const profile = partial.profile ?? 'cloud';
const defaults = createDefaultHeader(profile);
this.header = { ...defaults, ...partial, sections: [] };
}
/**
* Add a section to the appliance image.
*
* @param id Section identifier (e.g. 'kernel', 'runtime', 'ruflo').
* @param data Raw (uncompressed) section payload.
* @param options Optional compression and MIME type overrides.
*/
addSection(id, data, options) {
const compression = options?.compression ?? 'gzip';
const mimeType = options?.type ?? 'application/octet-stream';
let compressed;
let actualCompression = compression;
if (compression === 'gzip') {
compressed = gzipSync(data);
}
else if (compression === 'zstd') {
// zstd not available in core Node.js — fall back to gzip
compressed = gzipSync(data);
actualCompression = 'gzip';
}
else {
compressed = data;
}
const hash = sha256(compressed);
this.staged.push({
id,
type: mimeType,
data: compressed,
originalSize: data.length,
sha256: hash,
compression: actualCompression,
});
}
/**
* Assemble the final RVFA binary image.
*
* Layout:
* [4B magic] [4B version] [4B header_len]
* [header JSON bytes]
* [section 0 bytes] [section 1 bytes] ...
* [32B SHA256 of all section bytes combined]
*/
build() {
// Build section descriptors with placeholder offsets
const sectionDescriptors = this.staged.map((s) => ({
id: s.id,
type: s.type,
offset: 0,
size: s.data.length,
originalSize: s.originalSize,
sha256: s.sha256,
compression: s.compression,
}));
// Iteratively compute offsets: the header contains the offsets as JSON,
// so changing offsets can change the header length. We converge quickly.
this.header.sections = sectionDescriptors;
let headerJson = Buffer.from(JSON.stringify(this.header), 'utf-8');
let prevLen = -1;
for (let attempt = 0; attempt < 5 && headerJson.length !== prevLen; attempt++) {
prevLen = headerJson.length;
const dataAreaStart = PREAMBLE_SIZE + headerJson.length;
let cursor = dataAreaStart;
for (let i = 0; i < this.staged.length; i++) {
sectionDescriptors[i].offset = cursor;
cursor += this.staged[i].data.length;
}
this.header.sections = sectionDescriptors;
headerJson = Buffer.from(JSON.stringify(this.header), 'utf-8');
}
// Build preamble buffers
const magicBuf = Buffer.from('RVFA');
const versionBuf = Buffer.alloc(VERSION_SIZE);
versionBuf.writeUInt32LE(RVFA_VERSION, 0);
const headerLenBuf = Buffer.alloc(HEADER_LEN_SIZE);
headerLenBuf.writeUInt32LE(headerJson.length, 0);
// Concatenate section data
const sectionBuffers = this.staged.map((s) => s.data);
const allSectionData = Buffer.concat(sectionBuffers);
// Footer: SHA256 of all section data combined
const footer = sha256Bytes(allSectionData);
return Buffer.concat([
magicBuf,
versionBuf,
headerLenBuf,
headerJson,
allSectionData,
footer,
]);
}
}
// ---------------------------------------------------------------------------
// RvfaReader
// ---------------------------------------------------------------------------
export class RvfaReader {
buf;
header;
constructor(buf, header) {
this.buf = buf;
this.header = header;
}
/** Parse an RVFA image from an in-memory Buffer. */
static fromBuffer(buf) {
if (buf.length < PREAMBLE_SIZE) {
throw new Error('Buffer too small to contain RVFA preamble');
}
// Magic
const magic = buf.subarray(0, MAGIC_SIZE).toString('ascii');
if (magic !== 'RVFA') {
throw new Error(`Invalid RVFA magic: expected "RVFA", got "${magic}"`);
}
// Version
const version = buf.readUInt32LE(MAGIC_SIZE);
if (version !== RVFA_VERSION) {
throw new Error(`Unsupported RVFA version: ${version} (expected ${RVFA_VERSION})`);
}
// Header length
const headerLen = buf.readUInt32LE(MAGIC_SIZE + VERSION_SIZE);
if (headerLen > MAX_HEADER_JSON_SIZE) {
throw new Error(`Header JSON exceeds maximum size (${headerLen} > ${MAX_HEADER_JSON_SIZE})`);
}
if (PREAMBLE_SIZE + headerLen > buf.length) {
throw new Error('Buffer too small to contain declared header');
}
// Parse header JSON
const headerSlice = buf.subarray(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLen);
let parsed;
try {
parsed = JSON.parse(headerSlice.toString('utf-8'));
}
catch {
throw new Error('Failed to parse RVFA header JSON');
}
if (!validateHeader(parsed)) {
throw new Error('RVFA header failed validation');
}
const header = parsed;
// Bounds-check every section offset
const totalSize = buf.length;
for (const sec of header.sections) {
if (sec.offset < 0 || sec.size < 0) {
throw new Error(`Section "${sec.id}" has negative offset or size`);
}
if (sec.offset + sec.size > totalSize - SHA256_SIZE) {
throw new Error(`Section "${sec.id}" extends beyond buffer ` +
`(offset=${sec.offset}, size=${sec.size}, bufLen=${totalSize})`);
}
}
// Check for overlapping sections
const sorted = [...header.sections].sort((a, b) => a.offset - b.offset);
for (let i = 1; i < sorted.length; i++) {
const prev = sorted[i - 1];
const curr = sorted[i];
if (prev.offset + prev.size > curr.offset) {
throw new Error(`Sections "${prev.id}" and "${curr.id}" overlap ` +
`(${prev.offset}+${prev.size} > ${curr.offset})`);
}
}
return new RvfaReader(buf, header);
}
/** Read an RVFA image from a file path. */
static async fromFile(path) {
if (path.includes('\0')) {
throw new Error('Path contains null bytes');
}
const data = await readFile(path);
return RvfaReader.fromBuffer(data);
}
/** Return the parsed header. */
getHeader() {
return this.header;
}
/** List all sections declared in the header. */
getSections() {
return this.header.sections;
}
/**
* Extract and decompress a section by its id.
*
* @param id The section identifier (e.g. 'kernel', 'runtime').
* @returns The decompressed section payload.
*/
extractSection(id) {
const sec = this.header.sections.find((s) => s.id === id);
if (!sec) {
throw new Error(`Section "${id}" not found`);
}
if (sec.offset + sec.size > this.buf.length - SHA256_SIZE) {
throw new Error(`Section "${id}" exceeds buffer bounds`);
}
const raw = this.buf.subarray(sec.offset, sec.offset + sec.size);
if (sec.compression === 'gzip') {
return gunzipSync(raw);
}
if (sec.compression === 'zstd') {
// zstd not natively supported — attempt gzip fallback (mirrors writer)
try {
return gunzipSync(raw);
}
catch {
throw new Error('zstd decompression is not supported in this environment');
}
}
// compression === 'none'
return Buffer.from(raw);
}
/**
* Verify the integrity of the RVFA image.
*
* Checks:
* 1. Magic bytes
* 2. Version number
* 3. SHA256 of each section's compressed data
* 4. SHA256 footer (all section data combined)
*/
verify() {
const errors = [];
// 1. Magic
const magic = this.buf.subarray(0, MAGIC_SIZE).toString('ascii');
if (magic !== 'RVFA') {
errors.push(`Invalid magic: "${magic}"`);
}
// 2. Version
const version = this.buf.readUInt32LE(MAGIC_SIZE);
if (version !== RVFA_VERSION) {
errors.push(`Unsupported version: ${version}`);
}
// 3. Per-section SHA256
const sectionDataParts = [];
for (const sec of this.header.sections) {
if (sec.offset + sec.size > this.buf.length - SHA256_SIZE) {
errors.push(`Section "${sec.id}" extends beyond buffer`);
continue;
}
const raw = this.buf.subarray(sec.offset, sec.offset + sec.size);
sectionDataParts.push(raw);
const actual = sha256(raw);
if (actual !== sec.sha256) {
errors.push(`Section "${sec.id}" SHA256 mismatch: ` +
`expected ${sec.sha256}, got ${actual}`);
}
}
// 4. Footer SHA256
if (this.buf.length >= SHA256_SIZE) {
const allSections = Buffer.concat(sectionDataParts);
const expectedFooter = sha256Bytes(allSections);
const actualFooter = this.buf.subarray(this.buf.length - SHA256_SIZE);
if (!expectedFooter.equals(actualFooter)) {
errors.push(`Footer SHA256 mismatch: expected ${expectedFooter.toString('hex')}, ` +
`got ${actualFooter.toString('hex')}`);
}
}
else {
errors.push('Buffer too small to contain SHA256 footer');
}
return { valid: errors.length === 0, errors };
}
}
//# sourceMappingURL=rvfa-format.js.map