Package Exports
- @vectorforge-ai/sdk
- @vectorforge-ai/sdk/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@vectorforge-ai/sdk) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
VectorForge Node SDK
Official TypeScript/Node.js client for VectorForge Cloud APIs.
VectorForge is a trust and confidence layer for AI and automations, providing:
- DIVTs (Digital Integrity Verification Tokens) - Cryptographic "birth certificates" for data
- AI Answer Confidence Scoring - Privacy-preserving and comprehensive scoring
- Worldstate Logging - Immutable event capture for AI operations
- Hybrid Post-Quantum Cryptography - ECDSA P-521 + ML-DSA-65 signatures
Installation
From npm (Recommended)
npm install @vectorforge-ai/sdkFrom Source (Development)
git clone https://github.com/vectorforge/api
cd api/sdk/node
npm install
npm run buildFor image support:
npm install sharpQuick Start
Configuration
import { createVectorForgeClient } from '@vectorforge-ai/sdk';
// Option 1: Use environment variables (recommended)
// export VF_API_BASE_URL="https://api.vectorforge.ai"
// export VF_API_KEY="vf_prod_YourApiKeyHere"
const client = createVectorForgeClient();
// Option 2: Pass config directly
const client = createVectorForgeClient({
baseUrl: "https://api.vectorforge.ai",
apiKey: "vf_prod_YourApiKeyHere",
});High-Level API (Recommended)
The SDK provides high-level methods that handle canonicalization and hashing automatically. These are the recommended way to use VectorForge.
Register Text Content
import { createVectorForgeClient } from '@vectorforge-ai/sdk';
const client = createVectorForgeClient();
const result = await client.registerContent(
'prompt:123',
'What is the capital of France?',
'prompt_receipt_v1',
{ user_id: 'user-456', session: 'sess-789' }
);
console.log(`DIVT ID: ${result.divt_id}`);
console.log(`ECDSA signature: ${result.ecdsa_sig_b64.substring(0, 32)}...`);
console.log(`ML-DSA signature: ${result.ml_dsa_sig_b64.substring(0, 32)}...`);
console.log(`Ledger status: ${result.ledger_status}`);What it does:
- Normalizes text (Unicode NFC, line endings, trim whitespace)
- Computes SHA3-512 hash
- Creates DIVT with hybrid post-quantum signatures
- Returns
divt_idfor future verification
Register JSON Data
const result = await client.registerJson(
'rag_snapshot:v42',
{
snapshot_type: 'rag-corpus',
doc_hashes: ['hash1', 'hash2'],
index_hash: 'index_hash_value',
timestamp: '2025-11-21T10:00:00Z',
},
'rag_snapshot_v1',
{ project: 'hr-assistant', env: 'prod' }
);
console.log(`RAG snapshot registered: ${result.divt_id}`);What it does:
- Canonical JSON serialization (sorted keys, minimal whitespace)
- Computes SHA3-512 hash
- Creates DIVT
Register Embedding Vector
const result = await client.registerEmbedding(
'chunk:doc-123:p5',
[0.123456, -0.987654, 0.456789, ...], // Your embedding vector
'rag_chunk_v1',
{ document_id: 'doc-123', paragraph: 5 },
6 // Decimal precision
);
console.log(`Embedding registered: ${result.divt_id}`);What it does:
- Validates embedding (rejects NaN/Infinity)
- Formats with fixed precision for deterministic hashing
- Computes SHA3-512 hash
- Creates DIVT
Register Image
Requires: npm install sharp
import { readFile } from 'fs/promises';
const imageBuffer = await readFile('receipt.png');
const result = await client.registerImage(
'image:receipt-456',
imageBuffer,
'image_receipt_v1',
{ source: 'mobile_app', user_id: 'user-789' },
1024 // Max dimension
);
console.log(`Image registered: ${result.divt_id}`);What it does:
- Decodes image (supports PNG, JPEG, WebP)
- Normalizes to sRGB color space
- Resizes if needed (preserves aspect ratio)
- Re-encodes as deterministic PNG
- Computes SHA3-512 hash
- Creates DIVT
Complete Example: Prompt Receipt with Verification
import { createVectorForgeClient } from '@vectorforge-ai/sdk';
const client = createVectorForgeClient();
// Register AI prompt + response
const promptData = {
prompt: 'What is the capital of France?',
response: 'Paris',
model: 'gpt-4',
timestamp: '2025-11-21T10:00:00Z',
};
const registerResult = await client.registerJson(
'prompt_receipt:flow-abc-123',
promptData,
'prompt_receipt_v1',
{ workflow: 'customer_support' }
);
const divtId = registerResult.divt_id;
console.log(`✓ Prompt receipt registered: ${divtId}`);
// Later: Verify the prompt receipt
const verifyResult = await client.verifyJson(divtId, promptData);
if (verifyResult.verified) {
console.log('✓ DIVT is valid');
console.log(` - Hash valid: ${verifyResult.hash_valid}`);
console.log(` - ECDSA signature valid: ${verifyResult.ecdsa_signature_valid}`);
console.log(` - ML-DSA signature valid: ${verifyResult.ml_dsa_signature_valid}`);
console.log(` - Object ID: ${verifyResult.object_id}`);
console.log(` - Created: ${verifyResult.created_at}`);
console.log(` - Ledger status: ${verifyResult.ledger_status}`);
} else {
console.log('✗ DIVT verification failed');
console.log(` - Hash valid: ${verifyResult.hash_valid}`);
console.log(` - Revoked: ${verifyResult.revoked}`);
}Low-Level API (Advanced)
For advanced use cases where you want to compute hashes yourself, use the low-level register() method:
import { canon } from '@vectorforge-ai/sdk';
// Compute hash manually
const text = 'Hello, World!';
const hashB64 = canon.hashContentV1(text);
// Register with pre-computed hash
const result = await client.register({
object_id: 'doc-123',
hash_mode: 'content',
hash_version: 'content_v1',
hash_b64: hashB64,
data_type: 'prompt_receipt_v1',
});Canonicalization Utilities
import { canon } from '@vectorforge-ai/sdk';
// Text canonicalization
const hashB64 = canon.hashContentV1('Hello, World!');
// JSON canonicalization
const hashB64 = canon.hashJsonV1({ key: 'value', nested: { a: 1 } });
// Embedding canonicalization
const hashB64 = canon.hashEmbeddingV1([0.1, 0.2, 0.3], 6);
// Image canonicalization (requires sharp)
const imageBuffer = await readFile('image.png');
const hashB64 = await canon.hashImageV1(imageBuffer, 1024);
// Or get canonical bytes without hashing
const canonicalBuffer = canon.canonicalizeContentV1('Hello');
const hashB64 = canon.sha3512Digest(canonicalBuffer);Verification
Verify a Single DIVT
// Using hash_b64 (advanced)
const result = await client.verify({
divt_id: '019abc12-3456-7890-abcd-ef0123456789',
hash_b64: 'your-precomputed-hash-base64',
});
if (result.verified) {
console.log('✓ DIVT is valid');
console.log(` - Hash valid: ${result.hash_valid}`);
console.log(` - ECDSA valid: ${result.ecdsa_signature_valid}`);
console.log(` - ML-DSA valid: ${result.ml_dsa_signature_valid}`);
console.log(` - Revoked: ${result.revoked}`);
} else {
console.log('✗ DIVT verification failed');
}Verify with High-Level Helpers
// Verify text content
const result = await client.verifyContent(divtId, 'Hello, World!');
// Verify JSON data
const result = await client.verifyJson(divtId, { key: 'value' });Bundle API
Get comprehensive verification bundles for DIVTs including worldstate context and scoring results.
Get Bundle by DIVT ID
const bundle = await client.getBundle({
divt_id: '019abc12-3456-7890-abcd-ef0123456789',
});
console.log('DIVT Verification:');
console.log(` - Verified: ${bundle.divt.verified}`);
console.log(` - Hash valid: ${bundle.divt.hash_valid}`);
console.log(` - Ledger status: ${bundle.divt.ledger_status}`);
console.log(`Worldstate events: ${bundle.worldstate.length}`);
console.log(`Scoring events: ${bundle.scoring.length}`);
console.log(`Generated at: ${bundle.generated_at}`);Get Bundle by Object ID
const bundle = await client.getBundle({
object_id: 'prompt_receipt:flow-abc-123',
include_history: true,
});Scoring API
Privacy Score (No Raw Content Sent)
const result = await client.scorePrivacy({
query_id: 'query-123',
answer_id: 'answer-456',
evidence: [
{
object_id: 'chunk:doc-1:p1',
divt_id: '019abc...',
tenant_id: 'my-tenant',
similarity: 0.95,
chunk_confidence: 0.9,
},
],
});
console.log(`Overall confidence: ${result.overall_confidence}`);
console.log(`Semantic confidence: ${result.semantic_confidence}`);
console.log(`Integrity score: ${result.integrity_score}`);
console.log(`Verified count: ${result.verified_count}/${result.vector_count}`);Full Score (With Groq Judge)
const result = await client.scoreFull({
query: 'What is the capital of France?',
answer: 'The capital of France is Paris.',
evidence: [
{
object_id: 'chunk:doc-1:p1',
divt_id: '019abc...',
tenant_id: 'my-tenant',
text: 'Paris is the capital city of France.',
similarity: 0.95,
},
],
options: {
log_worldstate: 'minimal',
},
});
console.log(`Overall confidence: ${result.overall_confidence}`);
console.log(`Support score: ${result.support_score}`);
console.log(`Faithfulness score: ${result.faithfulness_score}`);Worldstate Read
Get Single Worldstate Record
// Get worldstate record metadata
const item = await client.getWorldstateItem({
wsl_id: '019abc12-3456-7890-abcd-ef0123456789',
});
console.log(`Kind: ${item.kind}`);
console.log(`Timestamp: ${item.timestamp}`);
console.log(`Ledger status: ${item.ledger_status}`);
console.log(`Summary: ${item.data_summary}`);
// Get worldstate record with full data from S3
const itemWithData = await client.getWorldstateItem({
wsl_id: '019abc12-3456-7890-abcd-ef0123456789',
include_data: true,
});
console.log('Full data:', itemWithData.data);List Worldstate Records
// List all records
const result = await client.listWorldstate();
console.log(`Found ${result.count} records`);
// List with filters
const promptReceipts = await client.listWorldstate({
kind: 'prompt_receipt',
created_from: '2025-11-01T00:00:00Z',
created_to: '2025-11-30T23:59:59Z',
limit: 50,
});
// Paginate through all results
let cursor = promptReceipts.cursor;
while (cursor) {
const page = await client.listWorldstate({ cursor });
for (const item of page.items) {
console.log(`${item.wsl_id}: ${item.data_summary}`);
}
cursor = page.cursor;
}Available Filters:
kind: Filter by event type (prompt_receipt,scoring_event,rag_snapshot, etc.)created_from: Start of time range (ISO 8601)created_to: End of time range (ISO 8601)limit: Page size (max 100, default 50)cursor: Pagination cursor from previous response
Stream Events (SSE)
const oneHourAgo = new Date(Date.now() - 3600000).toISOString();
await client.streamEvents(
{
since: oneHourAgo,
types: ['divt_registered', 'scoring_event'],
limit: 50,
},
(event) => {
console.log(`[${event.type}] ${event.id} at ${event.timestamp}`);
}
);Error Handling
import { VectorForgeAPIError } from '@vectorforge-ai/sdk';
try {
const result = await client.registerContent(
'doc-123',
'Hello, World!',
'prompt_receipt_v1'
);
} catch (error) {
if (error instanceof VectorForgeAPIError) {
console.error(`API Error: ${error.message}`);
console.error(`Status: ${error.statusCode}`);
console.error(`Code: ${error.error}`);
if (error.details) {
console.error(`Details: ${error.details}`);
}
} else {
console.error(`Unexpected error: ${error}`);
}
}Common Error Codes:
invalid_api_key(401) - API key invalid or expiredquota_exceeded(429) - Monthly request limit reachedrate_limit_exceeded(429) - Too many requestsplan_limitation(403) - Feature not available on your plannetwork_error(0) - Network connectivity issue
Type Support
Full TypeScript support with type definitions:
import type {
RegisterInput,
RegisterResult,
VerifyInput,
VerifyResult,
BundleInput,
BundleResult,
PrivacyScoreInput,
FullScoreInput,
ScoreResult,
StreamEventsInput,
StreamEvent,
} from '@vectorforge-ai/sdk';Integration Tests
To run integration tests against the live API:
export VF_API_BASE_URL="https://api.vectorforge.ai"
export VF_API_KEY="your-api-key"
npm testRequirements
- Node.js: >= 18.0.0 (uses native fetch)
- Dependencies:
js-sha3(SHA3-512 hashing)
- Optional:
sharp>= 0.33.0 (for image registration)
Related Documentation
- API Reference - Complete HTTP API documentation
- Implementation Plan - Full system specification
- Python SDK - Python SDK documentation
Support
- Issues: GitHub Issues
- Website: https://vectorforge.ai
License
MIT © VectorForge