@arke-institute/sdk 0.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -184
- package/dist/generated/index.cjs +19 -0
- package/dist/generated/index.cjs.map +1 -0
- package/dist/generated/index.d.cts +6192 -0
- package/dist/generated/index.d.ts +6192 -0
- package/dist/generated/index.js +1 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/index-BrXke2kI.d.ts +302 -0
- package/dist/index-FHcLPBSV.d.cts +302 -0
- package/dist/index.cjs +188 -4254
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -7
- package/dist/index.d.ts +62 -7
- package/dist/index.js +168 -4226
- package/dist/index.js.map +1 -1
- package/dist/operations/index.cjs +113 -0
- package/dist/operations/index.cjs.map +1 -0
- package/dist/operations/index.d.cts +3 -0
- package/dist/operations/index.d.ts +3 -0
- package/dist/operations/index.js +84 -0
- package/dist/operations/index.js.map +1 -0
- package/package.json +44 -53
- package/dist/client-dAk3E64p.d.cts +0 -183
- package/dist/client-dAk3E64p.d.ts +0 -183
- package/dist/collections/index.cjs +0 -233
- package/dist/collections/index.cjs.map +0 -1
- package/dist/collections/index.d.cts +0 -9
- package/dist/collections/index.d.ts +0 -9
- package/dist/collections/index.js +0 -205
- package/dist/collections/index.js.map +0 -1
- package/dist/content/index.cjs +0 -591
- package/dist/content/index.cjs.map +0 -1
- package/dist/content/index.d.cts +0 -516
- package/dist/content/index.d.ts +0 -516
- package/dist/content/index.js +0 -558
- package/dist/content/index.js.map +0 -1
- package/dist/edit/index.cjs +0 -1503
- package/dist/edit/index.cjs.map +0 -1
- package/dist/edit/index.d.cts +0 -78
- package/dist/edit/index.d.ts +0 -78
- package/dist/edit/index.js +0 -1447
- package/dist/edit/index.js.map +0 -1
- package/dist/errors-3L7IiHcr.d.cts +0 -480
- package/dist/errors-BTe8GKRQ.d.ts +0 -480
- package/dist/errors-CT7yzKkU.d.cts +0 -874
- package/dist/errors-CT7yzKkU.d.ts +0 -874
- package/dist/graph/index.cjs +0 -427
- package/dist/graph/index.cjs.map +0 -1
- package/dist/graph/index.d.cts +0 -485
- package/dist/graph/index.d.ts +0 -485
- package/dist/graph/index.js +0 -396
- package/dist/graph/index.js.map +0 -1
- package/dist/query/index.cjs +0 -356
- package/dist/query/index.cjs.map +0 -1
- package/dist/query/index.d.cts +0 -636
- package/dist/query/index.d.ts +0 -636
- package/dist/query/index.js +0 -328
- package/dist/query/index.js.map +0 -1
- package/dist/upload/index.cjs +0 -1634
- package/dist/upload/index.cjs.map +0 -1
- package/dist/upload/index.d.cts +0 -150
- package/dist/upload/index.d.ts +0 -150
- package/dist/upload/index.js +0 -1597
- package/dist/upload/index.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/upload/utils/errors.ts","../src/upload/platforms/common.ts","../src/upload/lib/validation.ts","../src/upload/utils/hash.ts","../src/upload/types/processing.ts","../src/upload/platforms/node.ts","../src/upload/platforms/browser.ts","../src/collections/errors.ts","../src/collections/client.ts","../src/upload/lib/worker-client-fetch.ts","../src/upload/utils/retry.ts","../src/upload/uploader.ts","../src/upload/lib/simple-fetch.ts","../src/upload/lib/multipart-fetch.ts","../src/upload/client.ts","../src/index.ts","../src/query/errors.ts","../src/query/client.ts","../src/edit/types.ts","../src/edit/errors.ts","../src/edit/client.ts","../src/edit/diff.ts","../src/edit/prompts.ts","../src/edit/session.ts","../src/content/errors.ts","../src/content/client.ts","../src/graph/errors.ts","../src/graph/client.ts"],"sourcesContent":["/**\n * Custom error classes for better error handling\n */\n\nexport class WorkerAPIError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public details?: any\n ) {\n super(message);\n this.name = 'WorkerAPIError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class UploadError extends Error {\n constructor(\n message: string,\n public fileName?: string,\n public statusCode?: number,\n public cause?: Error\n ) {\n super(message);\n this.name = 'UploadError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class ValidationError extends Error {\n constructor(message: string, public field?: string) {\n super(message);\n this.name = 'ValidationError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message: string, public cause?: Error) {\n super(message);\n this.name = 'NetworkError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class ScanError extends Error {\n constructor(message: string, public path?: string) {\n super(message);\n this.name = 'ScanError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\n/**\n * Determine if an error is retryable\n */\nexport function isRetryableError(error: any): boolean {\n // Network errors are retryable\n if (error instanceof NetworkError) {\n return true;\n }\n\n // Worker API 5xx errors are retryable\n if (error instanceof WorkerAPIError) {\n return error.statusCode ? error.statusCode >= 500 : false;\n }\n\n // Upload errors with 5xx or 429 status codes are retryable\n if (error instanceof UploadError) {\n if (error.statusCode) {\n return error.statusCode >= 500 || error.statusCode === 429;\n }\n return false;\n }\n\n // Network-level errors (Node.js)\n if (error.code === 'ECONNRESET' ||\n error.code === 'ETIMEDOUT' ||\n error.code === 'ENOTFOUND' ||\n error.code === 'ECONNREFUSED') {\n return true;\n }\n\n return false;\n}\n","/**\n * Common platform types and utilities\n */\n\nimport type { FileInfo } from '../types/file.js';\nimport type { ProcessingConfig } from '../types/processing.js';\n\n/**\n * Platform-specific file source\n * Can be a path string (Node.js) or File object (Browser)\n */\nexport type FileSource = string | File;\n\n/**\n * Platform-specific scanner interface\n */\nexport interface PlatformScanner {\n /**\n * Scan files from the provided source\n * @param source - File source (path for Node.js, File[] for browser)\n * @param options - Scan options\n */\n scanFiles(\n source: FileSource | FileSource[],\n options: PlatformScanOptions\n ): Promise<FileInfo[]>;\n\n /**\n * Read file contents as ArrayBuffer\n * @param file - FileInfo with platform-specific localPath\n */\n readFile(file: FileInfo): Promise<ArrayBuffer>;\n}\n\n/**\n * Options for platform scanning\n */\nexport interface PlatformScanOptions {\n /**\n * Logical root path for the batch\n */\n rootPath: string;\n\n /**\n * Follow symbolic links (Node.js only)\n */\n followSymlinks?: boolean;\n\n /**\n * Default processing configuration\n */\n defaultProcessingConfig?: ProcessingConfig;\n}\n\n/**\n * Detect current runtime platform\n */\nexport function detectPlatform(): 'node' | 'browser' | 'unknown' {\n // Check for Node.js\n if (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n ) {\n return 'node';\n }\n\n // Check for browser\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * Normalize path separators to forward slashes\n */\nexport function normalizePath(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\n/**\n * Get file extension from filename\n */\nexport function getExtension(filename: string): string {\n const lastDot = filename.lastIndexOf('.');\n return lastDot === -1 ? '' : filename.slice(lastDot + 1).toLowerCase();\n}\n\n/**\n * Get MIME type from filename\n */\nexport function getMimeType(filename: string): string {\n const ext = getExtension(filename);\n\n // Basic MIME type mapping\n const mimeTypes: Record<string, string> = {\n // Images\n 'jpg': 'image/jpeg',\n 'jpeg': 'image/jpeg',\n 'png': 'image/png',\n 'gif': 'image/gif',\n 'webp': 'image/webp',\n 'tif': 'image/tiff',\n 'tiff': 'image/tiff',\n 'bmp': 'image/bmp',\n 'svg': 'image/svg+xml',\n\n // Documents\n 'pdf': 'application/pdf',\n 'txt': 'text/plain',\n 'json': 'application/json',\n 'xml': 'application/xml',\n 'html': 'text/html',\n 'htm': 'text/html',\n 'css': 'text/css',\n 'js': 'application/javascript',\n\n // Archives\n 'zip': 'application/zip',\n 'tar': 'application/x-tar',\n 'gz': 'application/gzip',\n\n // Audio\n 'mp3': 'audio/mpeg',\n 'wav': 'audio/wav',\n 'ogg': 'audio/ogg',\n\n // Video\n 'mp4': 'video/mp4',\n 'webm': 'video/webm',\n 'mov': 'video/quicktime',\n };\n\n return mimeTypes[ext] || 'application/octet-stream';\n}\n","/**\n * Validation utilities for paths, files, and configuration\n */\n\nimport { ValidationError } from '../utils/errors.js';\nimport type { CustomPrompts } from '../types/config.js';\n\n// Size limits per API spec\nconst MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB\nconst MAX_BATCH_SIZE = 100 * 1024 * 1024 * 1024; // 100 GB\n\n// Invalid path characters\nconst INVALID_PATH_CHARS = /[<>:\"|?*\\x00-\\x1f]/;\n\n// Image MIME types that will be processed by OCR\nconst OCR_PROCESSABLE_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n];\n\n/**\n * Get file extension (including the dot)\n */\nexport function getFileExtension(fileName: string): string {\n const match = fileName.match(/\\.[^.]+$/);\n return match ? match[0] : '';\n}\n\n/**\n * Validate file size\n */\nexport function validateFileSize(size: number): void {\n if (size <= 0) {\n throw new ValidationError('File size must be greater than 0');\n }\n if (size > MAX_FILE_SIZE) {\n throw new ValidationError(\n `File size (${formatBytes(size)}) exceeds maximum allowed size (${formatBytes(MAX_FILE_SIZE)})`\n );\n }\n}\n\n/**\n * Validate batch size\n */\nexport function validateBatchSize(totalSize: number): void {\n if (totalSize > MAX_BATCH_SIZE) {\n throw new ValidationError(\n `Total batch size (${formatBytes(totalSize)}) exceeds maximum allowed size (${formatBytes(MAX_BATCH_SIZE)})`\n );\n }\n}\n\n/**\n * Validate logical path format\n */\nexport function validateLogicalPath(path: string): void {\n // Must start with /\n if (!path.startsWith('/')) {\n throw new ValidationError('Logical path must start with /', 'path');\n }\n\n // No invalid characters\n if (INVALID_PATH_CHARS.test(path)) {\n throw new ValidationError(\n 'Logical path contains invalid characters',\n 'path'\n );\n }\n\n // Allow \"/\" as root path, otherwise require at least one segment\n const segments = path.split('/').filter((s) => s.length > 0);\n if (segments.length === 0 && path !== '/') {\n throw new ValidationError('Logical path cannot be empty', 'path');\n }\n\n // No . or .. segments (directory traversal)\n for (const segment of segments) {\n if (segment === '.' || segment === '..') {\n throw new ValidationError(\n 'Logical path cannot contain . or .. segments',\n 'path'\n );\n }\n }\n}\n\n/**\n * Validate worker URL\n */\nexport function validateWorkerUrl(url: string): void {\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error('Protocol must be http or https');\n }\n } catch (error: any) {\n throw new ValidationError(`Invalid worker URL: ${error.message}`, 'workerUrl');\n }\n}\n\n/**\n * Validate uploader name\n */\nexport function validateUploader(uploader: string): void {\n if (!uploader || uploader.trim().length === 0) {\n throw new ValidationError('Uploader name cannot be empty', 'uploader');\n }\n}\n\n/**\n * Validate parent PI format\n * Note: Existence validation happens at worker level\n */\nexport function validateParentPi(pi: string): void {\n // PI must be exactly 26 characters (ULID format)\n if (pi.length !== 26) {\n throw new ValidationError(\n 'parent_pi must be exactly 26 characters',\n 'parent_pi'\n );\n }\n\n // PI must be alphanumeric (case-insensitive)\n if (!/^[0-9A-Z]{26}$/i.test(pi)) {\n throw new ValidationError(\n 'parent_pi must contain only alphanumeric characters (0-9, A-Z)',\n 'parent_pi'\n );\n }\n}\n\n/**\n * Validate metadata JSON\n */\nexport function validateMetadata(metadata: string): Record<string, any> {\n try {\n const parsed = JSON.parse(metadata);\n if (typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('Metadata must be a JSON object');\n }\n return parsed;\n } catch (error: any) {\n throw new ValidationError(`Invalid metadata JSON: ${error.message}`, 'metadata');\n }\n}\n\n/**\n * Validate .ref.json file content\n *\n * Required fields:\n * - url: Publicly accessible HTTP(S) URL to the referenced resource\n *\n * Optional fields:\n * - type: MIME type (e.g., 'image/jpeg', 'application/pdf')\n * - size: File size in bytes\n * - filename: Original filename for display\n * - ocr: Pre-existing OCR text (if already processed)\n *\n * Note: All other fields are allowed and will be passed through to the worker.\n */\nexport function validateRefJson(content: string, fileName: string, logger?: any): void {\n let parsed: any;\n\n // Parse JSON\n try {\n parsed = JSON.parse(content);\n } catch (error: any) {\n throw new ValidationError(\n `Invalid JSON in ${fileName}: ${error.message}`,\n 'ref'\n );\n }\n\n // Must be an object\n if (typeof parsed !== 'object' || Array.isArray(parsed) || parsed === null) {\n throw new ValidationError(\n `${fileName} must contain a JSON object`,\n 'ref'\n );\n }\n\n // Required field: url\n if (!parsed.url || typeof parsed.url !== 'string') {\n throw new ValidationError(\n `${fileName} must contain a 'url' field with a string value`,\n 'ref'\n );\n }\n\n // Validate URL format\n try {\n const url = new URL(parsed.url);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('URL must use HTTP or HTTPS protocol');\n }\n } catch (error: any) {\n throw new ValidationError(\n `Invalid URL in ${fileName}: ${error.message}`,\n 'ref'\n );\n }\n\n // Warn if type field is missing\n if (!parsed.type) {\n if (logger) {\n logger.warn(`${fileName}: Missing 'type' field (optional but recommended)`);\n }\n }\n\n // Warn if type is OCR-processable but extension not in filename\n if (parsed.type && OCR_PROCESSABLE_TYPES.includes(parsed.type)) {\n const typeToExt: { [key: string]: string } = {\n 'image/jpeg': '.jpg',\n 'image/png': '.png',\n 'image/webp': '.webp',\n };\n\n const expectedExt = typeToExt[parsed.type];\n if (expectedExt && !fileName.includes(`${expectedExt}.ref.json`)) {\n if (logger) {\n logger.warn(\n `${fileName}: Type is '${parsed.type}' but filename doesn't include '${expectedExt}.ref.json' pattern. ` +\n `This file may not be processed by OCR. Consider renaming to include the extension (e.g., 'photo${expectedExt}.ref.json').`\n );\n }\n }\n }\n}\n\n/**\n * Format bytes to human-readable string\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;\n}\n\n/**\n * Normalize path to POSIX format (forward slashes)\n */\nexport function normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/');\n}\n\n/**\n * Validate TIFF quality (for future preprocessor configuration)\n */\nexport function validateTiffQuality(quality: number): void {\n if (isNaN(quality) || quality < 1 || quality > 100) {\n throw new ValidationError(\n 'TIFF quality must be a number between 1 and 100',\n 'tiffQuality'\n );\n }\n}\n\n/**\n * Validate custom prompts\n */\nexport function validateCustomPrompts(prompts?: CustomPrompts): void {\n if (!prompts) return;\n\n const MAX_LENGTH = 50000; // 50KB per field - supports metadata file uploads\n const MAX_TOTAL_LENGTH = 75000; // 75KB total - stays under 128KB queue message limit\n const fields: Array<keyof CustomPrompts> = [\n 'general',\n 'reorganization',\n 'pinax',\n 'description',\n 'cheimarros',\n ];\n\n let totalLength = 0;\n\n for (const field of fields) {\n const value = prompts[field];\n if (value) {\n if (value.length > MAX_LENGTH) {\n throw new ValidationError(\n `Custom prompt '${field}' exceeds maximum length of ${MAX_LENGTH} characters (current: ${value.length})`,\n 'customPrompts'\n );\n }\n totalLength += value.length;\n }\n }\n\n if (totalLength > MAX_TOTAL_LENGTH) {\n throw new ValidationError(\n `Total custom prompts length (${totalLength}) exceeds maximum of ${MAX_TOTAL_LENGTH} characters`,\n 'customPrompts'\n );\n }\n}\n\n/**\n * Validate that customPrompts is not incorrectly placed in processing config\n */\nexport function validateCustomPromptsLocation(processingConfig?: any): void {\n if (!processingConfig) return;\n\n // Check if customPrompts was incorrectly placed inside processing config\n if ('customPrompts' in processingConfig) {\n throw new ValidationError(\n 'customPrompts must be a top-level field in UploaderConfig, not inside the processing config. ' +\n 'Use: new ArkeUploader({ customPrompts: {...}, processing: {...} }) ' +\n 'NOT: new ArkeUploader({ processing: { customPrompts: {...} } })',\n 'processing'\n );\n }\n}\n","/**\n * Hash and CID computation utilities\n */\n\nimport { CID } from 'multiformats/cid';\nimport * as raw from 'multiformats/codecs/raw';\nimport { sha256 } from 'multiformats/hashes/sha2';\n\n/**\n * Compute IPFS CID v1 for a file (Node.js only)\n * Uses raw codec and SHA-256 hash\n * Returns base32-encoded CID string\n */\nexport async function computeFileCID(filePath: string): Promise<string> {\n // Dynamic import to avoid bundling fs in browser builds\n const fs = await import('fs/promises');\n\n try {\n // Read file contents\n const fileBuffer = await fs.readFile(filePath);\n\n // Compute SHA-256 hash\n const hash = await sha256.digest(fileBuffer);\n\n // Create CID v1 with raw codec\n const cid = CID.create(1, raw.code, hash);\n\n // Return base32-encoded string (default for v1)\n return cid.toString();\n } catch (error: any) {\n throw new Error(`CID computation failed: ${error.message}`);\n }\n}\n\n/**\n * Compute CID for a buffer (works in all environments)\n */\nexport async function computeBufferCID(buffer: Buffer): Promise<string> {\n const hash = await sha256.digest(buffer);\n const cid = CID.create(1, raw.code, hash);\n return cid.toString();\n}\n\n/**\n * Compute CID from Uint8Array (browser-compatible)\n */\nexport async function computeCIDFromBuffer(data: Uint8Array): Promise<string> {\n const hash = await sha256.digest(data);\n const cid = CID.create(1, raw.code, hash);\n return cid.toString();\n}\n","/**\n * Processing configuration types for per-directory control\n */\n\n/**\n * Configuration for processing stages applied to files\n */\nexport interface ProcessingConfig {\n /** Enable OCR on eligible files */\n ocr: boolean;\n\n /** Enable description/summary generation */\n describe: boolean;\n\n /** Enable pinax metadata generation */\n pinax: boolean;\n}\n\n/**\n * Default processing configuration\n */\nexport const DEFAULT_PROCESSING_CONFIG: ProcessingConfig = {\n ocr: true,\n describe: true,\n pinax: true,\n};\n","/**\n * Node.js platform adapter for file scanning\n */\n\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { FileInfo } from '../types/file.js';\nimport { ScanError } from '../utils/errors.js';\nimport { validateFileSize, validateLogicalPath, validateRefJson } from '../lib/validation.js';\nimport { computeFileCID } from '../utils/hash.js';\nimport { DEFAULT_PROCESSING_CONFIG, type ProcessingConfig } from '../types/processing.js';\nimport type { PlatformScanner, PlatformScanOptions } from './common.js';\nimport { normalizePath, getMimeType } from './common.js';\n\n/**\n * Node.js file scanner implementation\n */\nexport class NodeScanner implements PlatformScanner {\n /**\n * Scan directory recursively and collect file metadata\n */\n async scanFiles(\n source: string | string[],\n options: PlatformScanOptions\n ): Promise<FileInfo[]> {\n const dirPath = Array.isArray(source) ? source[0] : source;\n\n if (!dirPath || typeof dirPath !== 'string') {\n throw new ScanError('Node.js scanner requires a directory path', '');\n }\n\n const files: FileInfo[] = [];\n\n // Validate directory exists\n try {\n const stats = await fs.stat(dirPath);\n if (!stats.isDirectory()) {\n throw new ScanError(`Path is not a directory: ${dirPath}`, dirPath);\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw new ScanError(`Directory not found: ${dirPath}`, dirPath);\n }\n throw new ScanError(`Cannot access directory: ${error.message}`, dirPath);\n }\n\n // Validate logical path\n validateLogicalPath(options.rootPath);\n\n const globalProcessingConfig = options.defaultProcessingConfig || DEFAULT_PROCESSING_CONFIG;\n\n /**\n * Load processing config from directory\n */\n async function loadDirectoryProcessingConfig(\n dirPath: string\n ): Promise<ProcessingConfig | null> {\n const configPath = path.join(dirPath, '.arke-process.json');\n try {\n const content = await fs.readFile(configPath, 'utf-8');\n return JSON.parse(content);\n } catch (error: any) {\n if (error.code !== 'ENOENT') {\n console.warn(`Error reading processing config ${configPath}: ${error.message}`);\n }\n return null;\n }\n }\n\n /**\n * Merge configs\n */\n function mergeProcessingConfig(\n defaults: ProcessingConfig,\n override: Partial<ProcessingConfig> | null\n ): ProcessingConfig {\n if (!override) return defaults;\n return {\n ocr: override.ocr ?? defaults.ocr,\n describe: override.describe ?? defaults.describe,\n pinax: override.pinax ?? defaults.pinax,\n };\n }\n\n /**\n * Recursive walker\n */\n async function walk(currentPath: string, relativePath: string = ''): Promise<void> {\n const dirConfigOverride = await loadDirectoryProcessingConfig(currentPath);\n const currentProcessingConfig = mergeProcessingConfig(\n globalProcessingConfig,\n dirConfigOverride\n );\n\n let entries;\n try {\n entries = await fs.readdir(currentPath, { withFileTypes: true });\n } catch (error: any) {\n console.warn(`Cannot read directory: ${currentPath}`, error.message);\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(currentPath, entry.name);\n const relPath = path.join(relativePath, entry.name);\n\n try {\n // Handle symlinks\n if (entry.isSymbolicLink()) {\n if (!options.followSymlinks) {\n continue;\n }\n\n const stats = await fs.stat(fullPath);\n if (stats.isDirectory()) {\n await walk(fullPath, relPath);\n } else if (stats.isFile()) {\n await processFile(fullPath, relPath, stats.size, currentProcessingConfig);\n }\n continue;\n }\n\n // Handle directories\n if (entry.isDirectory()) {\n await walk(fullPath, relPath);\n continue;\n }\n\n // Handle regular files\n if (entry.isFile()) {\n const stats = await fs.stat(fullPath);\n await processFile(fullPath, relPath, stats.size, currentProcessingConfig);\n }\n } catch (error: any) {\n if (error instanceof ScanError && error.message.includes('.ref.json')) {\n throw error;\n }\n console.warn(`Error processing ${fullPath}: ${error.message}`);\n continue;\n }\n }\n }\n\n /**\n * Process single file\n */\n async function processFile(\n fullPath: string,\n relativePath: string,\n size: number,\n processingConfig: ProcessingConfig\n ): Promise<void> {\n const fileName = path.basename(fullPath);\n\n // Skip processing config files\n if (fileName === '.arke-process.json') {\n return;\n }\n\n // Validate .ref.json files\n if (fileName.endsWith('.ref.json')) {\n try {\n const content = await fs.readFile(fullPath, 'utf-8');\n validateRefJson(content, fileName, console);\n } catch (error: any) {\n throw new ScanError(\n `Invalid .ref.json file: ${fileName} - ${error.message}`,\n fullPath\n );\n }\n }\n\n // Validate file size\n try {\n validateFileSize(size);\n } catch (error: any) {\n console.warn(`Skipping file that exceeds size limit: ${fileName}`, error.message);\n return;\n }\n\n // Construct logical path\n const normalizedRelPath = normalizePath(relativePath);\n const logicalPath = path.posix.join(options.rootPath, normalizedRelPath);\n\n // Validate logical path\n try {\n validateLogicalPath(logicalPath);\n } catch (error: any) {\n console.warn(`Skipping file with invalid logical path: ${logicalPath}`, error.message);\n return;\n }\n\n // Determine content type\n const contentType = getMimeType(fileName);\n\n // Check if file is readable\n try {\n await fs.access(fullPath, fs.constants.R_OK);\n } catch (error) {\n console.warn(`Skipping unreadable file: ${fullPath}`);\n return;\n }\n\n // Compute CID (optional - continue without if computation fails)\n let cid: string | undefined;\n try {\n cid = await computeFileCID(fullPath);\n } catch (error: any) {\n console.warn(`Warning: CID computation failed for ${fullPath}, continuing without CID:`, error.message);\n cid = undefined;\n }\n\n // Add to results\n files.push({\n localPath: fullPath,\n logicalPath,\n fileName,\n size,\n contentType,\n cid,\n processingConfig,\n });\n }\n\n // Start scan\n await walk(dirPath);\n\n // Sort by size (smallest first)\n files.sort((a, b) => a.size - b.size);\n\n return files;\n }\n\n /**\n * Read file contents as ArrayBuffer\n */\n async readFile(file: FileInfo): Promise<ArrayBuffer> {\n const buffer = await fs.readFile(file.localPath);\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);\n }\n}\n","/**\n * Browser platform adapter for file handling\n */\n\nimport type { FileInfo } from '../types/file.js';\nimport { ScanError } from '../utils/errors.js';\nimport { validateFileSize, validateLogicalPath } from '../lib/validation.js';\nimport { computeCIDFromBuffer } from '../utils/hash.js';\nimport { DEFAULT_PROCESSING_CONFIG } from '../types/processing.js';\nimport type { PlatformScanner, PlatformScanOptions } from './common.js';\nimport { normalizePath, getMimeType } from './common.js';\n\n/**\n * Browser file scanner implementation\n */\nexport class BrowserScanner implements PlatformScanner {\n /**\n * Scan files from File or FileList\n */\n async scanFiles(\n source: File | File[],\n options: PlatformScanOptions\n ): Promise<FileInfo[]> {\n const fileList = Array.isArray(source) ? source : [source];\n\n if (fileList.length === 0) {\n throw new ScanError('No files provided', '');\n }\n\n // Validate logical path\n validateLogicalPath(options.rootPath);\n\n const globalProcessingConfig = options.defaultProcessingConfig || DEFAULT_PROCESSING_CONFIG;\n const files: FileInfo[] = [];\n\n for (const file of fileList) {\n try {\n const fileInfo = await this.processFile(file, options.rootPath, globalProcessingConfig);\n if (fileInfo) {\n files.push(fileInfo);\n }\n } catch (error: any) {\n console.warn(`Error processing ${file.name}: ${error.message}`);\n continue;\n }\n }\n\n // Sort by size (smallest first)\n files.sort((a, b) => a.size - b.size);\n\n return files;\n }\n\n /**\n * Process a single File object\n */\n private async processFile(\n file: File,\n rootPath: string,\n processingConfig: any\n ): Promise<FileInfo | null> {\n const fileName = file.name;\n const size = file.size;\n\n // Skip hidden files (starting with .) - includes .DS_Store, .gitignore, etc.\n // These often have permission issues or are constantly modified by the OS\n if (fileName.startsWith('.')) {\n return null;\n }\n\n // Skip common system/temp files that shouldn't be uploaded\n const skipFiles = ['Thumbs.db', 'desktop.ini', '__MACOSX'];\n if (skipFiles.includes(fileName)) {\n return null;\n }\n\n // Skip processing config files\n if (fileName === '.arke-process.json') {\n return null;\n }\n\n // Validate file size\n try {\n validateFileSize(size);\n } catch (error: any) {\n console.warn(`Skipping file that exceeds size limit: ${fileName}`, error.message);\n return null;\n }\n\n // Extract relative path from file.webkitRelativePath or use just the filename\n let relativePath = '';\n if ('webkitRelativePath' in file && file.webkitRelativePath) {\n // For directory uploads, extract relative path\n const parts = file.webkitRelativePath.split('/');\n // Remove the first part (directory name) and join the rest\n if (parts.length > 1) {\n relativePath = parts.slice(1).join('/');\n } else {\n relativePath = fileName;\n }\n } else {\n relativePath = fileName;\n }\n\n // Construct logical path\n const normalizedRelPath = normalizePath(relativePath);\n const logicalPath = `${rootPath}/${normalizedRelPath}`.replace(/\\/+/g, '/');\n\n // Validate logical path\n try {\n validateLogicalPath(logicalPath);\n } catch (error: any) {\n console.warn(`Skipping file with invalid logical path: ${logicalPath}`, error.message);\n return null;\n }\n\n // Determine content type\n const contentType = file.type || getMimeType(fileName);\n\n // Compute CID (optional - continue without if computation fails)\n let cid: string | undefined;\n try {\n const buffer = await file.arrayBuffer();\n cid = await computeCIDFromBuffer(new Uint8Array(buffer));\n } catch (error: any) {\n console.warn(`Warning: CID computation failed for ${fileName}, continuing without CID:`, error.message);\n cid = undefined;\n }\n\n // For browser files, we store the File object itself as a special marker\n // The actual File object will be passed separately during upload\n return {\n localPath: `__browser_file__${fileName}`, // Special marker for browser files\n logicalPath,\n fileName,\n size,\n contentType,\n cid,\n processingConfig,\n };\n }\n\n /**\n * Read file contents as ArrayBuffer\n * Note: In browser context, the File object should be passed directly\n */\n async readFile(file: FileInfo): Promise<ArrayBuffer> {\n throw new Error('Browser scanner requires File objects to be provided directly during upload');\n }\n}\n","export class CollectionsError extends Error {\n constructor(\n message: string,\n public code: string = 'UNKNOWN_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'CollectionsError';\n }\n}\n","import { CollectionsError } from './errors';\nimport type {\n ChangeRootPayload,\n ChangeRootResponse,\n Collection,\n CollectionDetails,\n CollectionRole,\n CreateCollectionPayload,\n Invitation,\n InvitationsResponse,\n Member,\n MembersResponse,\n MyAccessResponse,\n MyCollectionsResponse,\n PaginatedCollections,\n PiPermissions,\n RegisterRootPayload,\n RootResponse,\n SuccessResponse,\n UpdateCollectionPayload,\n} from './types';\n\nexport interface CollectionsClientConfig {\n /**\n * Gateway base URL (e.g., https://api.arke.institute).\n * Must already point at the Arke gateway that proxies /collections/*.\n */\n gatewayUrl: string;\n /**\n * Optional bearer token for authenticated routes.\n * Public routes will still include it if provided.\n */\n authToken?: string;\n /**\n * Optional custom fetch (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\nexport class CollectionsClient {\n private baseUrl: string;\n private authToken?: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: CollectionsClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.authToken = config.authToken;\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n setAuthToken(token?: string) {\n this.authToken = token;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private getHeaders(authRequired: boolean): HeadersInit {\n const headers: HeadersInit = { 'Content-Type': 'application/json' };\n if (authRequired || this.authToken) {\n if (!this.authToken && authRequired) {\n throw new CollectionsError('Authentication required for this operation', 'AUTH_REQUIRED');\n }\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n }\n return headers;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n authRequired?: boolean;\n query?: Record<string, string | number | undefined>;\n } = {}\n ): Promise<T> {\n const authRequired = options.authRequired ?? false;\n const url = this.buildUrl(path, options.query);\n const headers = new Headers(this.getHeaders(authRequired));\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n const response = await this.fetchImpl(url, { ...options, headers });\n\n if (response.ok) {\n if (response.status === 204) {\n return undefined as T;\n }\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : `Request failed with status ${response.status}`;\n\n throw new CollectionsError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Collections\n // ---------------------------------------------------------------------------\n\n async listCollections(params?: { limit?: number; offset?: number }): Promise<PaginatedCollections> {\n return this.request('/collections', {\n method: 'GET',\n query: { limit: params?.limit, offset: params?.offset },\n });\n }\n\n async getCollection(id: string): Promise<CollectionDetails> {\n return this.request(`/collections/${id}`, { method: 'GET' });\n }\n\n async getCollectionRoot(id: string): Promise<RootResponse> {\n return this.request(`/collections/${id}/root`, { method: 'GET' });\n }\n\n async getMyAccess(id: string): Promise<MyAccessResponse> {\n return this.request(`/collections/${id}/my-access`, { method: 'GET', authRequired: true });\n }\n\n async createCollection(payload: CreateCollectionPayload): Promise<Collection> {\n return this.request('/collections', {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async registerRoot(payload: RegisterRootPayload): Promise<Collection & { rootPi: string }> {\n return this.request('/collections/register-root', {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async updateCollection(id: string, payload: UpdateCollectionPayload): Promise<Collection> {\n return this.request(`/collections/${id}`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async changeRoot(id: string, payload: ChangeRootPayload): Promise<ChangeRootResponse> {\n return this.request(`/collections/${id}/change-root`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async deleteCollection(id: string): Promise<SuccessResponse> {\n return this.request(`/collections/${id}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Members\n // ---------------------------------------------------------------------------\n\n async listMembers(collectionId: string): Promise<MembersResponse> {\n return this.request(`/collections/${collectionId}/members`, { method: 'GET' });\n }\n\n async updateMemberRole(\n collectionId: string,\n userId: string,\n role: CollectionRole\n ): Promise<{ success: true; role: CollectionRole }> {\n return this.request(`/collections/${collectionId}/members/${userId}`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify({ role }),\n });\n }\n\n async removeMember(collectionId: string, userId: string): Promise<SuccessResponse> {\n return this.request(`/collections/${collectionId}/members/${userId}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Invitations\n // ---------------------------------------------------------------------------\n\n async createInvitation(collectionId: string, email: string, role: CollectionRole): Promise<Invitation> {\n return this.request(`/collections/${collectionId}/invitations`, {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify({ email, role }),\n });\n }\n\n async listInvitations(collectionId: string): Promise<InvitationsResponse> {\n return this.request(`/collections/${collectionId}/invitations`, {\n method: 'GET',\n authRequired: true,\n });\n }\n\n async acceptInvitation(invitationId: string): Promise<{ success: true; role: CollectionRole }> {\n return this.request(`/invitations/${invitationId}/accept`, {\n method: 'POST',\n authRequired: true,\n });\n }\n\n async declineInvitation(invitationId: string): Promise<SuccessResponse> {\n return this.request(`/invitations/${invitationId}/decline`, {\n method: 'POST',\n authRequired: true,\n });\n }\n\n async revokeInvitation(invitationId: string): Promise<SuccessResponse> {\n return this.request(`/invitations/${invitationId}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Current user\n // ---------------------------------------------------------------------------\n\n async getMyCollections(): Promise<MyCollectionsResponse> {\n return this.request('/me/collections', { method: 'GET', authRequired: true });\n }\n\n async getMyInvitations(): Promise<InvitationsResponse> {\n return this.request('/me/invitations', { method: 'GET', authRequired: true });\n }\n\n // ---------------------------------------------------------------------------\n // PI permissions\n // ---------------------------------------------------------------------------\n\n async getPiPermissions(pi: string): Promise<PiPermissions> {\n return this.request(`/pi/${pi}/permissions`, { method: 'GET' });\n }\n}\n","/**\n * API client for communicating with the Arke Ingest Worker (fetch-based)\n */\n\nimport type {\n InitBatchRequest,\n InitBatchResponse,\n StartFileUploadRequest,\n StartFileUploadResponse,\n CompleteFileUploadRequest,\n CompleteFileUploadResponse,\n FinalizeBatchResponse,\n BatchStatusResponse,\n ErrorResponse,\n} from '../types/api.js';\nimport { WorkerAPIError, NetworkError } from '../utils/errors.js';\nimport { retryWithBackoff } from '../utils/retry.js';\n\nexport interface WorkerClientConfig {\n baseUrl: string;\n authToken?: string;\n timeout?: number;\n maxRetries?: number;\n retryInitialDelay?: number;\n retryMaxDelay?: number;\n retryJitter?: boolean;\n debug?: boolean;\n}\n\nexport class WorkerClient {\n private baseUrl: string;\n private authToken?: string;\n private timeout: number;\n private maxRetries: number;\n private retryInitialDelay: number;\n private retryMaxDelay: number;\n private retryJitter: boolean;\n private debug: boolean;\n\n constructor(config: WorkerClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.authToken = config.authToken;\n this.timeout = config.timeout ?? 30000; // 30 seconds\n this.maxRetries = config.maxRetries ?? 3;\n this.retryInitialDelay = config.retryInitialDelay ?? 1000; // 1 second\n this.retryMaxDelay = config.retryMaxDelay ?? 30000; // 30 seconds\n this.retryJitter = config.retryJitter ?? true;\n this.debug = config.debug ?? false;\n }\n\n setAuthToken(token?: string) {\n this.authToken = token;\n }\n\n /**\n * Make HTTP request with fetch\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n if (this.debug) {\n console.log(`HTTP Request: ${method} ${url}`, body);\n }\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data = await response.json();\n\n if (this.debug) {\n console.log(`HTTP Response: ${response.status}`, data);\n }\n\n if (!response.ok) {\n const errorData = data as ErrorResponse;\n throw new WorkerAPIError(\n errorData.error || 'Request failed',\n response.status,\n errorData.details\n );\n }\n\n return data as T;\n } catch (error: any) {\n if (error instanceof WorkerAPIError) {\n throw error;\n }\n\n if (error.name === 'AbortError') {\n throw new NetworkError(`Request timeout after ${this.timeout}ms`);\n }\n\n throw new NetworkError(`Network request failed: ${error.message}`);\n }\n }\n\n /**\n * Initialize a new batch upload\n */\n async initBatch(params: InitBatchRequest): Promise<InitBatchResponse> {\n return retryWithBackoff(\n () => this.request<InitBatchResponse>('POST', '/ingest/batches/init', params),\n {\n maxRetries: this.maxRetries,\n initialDelay: this.retryInitialDelay,\n maxDelay: this.retryMaxDelay,\n jitter: this.retryJitter,\n }\n );\n }\n\n /**\n * Request presigned URLs for a file upload\n */\n async startFileUpload(\n batchId: string,\n params: StartFileUploadRequest\n ): Promise<StartFileUploadResponse> {\n return retryWithBackoff(\n () =>\n this.request<StartFileUploadResponse>(\n 'POST',\n `/ingest/batches/${batchId}/files/start`,\n params\n ),\n {\n maxRetries: this.maxRetries,\n initialDelay: this.retryInitialDelay,\n maxDelay: this.retryMaxDelay,\n jitter: this.retryJitter,\n }\n );\n }\n\n /**\n * Mark a file upload as complete\n */\n async completeFileUpload(\n batchId: string,\n params: CompleteFileUploadRequest\n ): Promise<CompleteFileUploadResponse> {\n return retryWithBackoff(\n () =>\n this.request<CompleteFileUploadResponse>(\n 'POST',\n `/ingest/batches/${batchId}/files/complete`,\n params\n ),\n {\n maxRetries: this.maxRetries,\n initialDelay: this.retryInitialDelay,\n maxDelay: this.retryMaxDelay,\n jitter: this.retryJitter,\n }\n );\n }\n\n /**\n * Finalize the batch after all files are uploaded\n * Returns root_pi immediately for small batches, or status='discovery' for large batches\n */\n async finalizeBatch(batchId: string): Promise<FinalizeBatchResponse> {\n return retryWithBackoff(\n () =>\n this.request<FinalizeBatchResponse>(\n 'POST',\n `/ingest/batches/${batchId}/finalize`,\n {}\n ),\n {\n maxRetries: this.maxRetries,\n initialDelay: this.retryInitialDelay,\n maxDelay: this.retryMaxDelay,\n jitter: this.retryJitter,\n }\n );\n }\n\n /**\n * Get current batch status (used for polling during async discovery)\n */\n async getBatchStatus(batchId: string): Promise<BatchStatusResponse> {\n return retryWithBackoff(\n () =>\n this.request<BatchStatusResponse>(\n 'GET',\n `/ingest/batches/${batchId}/status`\n ),\n {\n maxRetries: this.maxRetries,\n initialDelay: this.retryInitialDelay,\n maxDelay: this.retryMaxDelay,\n jitter: this.retryJitter,\n }\n );\n }\n}\n","/**\n * Retry logic with exponential backoff\n */\n\nimport { isRetryableError } from './errors.js';\n\nexport interface RetryOptions {\n maxRetries: number;\n initialDelay: number;\n maxDelay: number;\n shouldRetry?: (error: any) => boolean;\n jitter?: boolean; // Add randomization to prevent thundering herd\n}\n\nconst DEFAULT_OPTIONS: RetryOptions = {\n maxRetries: 3,\n initialDelay: 1000, // 1 second\n maxDelay: 30000, // 30 seconds\n shouldRetry: isRetryableError,\n jitter: true,\n};\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: Partial<RetryOptions> = {}\n): Promise<T> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n let lastError: any;\n\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: any) {\n lastError = error;\n\n // Don't retry if we've exhausted attempts\n if (attempt >= opts.maxRetries) {\n throw error;\n }\n\n // Check if error is retryable\n if (opts.shouldRetry && !opts.shouldRetry(error)) {\n throw error;\n }\n\n // Handle 429 Rate Limit with Retry-After header\n let delay: number;\n if (error.statusCode === 429 && error.retryAfter) {\n // Use Retry-After header if present (in seconds)\n delay = Math.min(error.retryAfter * 1000, opts.maxDelay);\n } else {\n // Calculate delay with exponential backoff\n delay = Math.min(\n opts.initialDelay * Math.pow(2, attempt),\n opts.maxDelay\n );\n }\n\n // Add jitter to prevent thundering herd (±25% randomization)\n if (opts.jitter) {\n const jitterAmount = delay * 0.25;\n delay = delay + (Math.random() * jitterAmount * 2 - jitterAmount);\n }\n\n await sleep(Math.floor(delay));\n }\n }\n\n throw lastError;\n}\n\n/**\n * Sleep for a given number of milliseconds\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Main ArkeUploader SDK class\n */\n\nimport type {\n UploaderConfig,\n UploadOptions,\n UploadProgress,\n BatchResult,\n} from './types/config.js';\nimport type { FileInfo } from './types/file.js';\nimport { WorkerClient } from './lib/worker-client-fetch.js';\nimport { detectPlatform, type PlatformScanner, type FileSource } from './platforms/common.js';\nimport { uploadSimple } from './lib/simple-fetch.js';\nimport { uploadMultipart } from './lib/multipart-fetch.js';\nimport { ValidationError } from './utils/errors.js';\nimport { validateBatchSize, validateCustomPrompts, validateCustomPromptsLocation } from './lib/validation.js';\n\nconst MULTIPART_THRESHOLD = 5 * 1024 * 1024; // 5 MB\n\n/**\n * Upload client for Arke Institute's ingest service\n * Works in Node.js, browsers, and other JavaScript runtimes\n */\nexport class ArkeUploader {\n private config: UploaderConfig;\n private workerClient: WorkerClient;\n private scanner: PlatformScanner | null = null;\n private platform: 'node' | 'browser' | 'unknown';\n\n constructor(config: UploaderConfig) {\n // Validate that customPrompts is not incorrectly placed in processing config\n validateCustomPromptsLocation(config.processing);\n\n this.config = {\n rootPath: '/uploads', // Must have at least one segment (not just '/')\n parallelUploads: 5,\n parallelParts: 3,\n ...config,\n };\n\n this.workerClient = new WorkerClient({\n baseUrl: config.gatewayUrl,\n authToken: config.authToken,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n retryInitialDelay: config.retryInitialDelay,\n retryMaxDelay: config.retryMaxDelay,\n retryJitter: config.retryJitter,\n debug: false,\n });\n\n this.platform = detectPlatform();\n }\n\n /**\n * Get platform-specific scanner\n */\n private async getScanner(): Promise<PlatformScanner> {\n if (this.scanner) {\n return this.scanner;\n }\n\n if (this.platform === 'node') {\n const { NodeScanner } = await import('./platforms/node.js');\n this.scanner = new NodeScanner();\n } else if (this.platform === 'browser') {\n const { BrowserScanner } = await import('./platforms/browser.js');\n this.scanner = new BrowserScanner();\n } else {\n throw new ValidationError('Unsupported platform');\n }\n\n return this.scanner;\n }\n\n /**\n * Upload a batch of files\n * @param source - Directory path (Node.js) or File[]/FileList (browser)\n * @param options - Upload options\n */\n async uploadBatch(\n source: FileSource | FileSource[],\n options: UploadOptions = {}\n ): Promise<BatchResult> {\n const startTime = Date.now();\n const { onProgress, dryRun = false } = options;\n\n // Phase 1: Scanning\n this.reportProgress(onProgress, {\n phase: 'scanning',\n filesTotal: 0,\n filesUploaded: 0,\n bytesTotal: 0,\n bytesUploaded: 0,\n percentComplete: 0,\n });\n\n const scanner = await this.getScanner();\n const files = await scanner.scanFiles(source, {\n rootPath: this.config.rootPath || '/',\n followSymlinks: true,\n defaultProcessingConfig: this.config.processing,\n });\n\n if (files.length === 0) {\n throw new ValidationError('No files found to upload');\n }\n\n const totalSize = files.reduce((sum, f) => sum + f.size, 0);\n validateBatchSize(totalSize);\n\n // Validate custom prompts if provided\n if (this.config.customPrompts) {\n validateCustomPrompts(this.config.customPrompts);\n\n // Log which custom prompts are being used\n const promptFields = Object.keys(this.config.customPrompts).filter(\n key => this.config.customPrompts![key as keyof typeof this.config.customPrompts]\n );\n console.log(`[Arke Upload SDK] Custom prompts configured: ${promptFields.join(', ')}`);\n }\n\n if (dryRun) {\n return {\n batchId: 'dry-run',\n rootPi: 'dry-run',\n filesUploaded: files.length,\n bytesUploaded: totalSize,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Phase 2: Initialize batch\n const { batch_id } = await this.workerClient.initBatch({\n uploader: this.config.uploader,\n root_path: this.config.rootPath || '/',\n parent_pi: this.config.parentPi || '',\n metadata: this.config.metadata,\n file_count: files.length,\n total_size: totalSize,\n custom_prompts: this.config.customPrompts,\n });\n\n // Confirm custom prompts were sent\n if (this.config.customPrompts) {\n console.log(`[Arke Upload SDK] Custom prompts sent to worker for batch ${batch_id}`);\n }\n\n // Phase 3: Upload files\n this.reportProgress(onProgress, {\n phase: 'uploading',\n filesTotal: files.length,\n filesUploaded: 0,\n bytesTotal: totalSize,\n bytesUploaded: 0,\n percentComplete: 0,\n });\n\n let filesUploaded = 0;\n let bytesUploaded = 0;\n\n // Upload files with concurrency control\n const { failedFiles } = await this.uploadFilesWithConcurrency(\n batch_id,\n files,\n source,\n this.config.parallelUploads || 5,\n (file, bytes) => {\n filesUploaded++;\n bytesUploaded += bytes;\n\n this.reportProgress(onProgress, {\n phase: 'uploading',\n filesTotal: files.length,\n filesUploaded,\n bytesTotal: totalSize,\n bytesUploaded,\n currentFile: file.fileName,\n percentComplete: Math.round((bytesUploaded / totalSize) * 100),\n });\n }\n );\n\n // Check if all files failed\n if (failedFiles.length === files.length) {\n throw new ValidationError(\n `All ${files.length} files failed to upload. First error: ${failedFiles[0]?.error || 'Unknown'}`\n );\n }\n\n // Log warning if some files failed but continue with finalization\n if (failedFiles.length > 0) {\n console.warn(\n `Warning: ${failedFiles.length} of ${files.length} files failed to upload:`,\n failedFiles.map(f => `${f.file.fileName}: ${f.error}`).join(', ')\n );\n }\n\n // Phase 4: Finalize and get root_pi\n this.reportProgress(onProgress, {\n phase: 'finalizing',\n filesTotal: files.length,\n filesUploaded,\n bytesTotal: totalSize,\n bytesUploaded,\n percentComplete: 95,\n });\n\n const finalizeResult = await this.workerClient.finalizeBatch(batch_id);\n\n // Get root_pi - either immediately (sync discovery) or via polling (async discovery)\n let rootPi: string;\n\n if (finalizeResult.root_pi) {\n // Sync path - root_pi available immediately\n rootPi = finalizeResult.root_pi;\n } else if (finalizeResult.status === 'discovery') {\n // Async path - poll until discovery completes\n this.reportProgress(onProgress, {\n phase: 'discovery',\n filesTotal: files.length,\n filesUploaded,\n bytesTotal: totalSize,\n bytesUploaded,\n percentComplete: 97,\n });\n\n rootPi = await this.pollForRootPi(batch_id, onProgress, files.length, totalSize, bytesUploaded);\n } else {\n // Unexpected state - this shouldn't happen but handle gracefully\n throw new ValidationError(\n `Finalization returned unexpected status: ${finalizeResult.status} without root_pi`\n );\n }\n\n // Complete\n this.reportProgress(onProgress, {\n phase: 'complete',\n filesTotal: files.length,\n filesUploaded,\n bytesTotal: totalSize,\n bytesUploaded,\n percentComplete: 100,\n });\n\n return {\n batchId: batch_id,\n rootPi,\n filesUploaded,\n bytesUploaded,\n durationMs: Date.now() - startTime,\n };\n }\n\n /**\n * Poll for root_pi during async discovery\n */\n private async pollForRootPi(\n batchId: string,\n onProgress: ((progress: UploadProgress) => void) | undefined,\n filesTotal: number,\n bytesTotal: number,\n bytesUploaded: number\n ): Promise<string> {\n const POLL_INTERVAL_MS = 2000;\n const MAX_POLL_TIME_MS = 30 * 60 * 1000; // 30 minutes\n const startTime = Date.now();\n\n while (Date.now() - startTime < MAX_POLL_TIME_MS) {\n const status = await this.workerClient.getBatchStatus(batchId);\n\n if (status.root_pi) {\n return status.root_pi;\n }\n\n if (status.status === 'failed') {\n throw new ValidationError(`Batch discovery failed`);\n }\n\n // Report discovery progress if available\n if (status.discovery_progress && onProgress) {\n const { total, published } = status.discovery_progress;\n const discoveryPercent = total > 0 ? Math.round((published / total) * 100) : 0;\n this.reportProgress(onProgress, {\n phase: 'discovery',\n filesTotal,\n filesUploaded: filesTotal,\n bytesTotal,\n bytesUploaded,\n percentComplete: 95 + Math.round(discoveryPercent * 0.04), // 95-99%\n });\n }\n\n // Wait before polling again\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n\n throw new ValidationError(`Discovery timed out after ${MAX_POLL_TIME_MS / 1000} seconds`);\n }\n\n /**\n * Upload files with controlled concurrency\n */\n private async uploadFilesWithConcurrency(\n batchId: string,\n files: FileInfo[],\n source: FileSource | FileSource[],\n concurrency: number,\n onFileComplete: (file: FileInfo, bytes: number) => void\n ): Promise<{ failedFiles: Array<{ file: FileInfo; error: string }> }> {\n const queue = [...files];\n const workers: Promise<void>[] = [];\n const failedFiles: Array<{ file: FileInfo; error: string }> = [];\n\n const processNext = async () => {\n while (queue.length > 0) {\n const file = queue.shift()!;\n try {\n await this.uploadSingleFile(batchId, file, source);\n onFileComplete(file, file.size);\n } catch (error: any) {\n // Log the error but continue with other files\n const errorMessage = error.message || 'Unknown error';\n console.error(`Failed to upload ${file.fileName}: ${errorMessage}`);\n failedFiles.push({ file, error: errorMessage });\n // Don't re-throw - continue processing other files\n }\n }\n };\n\n // Start concurrent workers\n for (let i = 0; i < Math.min(concurrency, files.length); i++) {\n workers.push(processNext());\n }\n\n await Promise.all(workers);\n return { failedFiles };\n }\n\n /**\n * Upload a single file\n */\n private async uploadSingleFile(\n batchId: string,\n file: FileInfo,\n source: FileSource | FileSource[]\n ): Promise<void> {\n // Request presigned URL(s)\n const uploadInfo = await this.workerClient.startFileUpload(batchId, {\n file_name: file.fileName,\n file_size: file.size,\n logical_path: file.logicalPath,\n content_type: file.contentType,\n cid: file.cid,\n processing_config: file.processingConfig,\n });\n\n // Get file data\n const fileData = await this.getFileData(file, source);\n\n // Prepare retry options\n const retryOptions = {\n maxRetries: this.config.maxRetries,\n retryInitialDelay: this.config.retryInitialDelay,\n retryMaxDelay: this.config.retryMaxDelay,\n retryJitter: this.config.retryJitter,\n };\n\n // Upload to R2\n if (uploadInfo.upload_type === 'simple') {\n await uploadSimple(fileData, uploadInfo.presigned_url!, file.contentType, retryOptions);\n } else {\n // Multipart upload - map presigned URLs to array of URL strings\n const partUrls = uploadInfo.presigned_urls!.map((p) => p.url);\n const parts = await uploadMultipart(\n fileData,\n partUrls,\n this.config.parallelParts || 3,\n retryOptions\n );\n\n // Complete multipart upload\n await this.workerClient.completeFileUpload(batchId, {\n r2_key: uploadInfo.r2_key,\n upload_id: uploadInfo.upload_id!,\n parts,\n });\n\n return;\n }\n\n // Complete simple upload\n await this.workerClient.completeFileUpload(batchId, {\n r2_key: uploadInfo.r2_key,\n });\n }\n\n /**\n * Get file data based on platform\n */\n private async getFileData(\n file: FileInfo,\n source: FileSource | FileSource[]\n ): Promise<ArrayBuffer> {\n if (this.platform === 'node') {\n // Read from filesystem\n const fs = await import('fs/promises');\n const buffer = await fs.readFile(file.localPath);\n return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);\n } else if (this.platform === 'browser') {\n // Find the File object from source\n const files = Array.isArray(source) ? source : [source];\n const browserFile = files.find(\n (f) => f instanceof File && f.name === file.fileName\n ) as File | undefined;\n\n if (!browserFile) {\n throw new Error(`Could not find browser File object for ${file.fileName}`);\n }\n\n return browserFile.arrayBuffer();\n }\n\n throw new Error('Unsupported platform for file reading');\n }\n\n /**\n * Report progress to callback\n */\n private reportProgress(\n callback: ((progress: UploadProgress) => void) | undefined,\n progress: UploadProgress\n ): void {\n if (callback) {\n callback(progress);\n }\n }\n}\n","/**\n * Simple upload logic for files < 5 MB (fetch-based)\n */\n\nimport { UploadError } from '../utils/errors.js';\nimport { retryWithBackoff } from '../utils/retry.js';\n\nexport interface SimpleUploadOptions {\n maxRetries?: number;\n retryInitialDelay?: number;\n retryMaxDelay?: number;\n retryJitter?: boolean;\n}\n\n/**\n * Upload file data using simple PUT to presigned URL\n */\nexport async function uploadSimple(\n fileData: ArrayBuffer,\n presignedUrl: string,\n contentType?: string,\n options: SimpleUploadOptions = {}\n): Promise<void> {\n const { maxRetries = 3, retryInitialDelay, retryMaxDelay, retryJitter } = options;\n\n await retryWithBackoff(\n async () => {\n let response: Response;\n try {\n response = await fetch(presignedUrl, {\n method: 'PUT',\n body: fileData,\n headers: {\n ...(contentType ? { 'Content-Type': contentType } : {}),\n },\n });\n } catch (error: any) {\n // Network-level errors (connection refused, timeout, etc.)\n throw new UploadError(`Upload failed: ${error.message}`, undefined, undefined, error);\n }\n\n if (!response.ok) {\n // Extract Retry-After header for 429 responses\n const retryAfter = response.headers.get('retry-after');\n const error = new UploadError(\n `Upload failed with status ${response.status}: ${response.statusText}`,\n undefined,\n response.status\n );\n\n // Attach retry-after if present (convert to seconds)\n if (retryAfter && response.status === 429) {\n (error as any).retryAfter = parseInt(retryAfter, 10);\n }\n\n throw error;\n }\n },\n {\n maxRetries,\n initialDelay: retryInitialDelay,\n maxDelay: retryMaxDelay,\n jitter: retryJitter,\n }\n );\n}\n","/**\n * Multipart upload logic for files ≥ 5 MB (fetch-based)\n */\n\nimport type { PartInfo } from '../types/api.js';\nimport { UploadError } from '../utils/errors.js';\nimport { retryWithBackoff } from '../utils/retry.js';\n\nconst DEFAULT_PART_SIZE = 10 * 1024 * 1024; // 10 MB\n\nexport interface MultipartUploadOptions {\n maxRetries?: number;\n retryInitialDelay?: number;\n retryMaxDelay?: number;\n retryJitter?: boolean;\n}\n\n/**\n * Upload file data using multipart upload with presigned URLs\n * @param fileData - File data as ArrayBuffer\n * @param presignedUrls - Array of presigned URLs for each part\n * @param concurrency - Number of parts to upload in parallel\n * @param options - Upload retry options\n * @returns Array of PartInfo with ETags\n */\nexport async function uploadMultipart(\n fileData: ArrayBuffer,\n presignedUrls: string[],\n concurrency: number = 3,\n options: MultipartUploadOptions = {}\n): Promise<PartInfo[]> {\n const totalSize = fileData.byteLength;\n const partSize = Math.ceil(totalSize / presignedUrls.length);\n\n // Create upload tasks for each part\n const parts: PartInfo[] = [];\n const queue: Array<() => Promise<void>> = [];\n\n const { maxRetries = 3, retryInitialDelay, retryMaxDelay, retryJitter } = options;\n\n for (let i = 0; i < presignedUrls.length; i++) {\n const partNumber = i + 1;\n const start = i * partSize;\n const end = Math.min(start + partSize, totalSize);\n const partData = fileData.slice(start, end);\n const url = presignedUrls[i];\n\n queue.push(async () => {\n const etag = await uploadPart(partData, url, partNumber, maxRetries, {\n initialDelay: retryInitialDelay,\n maxDelay: retryMaxDelay,\n jitter: retryJitter,\n });\n parts.push({ part_number: partNumber, etag });\n });\n }\n\n // Execute uploads with concurrency control\n await executeWithConcurrency(queue, concurrency);\n\n // Sort parts by part number\n parts.sort((a, b) => a.part_number - b.part_number);\n\n return parts;\n}\n\n/**\n * Upload a single part\n */\nasync function uploadPart(\n partData: ArrayBuffer,\n presignedUrl: string,\n partNumber: number,\n maxRetries: number = 3,\n retryOptions: { initialDelay?: number; maxDelay?: number; jitter?: boolean } = {}\n): Promise<string> {\n return retryWithBackoff(\n async () => {\n let response: Response;\n try {\n response = await fetch(presignedUrl, {\n method: 'PUT',\n body: partData,\n });\n } catch (error: any) {\n // Network-level errors (connection refused, timeout, etc.)\n throw new UploadError(\n `Part ${partNumber} upload failed: ${error.message}`,\n undefined,\n undefined,\n error\n );\n }\n\n if (!response.ok) {\n // Extract Retry-After header for 429 responses\n const retryAfter = response.headers.get('retry-after');\n const error = new UploadError(\n `Part ${partNumber} upload failed with status ${response.status}: ${response.statusText}`,\n undefined,\n response.status\n );\n\n // Attach retry-after if present (convert to seconds)\n if (retryAfter && response.status === 429) {\n (error as any).retryAfter = parseInt(retryAfter, 10);\n }\n\n throw error;\n }\n\n // Get ETag from response headers\n const etag = response.headers.get('etag');\n if (!etag) {\n throw new UploadError(\n `Part ${partNumber} upload succeeded but no ETag returned`,\n undefined,\n response.status\n );\n }\n\n // Clean ETag (remove quotes if present)\n return etag.replace(/\"/g, '');\n },\n {\n maxRetries,\n initialDelay: retryOptions.initialDelay,\n maxDelay: retryOptions.maxDelay,\n jitter: retryOptions.jitter,\n }\n );\n}\n\n/**\n * Execute tasks with controlled concurrency\n */\nasync function executeWithConcurrency(\n tasks: Array<() => Promise<void>>,\n concurrency: number\n): Promise<void> {\n const queue = [...tasks];\n const workers: Promise<void>[] = [];\n\n const processNext = async () => {\n while (queue.length > 0) {\n const task = queue.shift()!;\n await task();\n }\n };\n\n // Start concurrent workers\n for (let i = 0; i < Math.min(concurrency, tasks.length); i++) {\n workers.push(processNext());\n }\n\n await Promise.all(workers);\n}\n","/**\n * Upload Client with Collections Integration\n * Provides high-level upload operations with permission checks\n */\n\nimport type {\n UploaderConfig,\n UploadOptions,\n UploadProgress,\n BatchResult,\n CustomPrompts,\n} from './types/config';\nimport type { ProcessingConfig } from './types/processing';\nimport { ArkeUploader } from './uploader';\nimport { CollectionsClient, type CollectionsClientConfig } from '../collections/client';\nimport type { CreateCollectionPayload, Collection, PiPermissions } from '../collections/types';\n\nexport interface UploadClientConfig {\n /**\n * Gateway base URL (e.g., https://api.arke.institute)\n */\n gatewayUrl: string;\n /**\n * Bearer token for authentication\n */\n authToken: string;\n /**\n * Name of person/service uploading files (defaults to user ID from JWT)\n */\n uploader?: string;\n /**\n * Custom fetch implementation (optional, for testing)\n */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Extract user ID from JWT token (without verification)\n */\nfunction getUserIdFromToken(token: string): string | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n\n // Decode base64url payload\n const payload = parts[1]\n .replace(/-/g, '+')\n .replace(/_/g, '/');\n\n // Handle browser vs Node.js\n let decoded: string;\n if (typeof atob === 'function') {\n decoded = atob(payload);\n } else {\n decoded = Buffer.from(payload, 'base64').toString('utf-8');\n }\n\n const data = JSON.parse(decoded);\n return data.sub || null;\n } catch {\n return null;\n }\n}\n\nexport interface CreateCollectionUploadOptions {\n /**\n * Files to upload - directory path (Node.js) or File[]/FileList (browser)\n */\n files: string | File[] | FileList;\n /**\n * Collection metadata\n */\n collectionMetadata: CreateCollectionPayload;\n /**\n * Custom prompts for AI processing\n */\n customPrompts?: CustomPrompts;\n /**\n * Processing options (OCR, IIIF, etc.)\n */\n processing?: ProcessingConfig;\n /**\n * Progress callback\n */\n onProgress?: (progress: UploadProgress) => void;\n /**\n * Dry run mode\n */\n dryRun?: boolean;\n}\n\nexport interface AddToCollectionOptions {\n /**\n * Files to upload - directory path (Node.js) or File[]/FileList (browser)\n */\n files: string | File[] | FileList;\n /**\n * Parent PI to add files under (must be within a collection you can edit)\n */\n parentPi: string;\n /**\n * Custom prompts for AI processing\n */\n customPrompts?: CustomPrompts;\n /**\n * Processing options (OCR, IIIF, etc.)\n */\n processing?: ProcessingConfig;\n /**\n * Progress callback\n */\n onProgress?: (progress: UploadProgress) => void;\n /**\n * Dry run mode\n */\n dryRun?: boolean;\n}\n\nexport interface CreateCollectionUploadResult extends BatchResult {\n /**\n * The created collection\n */\n collection: Collection & { rootPi: string };\n}\n\n/**\n * High-level upload client with collections integration\n *\n * @example\n * ```typescript\n * import { UploadClient } from '@arke-institute/sdk';\n *\n * const client = new UploadClient({\n * gatewayUrl: 'https://api.arke.institute',\n * authToken: 'your-jwt-token',\n * uploader: 'my-app',\n * });\n *\n * // Create a new collection from files\n * const result = await client.createCollection({\n * files: './photos',\n * collectionMetadata: { title: 'My Archive', slug: 'my-archive' },\n * });\n *\n * // Add files to an existing collection\n * await client.addToCollection({\n * files: './more-photos',\n * parentPi: result.collection.rootPi,\n * });\n * ```\n */\nexport class UploadClient {\n private config: UploadClientConfig & { uploader: string };\n private collectionsClient: CollectionsClient;\n\n constructor(config: UploadClientConfig) {\n // Default uploader to user ID from JWT if not provided\n const uploader = config.uploader || getUserIdFromToken(config.authToken) || 'unknown';\n\n this.config = { ...config, uploader };\n this.collectionsClient = new CollectionsClient({\n gatewayUrl: config.gatewayUrl,\n authToken: config.authToken,\n fetchImpl: config.fetchImpl,\n });\n }\n\n /**\n * Update the auth token (e.g., after token refresh)\n */\n setAuthToken(token: string) {\n this.config = { ...this.config, authToken: token };\n this.collectionsClient.setAuthToken(token);\n }\n\n /**\n * Create a new collection and upload files to it\n *\n * Anyone authenticated can create a new collection.\n * The root PI of the uploaded files becomes the collection's root.\n */\n async createCollection(\n options: CreateCollectionUploadOptions\n ): Promise<CreateCollectionUploadResult> {\n const { files, collectionMetadata, customPrompts, processing, onProgress, dryRun } = options;\n\n // Default visibility to 'public' if not specified\n const metadata = {\n ...collectionMetadata,\n visibility: collectionMetadata.visibility || 'public',\n };\n\n // Create uploader for the batch\n const uploader = new ArkeUploader({\n gatewayUrl: this.config.gatewayUrl,\n authToken: this.config.authToken,\n uploader: this.config.uploader,\n customPrompts,\n processing,\n });\n\n // Upload the files first\n const batchResult = await uploader.uploadBatch(files as any, {\n onProgress,\n dryRun,\n });\n\n if (dryRun) {\n return {\n ...batchResult,\n collection: {\n id: 'dry-run',\n title: metadata.title,\n slug: metadata.slug,\n description: metadata.description,\n visibility: metadata.visibility,\n rootPi: 'dry-run',\n },\n };\n }\n\n // Register the root PI as a collection\n // The uploader returns the real rootPi after discovery completes\n const collection = await this.collectionsClient.registerRoot({\n ...metadata,\n rootPi: batchResult.rootPi,\n });\n\n return {\n ...batchResult,\n collection,\n };\n }\n\n /**\n * Add files to an existing collection\n *\n * Requires owner or editor role on the collection containing the parent PI.\n * Use this to add a folder or files to an existing collection hierarchy.\n *\n * Note: Permission checks are enforced server-side by the ingest worker.\n * The server will return 403 if the user lacks edit access to the parent PI.\n */\n async addToCollection(options: AddToCollectionOptions): Promise<BatchResult> {\n const { files, parentPi, customPrompts, processing, onProgress, dryRun } = options;\n\n // Create uploader with the parent PI\n const uploader = new ArkeUploader({\n gatewayUrl: this.config.gatewayUrl,\n authToken: this.config.authToken,\n uploader: this.config.uploader,\n parentPi,\n customPrompts,\n processing,\n });\n\n // Upload the files\n return uploader.uploadBatch(files as any, {\n onProgress,\n dryRun,\n });\n }\n\n /**\n * Check if you can edit a specific PI (i.e., add files to its collection)\n */\n async canEdit(pi: string): Promise<PiPermissions> {\n return this.collectionsClient.getPiPermissions(pi);\n }\n\n /**\n * Get access to the underlying collections client for other operations\n */\n get collections(): CollectionsClient {\n return this.collectionsClient;\n }\n}\n","/**\n * @arke-institute/sdk - TypeScript SDK for building applications on the Arke platform\n *\n * @example\n * ```typescript\n * import {\n * CollectionsClient,\n * UploadClient,\n * QueryClient,\n * EditClient,\n * ContentClient,\n * GraphClient\n * } from '@arke-institute/sdk';\n *\n * // Collections management\n * const collections = new CollectionsClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * authToken: 'your-jwt-token',\n * });\n *\n * // Upload with collections integration\n * const upload = new UploadClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * authToken: 'your-jwt-token',\n * uploader: 'my-app',\n * });\n *\n * // Query the knowledge graph (no auth required)\n * const query = new QueryClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Content access (no auth required)\n * const content = new ContentClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Graph relationships (no auth required)\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get an entity and its content\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * const imageBlob = await content.download(entity.components.source);\n *\n * // Get entities with relationships from the knowledge graph\n * const entities = await graph.getEntitiesWithRelationships(entity.pi);\n *\n * // Execute a path query\n * const results = await query.path('\"alice austen\" -[*]{,4}-> type:person');\n * ```\n */\n\n// Collections\nexport {\n CollectionsClient,\n type CollectionsClientConfig,\n} from './collections/client';\nexport { CollectionsError } from './collections/errors';\nexport type {\n Collection,\n CollectionDetails,\n CollectionRole,\n CollectionVisibility,\n CreateCollectionPayload,\n UpdateCollectionPayload,\n RegisterRootPayload,\n ChangeRootPayload,\n ChangeRootResponse,\n Member,\n MemberUser,\n MembersResponse,\n Invitation,\n InvitationUser,\n InvitationsResponse,\n MyAccessResponse,\n MyCollectionsResponse,\n PaginatedCollections,\n PiPermissions,\n RootResponse,\n SuccessResponse,\n} from './collections/types';\n\n// Upload\nexport {\n UploadClient,\n type UploadClientConfig,\n type CreateCollectionUploadOptions,\n type AddToCollectionOptions,\n type CreateCollectionUploadResult,\n} from './upload/client';\nexport { ArkeUploader } from './upload/uploader';\nexport type {\n UploaderConfig,\n UploadOptions,\n UploadProgress,\n BatchResult,\n CustomPrompts,\n ProcessingConfig,\n FileInfo,\n} from './upload/types/index';\nexport {\n ValidationError,\n ScanError,\n WorkerAPIError,\n NetworkError,\n UploadError,\n} from './upload/utils/errors';\n\n// Query\nexport { QueryClient, type QueryClientConfig } from './query/client';\nexport { QueryError } from './query/errors';\nexport type {\n // Request types\n LineageFilter,\n PathQueryOptions,\n NaturalQueryOptions,\n // Response types\n EnrichedContent,\n Entity,\n PathStep,\n QueryResultItem,\n LineageMetadata,\n QueryMetadata,\n QueryResult,\n TranslationInfo,\n NaturalQueryResult,\n TranslateResult,\n // Parse types\n ASTNodeType,\n EntryAST,\n FilterAST,\n HopAST,\n PathAST,\n ParseResult,\n ParseError,\n // Syntax documentation types\n EntryPointDoc,\n EdgeTypeDoc,\n VariableDepthDoc,\n FilterTypeDoc,\n ParameterDoc,\n ExampleDoc,\n SyntaxDocumentation,\n} from './query/types';\n\n// Edit\nexport { EditClient, type EditClientConfig } from './edit/client';\nexport { EditSession } from './edit/session';\nexport { EditError, PermissionError } from './edit/errors';\nexport type {\n EditMode,\n EditSessionConfig,\n EditScope,\n RegeneratableComponent,\n EditResult,\n EditStatus,\n EditPhase,\n ReprocessResult,\n ReprocessStatus,\n} from './edit/types';\n\n// Content\nexport { ContentClient, type ContentClientConfig } from './content/client';\nexport {\n ContentError,\n EntityNotFoundError,\n ContentNotFoundError,\n ComponentNotFoundError,\n VersionNotFoundError,\n NetworkError as ContentNetworkError,\n} from './content/errors';\nexport type {\n Entity as ContentEntity,\n EntitySummary,\n EntityVersion,\n ListOptions,\n ListResponse,\n VersionsOptions,\n VersionsResponse,\n ResolveResponse,\n} from './content/types';\n\n// Graph\nexport { GraphClient, type GraphClientConfig } from './graph/client';\nexport {\n GraphError,\n GraphEntityNotFoundError,\n NoPathFoundError,\n NetworkError as GraphNetworkError,\n} from './graph/errors';\nexport type {\n GraphEntity,\n Relationship,\n EntityWithRelationships,\n PathEdge,\n Path,\n PathOptions,\n ReachableOptions,\n ListFromPiOptions,\n EntityQueryResponse,\n EntitiesWithRelationshipsResponse,\n PathsResponse,\n LineagePiEntry,\n LineageResultSet,\n LineageResponse,\n} from './graph/types';\n","/**\n * Error class for query operations\n */\nexport class QueryError extends Error {\n constructor(\n message: string,\n public code: string = 'UNKNOWN_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'QueryError';\n }\n}\n","import { QueryError } from './errors';\nimport type {\n PathQueryOptions,\n NaturalQueryOptions,\n QueryResult,\n NaturalQueryResult,\n TranslateResult,\n ParseResult,\n ParseError,\n SyntaxDocumentation,\n SemanticSearchOptions,\n SemanticSearchResponse,\n CollectionSearchOptions,\n CollectionSearchResponse,\n} from './types';\n\n/**\n * Configuration for QueryClient\n */\nexport interface QueryClientConfig {\n /**\n * Gateway base URL (e.g., https://gateway.arke.institute).\n * The client will call /query/* endpoints.\n */\n gatewayUrl: string;\n /**\n * Optional custom fetch implementation (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\n/**\n * Client for querying the Arke knowledge graph.\n *\n * All query endpoints are public and do not require authentication.\n *\n * @example\n * ```typescript\n * const query = new QueryClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Direct path query\n * const results = await query.path('\"alice austen\" -[*]{,4}-> type:person');\n *\n * // Natural language query\n * const nlResults = await query.natural('Find photographers connected to Alice Austen');\n *\n * // Get syntax documentation\n * const syntax = await query.syntax();\n * ```\n */\nexport class QueryClient {\n private baseUrl: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: QueryClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n query?: Record<string, string | undefined>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n const response = await this.fetchImpl(url, { ...options, headers });\n\n if (response.ok) {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : (body as JsonBody)?.message && typeof (body as JsonBody).message === 'string'\n ? ((body as JsonBody).message as string)\n : `Request failed with status ${response.status}`;\n\n throw new QueryError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Query methods\n // ---------------------------------------------------------------------------\n\n /**\n * Execute a path query against the knowledge graph.\n *\n * @param pathQuery - The path query string (e.g., '\"alice austen\" -[*]{,4}-> type:person')\n * @param options - Query options (k, k_explore, lineage, enrich, etc.)\n * @returns Query results with entities, paths, and metadata\n *\n * @example\n * ```typescript\n * // Simple semantic search\n * const results = await query.path('\"Washington\" type:person');\n *\n * // Multi-hop traversal\n * const results = await query.path('\"alice austen\" -[*]{,4}-> type:person ~ \"photographer\"');\n *\n * // With lineage filtering (collection scope)\n * const results = await query.path('\"letters\" type:document', {\n * lineage: { sourcePi: 'arke:my_collection', direction: 'descendants' },\n * k: 10,\n * });\n * ```\n */\n async path(pathQuery: string, options: PathQueryOptions = {}): Promise<QueryResult> {\n return this.request<QueryResult>('/query/path', {\n method: 'POST',\n body: JSON.stringify({\n path: pathQuery,\n ...options,\n }),\n });\n }\n\n /**\n * Execute a natural language query.\n *\n * The query is translated to a path query using an LLM, then executed.\n *\n * @param question - Natural language question\n * @param options - Query options including custom_instructions for the LLM\n * @returns Query results with translation info\n *\n * @example\n * ```typescript\n * const results = await query.natural('Find photographers connected to Alice Austen');\n * console.log('Generated query:', results.translation.path);\n * console.log('Explanation:', results.translation.explanation);\n * ```\n */\n async natural(question: string, options: NaturalQueryOptions = {}): Promise<NaturalQueryResult> {\n const { custom_instructions, ...queryOptions } = options;\n return this.request<NaturalQueryResult>('/query/natural', {\n method: 'POST',\n body: JSON.stringify({\n query: question,\n custom_instructions,\n ...queryOptions,\n }),\n });\n }\n\n /**\n * Translate a natural language question to a path query without executing it.\n *\n * Useful for understanding how questions are translated or for manual execution later.\n *\n * @param question - Natural language question\n * @param customInstructions - Optional additional instructions for the LLM\n * @returns Translation result with path query and explanation\n *\n * @example\n * ```typescript\n * const result = await query.translate('Who wrote letters from Philadelphia?');\n * console.log('Path query:', result.path);\n * // '\"letters\" <-[authored, wrote]- type:person -[located]-> \"Philadelphia\"'\n * ```\n */\n async translate(question: string, customInstructions?: string): Promise<TranslateResult> {\n return this.request<TranslateResult>('/query/translate', {\n method: 'POST',\n body: JSON.stringify({\n query: question,\n custom_instructions: customInstructions,\n }),\n });\n }\n\n /**\n * Parse and validate a path query without executing it.\n *\n * Returns the AST (Abstract Syntax Tree) if valid, or throws an error.\n *\n * @param pathQuery - The path query to parse\n * @returns Parsed AST\n * @throws QueryError if the query has syntax errors\n *\n * @example\n * ```typescript\n * try {\n * const result = await query.parse('\"test\" -[*]-> type:person');\n * console.log('Valid query, AST:', result.ast);\n * } catch (err) {\n * console.error('Invalid query:', err.message);\n * }\n * ```\n */\n async parse(pathQuery: string): Promise<ParseResult> {\n const url = this.buildUrl('/query/parse', { path: pathQuery });\n const response = await this.fetchImpl(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n });\n\n const body = await response.json() as ParseResult | ParseError;\n\n // Check if it's an error response (parse errors return 400)\n if ('error' in body && body.error === 'Parse error') {\n throw new QueryError(\n (body as ParseError).message,\n 'PARSE_ERROR',\n { position: (body as ParseError).position }\n );\n }\n\n if (!response.ok) {\n throw new QueryError(\n (body as any).error || `Request failed with status ${response.status}`,\n 'HTTP_ERROR',\n { status: response.status, body }\n );\n }\n\n return body as ParseResult;\n }\n\n /**\n * Get the path query syntax documentation.\n *\n * Returns comprehensive documentation including entry points, edge traversal,\n * filters, examples, and constraints.\n *\n * @returns Syntax documentation\n *\n * @example\n * ```typescript\n * const syntax = await query.syntax();\n *\n * // List all entry point types\n * syntax.entryPoints.types.forEach(ep => {\n * console.log(`${ep.syntax} - ${ep.description}`);\n * });\n *\n * // Show examples\n * syntax.examples.forEach(ex => {\n * console.log(`${ex.description}: ${ex.query}`);\n * });\n * ```\n */\n async syntax(): Promise<SyntaxDocumentation> {\n return this.request<SyntaxDocumentation>('/query/syntax', {\n method: 'GET',\n });\n }\n\n /**\n * Check the health of the query service.\n *\n * @returns Health status\n */\n async health(): Promise<{ status: string; service: string; version: string }> {\n return this.request('/query/health', { method: 'GET' });\n }\n\n /**\n * Direct semantic search against the vector index.\n *\n * This bypasses the path query syntax and directly queries Pinecone for\n * semantically similar entities. Useful for:\n * - Simple semantic searches without graph traversal\n * - Scoped searches filtered by source_pi (collection scope)\n * - Type-filtered semantic searches\n *\n * For graph traversal and path-based queries, use `path()` instead.\n *\n * @param text - Search query text\n * @param options - Search options (namespace, filters, top_k)\n * @returns Matching entities with similarity scores\n *\n * @example\n * ```typescript\n * // Simple semantic search\n * const results = await query.semanticSearch('photographers from New York');\n *\n * // Scoped to a specific PI (collection)\n * const scoped = await query.semanticSearch('portraits', {\n * filter: { source_pi: '01K75HQQXNTDG7BBP7PS9AWYAN' },\n * top_k: 20,\n * });\n *\n * // Filter by type\n * const people = await query.semanticSearch('artists', {\n * filter: { type: 'person' },\n * });\n *\n * // Search across merged entities from multiple source PIs\n * const merged = await query.semanticSearch('historical documents', {\n * filter: { merged_entities_source_pis: ['pi-1', 'pi-2'] },\n * });\n * ```\n */\n async semanticSearch(\n text: string,\n options: SemanticSearchOptions = {}\n ): Promise<SemanticSearchResponse> {\n // Build Pinecone-compatible filter from our typed filter\n let pineconeFilter: Record<string, unknown> | undefined;\n\n if (options.filter) {\n pineconeFilter = {};\n\n if (options.filter.type) {\n const types = Array.isArray(options.filter.type)\n ? options.filter.type\n : [options.filter.type];\n pineconeFilter.type = types.length === 1\n ? { $eq: types[0] }\n : { $in: types };\n }\n\n if (options.filter.source_pi) {\n const pis = Array.isArray(options.filter.source_pi)\n ? options.filter.source_pi\n : [options.filter.source_pi];\n pineconeFilter.source_pi = pis.length === 1\n ? { $eq: pis[0] }\n : { $in: pis };\n }\n\n if (options.filter.merged_entities_source_pis) {\n const pis = Array.isArray(options.filter.merged_entities_source_pis)\n ? options.filter.merged_entities_source_pis\n : [options.filter.merged_entities_source_pis];\n // Use $in for array field matching (any of the provided PIs)\n pineconeFilter.merged_entities_source_pis = { $in: pis };\n }\n\n // If no filters were actually set, clear the object\n if (Object.keys(pineconeFilter).length === 0) {\n pineconeFilter = undefined;\n }\n }\n\n return this.request<SemanticSearchResponse>('/query/search/semantic', {\n method: 'POST',\n body: JSON.stringify({\n text,\n namespace: options.namespace,\n filter: pineconeFilter,\n top_k: options.top_k,\n }),\n });\n }\n\n /**\n * Search for collections by semantic similarity.\n *\n * Searches the dedicated collections index for fast semantic matching.\n *\n * @param query - Search query text\n * @param options - Search options (limit, visibility filter)\n * @returns Matching collections with similarity scores\n *\n * @example\n * ```typescript\n * // Search for photography-related collections\n * const results = await query.searchCollections('photography');\n * console.log(results.collections[0].title);\n *\n * // Search only public collections\n * const publicResults = await query.searchCollections('history', {\n * visibility: 'public',\n * limit: 20,\n * });\n * ```\n */\n async searchCollections(\n query: string,\n options: CollectionSearchOptions = {}\n ): Promise<CollectionSearchResponse> {\n return this.request<CollectionSearchResponse>('/query/search/collections', {\n method: 'GET',\n query: {\n q: query,\n limit: options.limit?.toString(),\n visibility: options.visibility,\n },\n });\n }\n}\n","/**\n * Arke SDK - Edit Package Type Definitions\n *\n * Types for write operations against the IPFS Wrapper API.\n * Based on the arke/eidos@v1 schema.\n */\n\n// ============================================================================\n// Network Types\n// ============================================================================\n\n/** Network type for API requests */\nexport type Network = 'main' | 'test';\n\n// ============================================================================\n// Entity Types (arke/eidos@v1 aligned)\n// ============================================================================\n\n/**\n * Full entity manifest from IPFS Wrapper\n */\nexport interface Entity {\n /** Entity identifier (ULID or test ID with II prefix) */\n id: string;\n /** Entity type (e.g., \"PI\", \"person\", \"place\", \"concept\", \"document\") */\n type: string;\n /** Creation timestamp (immutable, set at v1) */\n created_at: string;\n /** Display name */\n label?: string;\n /** Human-readable description */\n description?: string;\n /** Version number */\n ver: number;\n /** Timestamp when this version was created */\n ts: string;\n /** CID of this manifest */\n manifest_cid: string;\n /** CID of the previous version (null for version 1) */\n prev_cid: string | null;\n /** Map of component names to their CIDs */\n components: Record<string, string>;\n /** IDs of child entities */\n children_pi?: string[];\n /** ID of parent entity */\n parent_pi?: string;\n /** Provenance: which PI extracted this entity */\n source_pi?: string;\n /** IDs of entities that have been merged into this one */\n merged_entities?: string[];\n /** Change note for this version */\n note?: string;\n}\n\n/**\n * Summary entity info returned when listing entities\n */\nexport interface EntitySummary {\n /** Entity identifier */\n id: string;\n /** Tip CID (latest manifest) */\n tip: string;\n /** Entity type (if include_metadata=true) */\n type?: string;\n /** Display name (if include_metadata=true) */\n label?: string;\n /** Version number (if include_metadata=true) */\n ver?: number;\n /** Timestamp (if include_metadata=true) */\n ts?: string;\n /** Change note (if include_metadata=true) */\n note?: string;\n /** Number of components (if include_metadata=true) */\n component_count?: number;\n /** Number of children (if include_metadata=true) */\n children_count?: number;\n}\n\n/**\n * Version entry in version history\n */\nexport interface VersionHistoryItem {\n /** Version number */\n ver: number;\n /** CID of this version's manifest */\n cid: string;\n /** Timestamp when this version was created */\n ts: string;\n /** Change note for this version */\n note?: string;\n}\n\n// ============================================================================\n// Relationship Types (arke/relationships@v1)\n// ============================================================================\n\n/**\n * A single relationship edge in the semantic graph\n */\nexport interface Relationship {\n /** Relationship predicate (e.g., \"authored_by\", \"mentions\", \"located_in\") */\n predicate: string;\n /** Type of target */\n target_type: 'pi' | 'entity';\n /** Target entity identifier */\n target_id: string;\n /** Display label for the target (e.g., \"Alice Austen\") */\n target_label: string;\n /** Target entity type (e.g., \"person\", \"place\") - only if target is entity */\n target_entity_type?: string;\n /** Optional metadata on the relationship edge */\n properties?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Create Entity\n// ============================================================================\n\n/**\n * Request to create a new entity\n */\nexport interface CreateEntityRequest {\n /** Entity ID (optional - server generates ULID if omitted) */\n id?: string;\n /** Entity type (required, e.g., \"PI\", \"person\", \"place\") */\n type: string;\n /** Components map: label → CID */\n components: Record<string, string>;\n /** Display name */\n label?: string;\n /** Human-readable description */\n description?: string;\n /** Parent entity ID (auto-updates parent's children_pi) */\n parent_pi?: string;\n /** Child entity IDs */\n children_pi?: string[];\n /** Provenance: which PI extracted this entity */\n source_pi?: string;\n /** Initial properties (will be stored as component) */\n properties?: Record<string, unknown>;\n /** Initial relationships (will be stored as component) */\n relationships?: Relationship[];\n /** Change note */\n note?: string;\n}\n\n/**\n * Response from creating an entity\n */\nexport interface CreateEntityResponse {\n /** Entity identifier */\n id: string;\n /** Entity type */\n type: string;\n /** Version number (always 1 for new entities) */\n ver: number;\n /** CID of the manifest */\n manifest_cid: string;\n /** Tip CID (same as manifest_cid for new entities) */\n tip: string;\n}\n\n// ============================================================================\n// Update Entity (Append Version)\n// ============================================================================\n\n/**\n * Request to append a new version to an entity\n */\nexport interface UpdateEntityRequest {\n /** Current tip CID (CAS guard - required) */\n expect_tip: string;\n /** Change entity type */\n type?: string;\n /** Update display name */\n label?: string;\n /** Update description */\n description?: string;\n /** Components to add/update: label → CID */\n components?: Record<string, string>;\n /** Component labels to remove */\n components_remove?: string[];\n /** Child IDs to add (max 100, auto-updates children's parent_pi) */\n children_pi_add?: string[];\n /** Child IDs to remove (max 100, auto-updates children's parent_pi) */\n children_pi_remove?: string[];\n /** Replace entire properties object */\n properties?: Record<string, unknown>;\n /** Replace entire relationships array */\n relationships?: Relationship[];\n /** Change note */\n note?: string;\n}\n\n/**\n * Response from updating an entity\n */\nexport interface UpdateEntityResponse {\n /** Entity identifier */\n id: string;\n /** Entity type */\n type: string;\n /** New version number */\n ver: number;\n /** CID of the new manifest */\n manifest_cid: string;\n /** New tip CID */\n tip: string;\n}\n\n// ============================================================================\n// List Entities\n// ============================================================================\n\n/**\n * Options for listing entities\n */\nexport interface ListEntitiesOptions {\n /** Maximum entities to return (1-1000, default: 100) */\n limit?: number;\n /** Pagination cursor from next_cursor */\n cursor?: string;\n /** Include full metadata for each entity */\n include_metadata?: boolean;\n}\n\n/**\n * Response from listing entities\n */\nexport interface ListEntitiesResponse {\n /** List of entity summaries */\n entities: EntitySummary[];\n /** Limit used */\n limit: number;\n /** Cursor for next page (null if no more) */\n next_cursor: string | null;\n}\n\n// ============================================================================\n// Version Operations\n// ============================================================================\n\n/**\n * Options for listing versions\n */\nexport interface ListVersionsOptions {\n /** Maximum versions to return (1-1000, default: 50) */\n limit?: number;\n /** Pagination cursor (manifest CID) */\n cursor?: string;\n}\n\n/**\n * Response from listing versions\n */\nexport interface ListVersionsResponse {\n /** List of versions (newest first) */\n items: VersionHistoryItem[];\n /** Cursor for next page (null if reached genesis) */\n next_cursor: string | null;\n}\n\n/**\n * Response from resolving an ID to tip\n */\nexport interface ResolveResponse {\n /** Entity identifier */\n id: string;\n /** Tip CID (latest manifest) */\n tip: string;\n}\n\n// ============================================================================\n// Hierarchy Operations\n// ============================================================================\n\n/**\n * Request to update parent-child hierarchy\n */\nexport interface UpdateHierarchyRequest {\n /** Parent entity ID */\n parent_id: string;\n /** Current parent tip CID (CAS guard) */\n expect_tip: string;\n /** Child IDs to add (max 100) */\n add_children?: string[];\n /** Child IDs to remove (max 100) */\n remove_children?: string[];\n /** Change note */\n note?: string;\n}\n\n/**\n * Response from updating hierarchy\n */\nexport interface UpdateHierarchyResponse {\n /** Parent entity ID */\n parent_pi: string;\n /** New parent version */\n parent_ver: number;\n /** New parent tip CID */\n parent_tip: string;\n /** Number of children successfully updated */\n children_updated: number;\n /** Number of children that failed to update */\n children_failed: number;\n}\n\n// ============================================================================\n// Merge Operations\n// ============================================================================\n\n/**\n * Request to merge source entity into target\n */\nexport interface MergeEntityRequest {\n /** Target entity ID (entity to merge into) */\n target_id: string;\n /** Current target tip CID (CAS guard) */\n expect_target_tip: string;\n /** Reason for merge */\n note?: string;\n /** Skip index-sync callback (internal use) */\n skip_sync?: boolean;\n}\n\n/**\n * Response from merging entities\n */\nexport interface MergeEntityResponse {\n /** Source entity ID (now a tombstone) */\n source_id: string;\n /** Target entity ID */\n target_id: string;\n /** New target version */\n target_ver: number;\n /** New target tip CID */\n target_tip: string;\n /** CID of the tombstone manifest */\n tombstone_cid: string;\n}\n\n/**\n * Request to unmerge (restore) a previously merged entity\n */\nexport interface UnmergeEntityRequest {\n /** Target entity ID (entity it was merged into) */\n target_id: string;\n /** Current target tip CID (CAS guard) */\n expect_target_tip: string;\n /** Reason for unmerge */\n note?: string;\n /** Skip index-sync callback (internal use) */\n skip_sync?: boolean;\n}\n\n/**\n * Response from unmerging entity\n */\nexport interface UnmergeEntityResponse {\n /** Restored source entity ID */\n source_id: string;\n /** New source version */\n source_ver: number;\n /** New source tip CID */\n source_tip: string;\n /** Target entity ID */\n target_id: string;\n /** New target version */\n target_ver: number;\n /** New target tip CID */\n target_tip: string;\n}\n\n// ============================================================================\n// Delete Operations\n// ============================================================================\n\n/**\n * Request to soft delete an entity\n */\nexport interface DeleteEntityRequest {\n /** Current tip CID (CAS guard) */\n expect_tip: string;\n /** Reason for deletion */\n note?: string;\n}\n\n/**\n * Response from deleting an entity\n */\nexport interface DeleteEntityResponse {\n /** Entity ID */\n id: string;\n /** Version number of the tombstone */\n deleted_ver: number;\n /** Timestamp of deletion */\n deleted_at: string;\n /** CID of the tombstone manifest */\n deleted_manifest_cid: string;\n /** Previous version number (before deletion) */\n previous_ver: number;\n /** CID of the previous manifest */\n prev_cid: string;\n}\n\n/**\n * Request to restore a deleted entity\n */\nexport interface UndeleteEntityRequest {\n /** Current tip CID (tombstone CID, CAS guard) */\n expect_tip: string;\n /** Reason for restoration */\n note?: string;\n}\n\n/**\n * Response from restoring a deleted entity\n */\nexport interface UndeleteEntityResponse {\n /** Entity ID */\n id: string;\n /** New version number after restoration */\n restored_ver: number;\n /** Version number that was restored from */\n restored_from_ver: number;\n /** CID of the new manifest */\n new_manifest_cid: string;\n}\n\n// ============================================================================\n// Upload Operations\n// ============================================================================\n\n/**\n * Response from uploading files\n */\nexport interface UploadResponse {\n /** Original filename */\n name: string;\n /** CID of the uploaded content */\n cid: string;\n /** Size in bytes */\n size: number;\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport type EditMode = 'ai-prompt' | 'manual-with-review' | 'manual-only';\n\nexport interface EditSessionConfig {\n mode: EditMode;\n aiReviewEnabled?: boolean; // Default: true for manual modes\n}\n\n// ============================================================================\n// Edit Types (for UI/workflow)\n// ============================================================================\n\nexport type RegeneratableComponent = 'pinax' | 'description' | 'cheimarros';\n\nexport interface EditScope {\n components: RegeneratableComponent[]; // Which components to regenerate\n cascade: boolean; // Propagate changes up the tree?\n stopAtPi?: string; // Stop cascade at this ancestor PI\n}\n\nexport interface Correction {\n original: string;\n corrected: string;\n sourceFile?: string;\n context?: string; // Surrounding text for context\n}\n\n// ============================================================================\n// Diff Types\n// ============================================================================\n\nexport type DiffType = 'addition' | 'deletion' | 'change' | 'unchanged';\n\nexport interface TextDiff {\n type: DiffType;\n original?: string;\n modified?: string;\n lineNumber?: number;\n context?: string;\n}\n\nexport interface ComponentDiff {\n componentName: string;\n diffs: TextDiff[];\n summary: string; // Human-readable summary\n hasChanges: boolean;\n}\n\n// ============================================================================\n// Prompt Types\n// ============================================================================\n\nexport type PromptTarget = RegeneratableComponent | 'general' | 'reorganization';\n\nexport interface EntityContext {\n pi: string;\n ver: number;\n parentPi?: string;\n childrenCount: number;\n currentContent: Record<string, string>;\n}\n\nexport interface CascadeContext {\n path: string[]; // PIs from current to root\n depth: number;\n stopAtPi?: string;\n}\n\n// ============================================================================\n// Reprocess Types\n// ============================================================================\n\nexport interface CustomPrompts {\n general?: string;\n pinax?: string;\n description?: string;\n cheimarros?: string;\n reorganization?: string;\n}\n\nexport interface ReprocessRequest {\n pi: string;\n phases: RegeneratableComponent[];\n cascade: boolean;\n options?: {\n stop_at_pi?: string;\n custom_prompts?: CustomPrompts;\n custom_note?: string; // Custom version note (overrides default phase notes)\n };\n}\n\nexport interface ReprocessResult {\n batch_id: string;\n entities_queued: number;\n entity_pis: string[];\n status_url: string;\n}\n\nexport type ReprocessPhase =\n | 'QUEUED'\n | 'DISCOVERY'\n | 'OCR_IN_PROGRESS'\n | 'REORGANIZATION'\n | 'PINAX_EXTRACTION'\n | 'CHEIMARROS_EXTRACTION'\n | 'DESCRIPTION'\n | 'DONE'\n | 'ERROR';\n\nexport interface ReprocessProgress {\n directories_total: number;\n directories_pinax_complete: number;\n directories_cheimarros_complete: number;\n directories_description_complete: number;\n}\n\nexport interface ReprocessStatus {\n batch_id: string;\n status: ReprocessPhase;\n progress: ReprocessProgress;\n root_pi?: string;\n error?: string;\n started_at?: string;\n completed_at?: string;\n}\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\nexport interface SaveResult {\n pi: string;\n newVersion: number;\n newTip: string;\n}\n\nexport interface EditResult {\n // Phase 1: Save results (if manual edits were made)\n saved?: SaveResult;\n\n // Phase 2: Reprocess results (if regeneration requested)\n reprocess?: ReprocessResult;\n}\n\nexport type EditPhase = 'idle' | 'saving' | 'reprocessing' | 'complete' | 'error';\n\nexport interface EditStatus {\n phase: EditPhase;\n saveComplete: boolean;\n reprocessStatus?: ReprocessStatus;\n error?: string;\n}\n\nexport interface PollOptions {\n intervalMs?: number; // Default: 2000\n timeoutMs?: number; // Default: 300000 (5 min)\n onProgress?: (status: EditStatus) => void;\n}\n\n// ============================================================================\n// Change Summary\n// ============================================================================\n\nexport interface ChangeSummary {\n mode: EditMode;\n hasManualEdits: boolean;\n editedComponents: string[];\n corrections: Correction[];\n prompts: Record<string, string>;\n scope: EditScope;\n willRegenerate: RegeneratableComponent[];\n willCascade: boolean;\n willSave: boolean;\n willReprocess: boolean;\n}\n\n// ============================================================================\n// Retry Configuration\n// ============================================================================\n\n/**\n * Configuration for retry behavior on transient errors\n */\nexport interface RetryConfig {\n /** Maximum retry attempts (default: 10) */\n maxRetries: number;\n /** Base delay in ms (default: 100) */\n baseDelay: number;\n /** Maximum delay in ms (default: 5000) */\n maxDelay: number;\n /** Jitter factor 0-1 (default: 0.3) */\n jitterFactor: number;\n}\n\n/**\n * Default retry configuration based on API spec recommendations\n */\nexport const DEFAULT_RETRY_CONFIG: RetryConfig = {\n maxRetries: 10,\n baseDelay: 100,\n maxDelay: 5000,\n jitterFactor: 0.3,\n};\n","/**\n * Error classes for edit operations\n */\n\n/**\n * Base error class for edit operations\n */\nexport class EditError extends Error {\n constructor(\n message: string,\n public code: string = 'UNKNOWN_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'EditError';\n }\n}\n\n/**\n * Thrown when an entity is not found\n */\nexport class EntityNotFoundError extends EditError {\n constructor(id: string) {\n super(`Entity not found: ${id}`, 'ENTITY_NOT_FOUND', { id });\n this.name = 'EntityNotFoundError';\n }\n}\n\n/**\n * Thrown when a CAS (Compare-And-Swap) conflict occurs\n * This means the entity was modified since it was last read\n */\nexport class CASConflictError extends EditError {\n constructor(id: string, expectedTip: string, actualTip: string) {\n super(\n `CAS conflict: entity ${id} was modified (expected ${expectedTip}, got ${actualTip})`,\n 'CAS_CONFLICT',\n { id, expectedTip, actualTip }\n );\n this.name = 'CASConflictError';\n }\n}\n\n/**\n * Thrown when an entity ID already exists (on create)\n */\nexport class EntityExistsError extends EditError {\n constructor(id: string) {\n super(`Entity already exists: ${id}`, 'ENTITY_EXISTS', { id });\n this.name = 'EntityExistsError';\n }\n}\n\n/**\n * Thrown when a merge operation fails\n */\nexport class MergeError extends EditError {\n constructor(message: string, sourceId?: string, targetId?: string) {\n super(message, 'MERGE_ERROR', { sourceId, targetId });\n this.name = 'MergeError';\n }\n}\n\n/**\n * Thrown when an unmerge operation fails\n */\nexport class UnmergeError extends EditError {\n constructor(message: string, sourceId?: string, targetId?: string) {\n super(message, 'UNMERGE_ERROR', { sourceId, targetId });\n this.name = 'UnmergeError';\n }\n}\n\n/**\n * Thrown when a delete operation fails\n */\nexport class DeleteError extends EditError {\n constructor(message: string, id?: string) {\n super(message, 'DELETE_ERROR', { id });\n this.name = 'DeleteError';\n }\n}\n\n/**\n * Thrown when an undelete operation fails\n */\nexport class UndeleteError extends EditError {\n constructor(message: string, id?: string) {\n super(message, 'UNDELETE_ERROR', { id });\n this.name = 'UndeleteError';\n }\n}\n\n/**\n * Thrown when reprocessing fails\n */\nexport class ReprocessError extends EditError {\n constructor(message: string, batchId?: string) {\n super(message, 'REPROCESS_ERROR', { batchId });\n this.name = 'ReprocessError';\n }\n}\n\n/**\n * Thrown when request validation fails\n */\nexport class ValidationError extends EditError {\n constructor(message: string, field?: string) {\n super(message, 'VALIDATION_ERROR', { field });\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Thrown when the user doesn't have permission\n */\nexport class PermissionError extends EditError {\n constructor(message: string, id?: string) {\n super(message, 'PERMISSION_DENIED', { id });\n this.name = 'PermissionError';\n }\n}\n\n/**\n * Thrown when a network error occurs\n */\nexport class NetworkError extends EditError {\n constructor(message: string, statusCode?: number) {\n super(message, 'NETWORK_ERROR', { statusCode });\n this.name = 'NetworkError';\n }\n}\n\n/**\n * Thrown when content is not found by CID\n */\nexport class ContentNotFoundError extends EditError {\n constructor(cid: string) {\n super(`Content not found: ${cid}`, 'CONTENT_NOT_FOUND', { cid });\n this.name = 'ContentNotFoundError';\n }\n}\n\n/**\n * Thrown when the IPFS backend has an error\n */\nexport class IPFSError extends EditError {\n constructor(message: string) {\n super(message, 'IPFS_ERROR');\n this.name = 'IPFSError';\n }\n}\n\n/**\n * Thrown when the backend API has an error\n */\nexport class BackendError extends EditError {\n constructor(message: string) {\n super(message, 'BACKEND_ERROR');\n this.name = 'BackendError';\n }\n}\n","/**\n * EditClient - Complete API client for Arke edit operations\n *\n * Provides full access to IPFS Wrapper write operations:\n * - Entity CRUD (create, read, update, delete)\n * - Version management\n * - Hierarchy operations\n * - Merge/unmerge operations\n * - Content upload\n * - Reprocessing\n *\n * Routes through the gateway:\n * - /api/* -> IPFS Wrapper (entities, content, uploads)\n * - /reprocess/* -> Reprocess API\n */\n\nimport type {\n Network,\n Entity,\n CreateEntityRequest,\n CreateEntityResponse,\n UpdateEntityRequest,\n UpdateEntityResponse,\n ListEntitiesOptions,\n ListEntitiesResponse,\n ListVersionsOptions,\n ListVersionsResponse,\n ResolveResponse,\n UpdateHierarchyRequest,\n UpdateHierarchyResponse,\n MergeEntityRequest,\n MergeEntityResponse,\n UnmergeEntityRequest,\n UnmergeEntityResponse,\n DeleteEntityRequest,\n DeleteEntityResponse,\n UndeleteEntityRequest,\n UndeleteEntityResponse,\n UploadResponse,\n ReprocessRequest,\n ReprocessResult,\n ReprocessStatus,\n RetryConfig,\n} from './types.js';\nimport { DEFAULT_RETRY_CONFIG } from './types.js';\nimport {\n EditError,\n EntityNotFoundError,\n EntityExistsError,\n CASConflictError,\n MergeError,\n UnmergeError,\n DeleteError,\n UndeleteError,\n ReprocessError,\n PermissionError,\n ValidationError,\n NetworkError,\n ContentNotFoundError,\n IPFSError,\n BackendError,\n} from './errors.js';\n\n/** Configuration for EditClient */\nexport interface EditClientConfig {\n /** Gateway URL (e.g., https://gateway.arke.io) or direct API URL */\n gatewayUrl: string;\n /** JWT auth token */\n authToken?: string;\n /** Network to use (default: 'main') */\n network?: Network;\n /** User ID for permission checks */\n userId?: string;\n /** Retry configuration */\n retryConfig?: Partial<RetryConfig>;\n /** Optional transform for status URLs (e.g., for CORS proxy) */\n statusUrlTransform?: (url: string) => string;\n /**\n * API prefix for IPFS wrapper routes (default: '/api').\n * Set to '' (empty string) when using direct API URL like https://api.arke.institute\n */\n apiPrefix?: string;\n}\n\n/** Retry status codes */\nconst RETRYABLE_STATUS_CODES = [409, 503];\n\n/** Retry error messages */\nconst RETRYABLE_ERRORS = ['ECONNRESET', 'ETIMEDOUT', 'fetch failed'];\n\nexport class EditClient {\n private gatewayUrl: string;\n private authToken?: string;\n private network: Network;\n private userId?: string;\n private retryConfig: RetryConfig;\n private statusUrlTransform?: (url: string) => string;\n private apiPrefix: string;\n\n constructor(config: EditClientConfig) {\n this.gatewayUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.authToken = config.authToken;\n this.network = config.network || 'main';\n this.userId = config.userId;\n this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config.retryConfig };\n this.statusUrlTransform = config.statusUrlTransform;\n this.apiPrefix = config.apiPrefix ?? '/api';\n }\n\n // ===========================================================================\n // Configuration Methods\n // ===========================================================================\n\n /**\n * Update the auth token (useful for token refresh)\n */\n setAuthToken(token: string): void {\n this.authToken = token;\n }\n\n /**\n * Set the network (main or test)\n */\n setNetwork(network: Network): void {\n this.network = network;\n }\n\n /**\n * Set the user ID for permission checks\n */\n setUserId(userId: string): void {\n this.userId = userId;\n }\n\n // ===========================================================================\n // Internal Helpers\n // ===========================================================================\n\n /**\n * Build URL with API prefix\n */\n private buildUrl(path: string): string {\n return `${this.gatewayUrl}${this.apiPrefix}${path}`;\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n private getHeaders(contentType: string | null = 'application/json'): HeadersInit {\n const headers: HeadersInit = {};\n if (contentType) {\n headers['Content-Type'] = contentType;\n }\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n headers['X-Arke-Network'] = this.network;\n if (this.userId) {\n headers['X-User-Id'] = this.userId;\n }\n return headers;\n }\n\n private calculateDelay(attempt: number): number {\n const { baseDelay, maxDelay, jitterFactor } = this.retryConfig;\n const exponentialDelay = baseDelay * Math.pow(2, attempt);\n const cappedDelay = Math.min(exponentialDelay, maxDelay);\n const jitter = cappedDelay * jitterFactor * (Math.random() * 2 - 1);\n return Math.max(0, cappedDelay + jitter);\n }\n\n private isRetryableStatus(status: number): boolean {\n return RETRYABLE_STATUS_CODES.includes(status);\n }\n\n private isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n return RETRYABLE_ERRORS.some((e) => message.includes(e.toLowerCase()));\n }\n\n /**\n * Execute a fetch with exponential backoff retry on transient errors\n */\n private async fetchWithRetry(\n url: string,\n options: RequestInit,\n context: string\n ): Promise<Response> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n\n // Check for retryable status codes\n if (this.isRetryableStatus(response.status) && attempt < this.retryConfig.maxRetries) {\n const delay = this.calculateDelay(attempt);\n lastError = new Error(`${context}: ${response.status} ${response.statusText}`);\n await this.sleep(delay);\n continue;\n }\n\n return response;\n } catch (error) {\n lastError = error as Error;\n if (this.isRetryableError(lastError) && attempt < this.retryConfig.maxRetries) {\n const delay = this.calculateDelay(attempt);\n await this.sleep(delay);\n continue;\n }\n throw new NetworkError(lastError.message);\n }\n }\n\n throw lastError || new NetworkError('Request failed after retries');\n }\n\n /**\n * Handle common error responses and throw appropriate error types\n */\n private async handleErrorResponse(response: Response, context: string): Promise<never> {\n let errorData: { error?: string; message?: string; details?: unknown } = {};\n try {\n errorData = await response.json();\n } catch {\n // Response may not be JSON\n }\n\n const message = errorData.message || `${context}: ${response.statusText}`;\n const errorCode = errorData.error || '';\n\n switch (response.status) {\n case 400:\n throw new ValidationError(message);\n case 403:\n throw new PermissionError(message);\n case 404:\n throw new EntityNotFoundError(message);\n case 409:\n if (errorCode === 'CAS_FAILURE') {\n const details = errorData.details as { actual?: string; expect?: string } | undefined;\n throw new CASConflictError(\n context,\n details?.expect || 'unknown',\n details?.actual || 'unknown'\n );\n }\n if (errorCode === 'CONFLICT') {\n throw new EntityExistsError(message);\n }\n throw new EditError(message, errorCode, errorData.details);\n case 503:\n if (errorCode === 'IPFS_ERROR') {\n throw new IPFSError(message);\n }\n if (errorCode === 'BACKEND_ERROR') {\n throw new BackendError(message);\n }\n throw new NetworkError(message, response.status);\n default:\n throw new EditError(message, errorCode || 'API_ERROR', { status: response.status });\n }\n }\n\n // ===========================================================================\n // Entity CRUD Operations\n // ===========================================================================\n\n /**\n * Create a new entity\n */\n async createEntity(request: CreateEntityRequest): Promise<CreateEntityResponse> {\n const url = this.buildUrl('/entities');\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(request),\n },\n 'Create entity'\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, 'Create entity');\n }\n\n return response.json();\n }\n\n /**\n * Get an entity by ID\n */\n async getEntity(id: string): Promise<Entity> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}`);\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n `Get entity ${id}`\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Get entity ${id}`);\n }\n\n return response.json();\n }\n\n /**\n * List entities with pagination\n */\n async listEntities(options: ListEntitiesOptions = {}): Promise<ListEntitiesResponse> {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', options.limit.toString());\n if (options.cursor) params.set('cursor', options.cursor);\n if (options.include_metadata) params.set('include_metadata', 'true');\n\n const queryString = params.toString();\n const url = this.buildUrl(`/entities${queryString ? `?${queryString}` : ''}`);\n\n const response = await this.fetchWithRetry(url, { headers: this.getHeaders() }, 'List entities');\n\n if (!response.ok) {\n await this.handleErrorResponse(response, 'List entities');\n }\n\n return response.json();\n }\n\n /**\n * Update an entity (append new version)\n */\n async updateEntity(id: string, update: UpdateEntityRequest): Promise<UpdateEntityResponse> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}/versions`);\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(update),\n },\n `Update entity ${id}`\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Update entity ${id}`);\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Version Operations\n // ===========================================================================\n\n /**\n * List version history for an entity\n */\n async listVersions(id: string, options: ListVersionsOptions = {}): Promise<ListVersionsResponse> {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', options.limit.toString());\n if (options.cursor) params.set('cursor', options.cursor);\n\n const queryString = params.toString();\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}/versions${queryString ? `?${queryString}` : ''}`);\n\n const response = await this.fetchWithRetry(url, { headers: this.getHeaders() }, `List versions for ${id}`);\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `List versions for ${id}`);\n }\n\n return response.json();\n }\n\n /**\n * Get a specific version of an entity\n */\n async getVersion(id: string, selector: string): Promise<Entity> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}/versions/${encodeURIComponent(selector)}`);\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n `Get version ${selector} for ${id}`\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Get version ${selector} for ${id}`);\n }\n\n return response.json();\n }\n\n /**\n * Resolve an entity ID to its current tip CID (fast lookup)\n */\n async resolve(id: string): Promise<ResolveResponse> {\n const url = this.buildUrl(`/resolve/${encodeURIComponent(id)}`);\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n `Resolve ${id}`\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Resolve ${id}`);\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Hierarchy Operations\n // ===========================================================================\n\n /**\n * Update parent-child hierarchy relationships\n */\n async updateHierarchy(request: UpdateHierarchyRequest): Promise<UpdateHierarchyResponse> {\n const apiRequest = {\n parent_pi: request.parent_id,\n expect_tip: request.expect_tip,\n add_children: request.add_children,\n remove_children: request.remove_children,\n note: request.note,\n };\n\n const url = this.buildUrl('/hierarchy');\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(apiRequest),\n },\n `Update hierarchy for ${request.parent_id}`\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Update hierarchy for ${request.parent_id}`);\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Merge Operations\n // ===========================================================================\n\n /**\n * Merge source entity into target entity\n */\n async mergeEntity(sourceId: string, request: MergeEntityRequest): Promise<MergeEntityResponse> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(sourceId)}/merge`);\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(request),\n },\n `Merge ${sourceId} into ${request.target_id}`\n );\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw new MergeError(\n error.message || `Merge failed: ${response.statusText}`,\n sourceId,\n request.target_id\n );\n } catch (e) {\n if (e instanceof MergeError) throw e;\n await this.handleErrorResponse(response, `Merge ${sourceId}`);\n }\n }\n\n return response.json();\n }\n\n /**\n * Unmerge (restore) a previously merged entity\n */\n async unmergeEntity(sourceId: string, request: UnmergeEntityRequest): Promise<UnmergeEntityResponse> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(sourceId)}/unmerge`);\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(request),\n },\n `Unmerge ${sourceId}`\n );\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw new UnmergeError(\n error.message || `Unmerge failed: ${response.statusText}`,\n sourceId,\n request.target_id\n );\n } catch (e) {\n if (e instanceof UnmergeError) throw e;\n await this.handleErrorResponse(response, `Unmerge ${sourceId}`);\n }\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Delete Operations\n // ===========================================================================\n\n /**\n * Soft delete an entity (creates tombstone, preserves history)\n */\n async deleteEntity(id: string, request: DeleteEntityRequest): Promise<DeleteEntityResponse> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}/delete`);\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(request),\n },\n `Delete ${id}`\n );\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw new DeleteError(error.message || `Delete failed: ${response.statusText}`, id);\n } catch (e) {\n if (e instanceof DeleteError) throw e;\n await this.handleErrorResponse(response, `Delete ${id}`);\n }\n }\n\n return response.json();\n }\n\n /**\n * Restore a deleted entity\n */\n async undeleteEntity(id: string, request: UndeleteEntityRequest): Promise<UndeleteEntityResponse> {\n const url = this.buildUrl(`/entities/${encodeURIComponent(id)}/undelete`);\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(request),\n },\n `Undelete ${id}`\n );\n\n if (!response.ok) {\n try {\n const error = await response.json();\n throw new UndeleteError(error.message || `Undelete failed: ${response.statusText}`, id);\n } catch (e) {\n if (e instanceof UndeleteError) throw e;\n await this.handleErrorResponse(response, `Undelete ${id}`);\n }\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Content Operations\n // ===========================================================================\n\n /**\n * Upload files to IPFS\n */\n async upload(files: File | Blob | File[] | Blob[] | FormData): Promise<UploadResponse[]> {\n let formData: FormData;\n\n if (files instanceof FormData) {\n formData = files;\n } else {\n formData = new FormData();\n const fileArray = Array.isArray(files) ? files : [files];\n for (const file of fileArray) {\n if (file instanceof File) {\n formData.append('file', file, file.name);\n } else {\n formData.append('file', file, 'file');\n }\n }\n }\n\n const url = this.buildUrl('/upload');\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(null), // No Content-Type for multipart\n body: formData,\n },\n 'Upload files'\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, 'Upload files');\n }\n\n return response.json();\n }\n\n /**\n * Upload text content and return CID\n */\n async uploadContent(content: string, filename: string): Promise<string> {\n const blob = new Blob([content], { type: 'text/plain' });\n const file = new File([blob], filename, { type: 'text/plain' });\n const [result] = await this.upload(file);\n return result.cid;\n }\n\n /**\n * Download file content by CID\n */\n async getContent(cid: string): Promise<string> {\n const url = this.buildUrl(`/cat/${encodeURIComponent(cid)}`);\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n `Get content ${cid}`\n );\n\n if (response.status === 404) {\n throw new ContentNotFoundError(cid);\n }\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Get content ${cid}`);\n }\n\n return response.text();\n }\n\n /**\n * Download a DAG node (JSON) by CID\n */\n async getDag<T = unknown>(cid: string): Promise<T> {\n const url = this.buildUrl(`/dag/${encodeURIComponent(cid)}`);\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n `Get DAG ${cid}`\n );\n\n if (response.status === 404) {\n throw new ContentNotFoundError(cid);\n }\n\n if (!response.ok) {\n await this.handleErrorResponse(response, `Get DAG ${cid}`);\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Arke Origin Operations\n // ===========================================================================\n\n /**\n * Get the Arke origin block (genesis entity)\n */\n async getArke(): Promise<Entity> {\n const url = this.buildUrl('/arke');\n const response = await this.fetchWithRetry(\n url,\n { headers: this.getHeaders() },\n 'Get Arke'\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, 'Get Arke');\n }\n\n return response.json();\n }\n\n /**\n * Initialize the Arke origin block (creates if doesn't exist)\n */\n async initArke(): Promise<CreateEntityResponse> {\n const url = this.buildUrl('/arke/init');\n const response = await this.fetchWithRetry(\n url,\n {\n method: 'POST',\n headers: this.getHeaders(),\n },\n 'Init Arke'\n );\n\n if (!response.ok) {\n await this.handleErrorResponse(response, 'Init Arke');\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Reprocess API Operations (via /reprocess/*)\n // ===========================================================================\n\n /**\n * Trigger reprocessing for an entity\n */\n async reprocess(request: ReprocessRequest): Promise<ReprocessResult> {\n const response = await this.fetchWithRetry(\n `${this.gatewayUrl}/reprocess/reprocess`,\n {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify({\n pi: request.pi,\n phases: request.phases,\n cascade: request.cascade,\n options: request.options,\n }),\n },\n `Reprocess ${request.pi}`\n );\n\n if (response.status === 403) {\n const error = await response.json().catch(() => ({}));\n throw new PermissionError(\n error.message || `Permission denied to reprocess ${request.pi}`,\n request.pi\n );\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new ReprocessError(error.message || `Reprocess failed: ${response.statusText}`);\n }\n\n return response.json();\n }\n\n /**\n * Get reprocessing status by batch ID\n */\n async getReprocessStatus(statusUrl: string, isFirstPoll = false): Promise<ReprocessStatus> {\n const fetchUrl = this.statusUrlTransform ? this.statusUrlTransform(statusUrl) : statusUrl;\n\n const delay = isFirstPoll ? 3000 : this.retryConfig.baseDelay;\n if (isFirstPoll) {\n await this.sleep(delay);\n }\n\n const response = await this.fetchWithRetry(\n fetchUrl,\n { headers: this.getHeaders() },\n 'Get reprocess status'\n );\n\n if (!response.ok) {\n throw new EditError(\n `Failed to fetch reprocess status: ${response.statusText}`,\n 'STATUS_ERROR',\n { status: response.status }\n );\n }\n\n return response.json();\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Execute an operation with automatic CAS retry\n */\n async withCAS<T>(\n id: string,\n operation: (entity: Entity) => Promise<T>,\n maxRetries = 3\n ): Promise<T> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n const entity = await this.getEntity(id);\n return await operation(entity);\n } catch (error) {\n if (error instanceof CASConflictError && attempt < maxRetries - 1) {\n lastError = error;\n const delay = this.calculateDelay(attempt);\n await this.sleep(delay);\n continue;\n }\n throw error;\n }\n }\n\n throw lastError || new EditError('withCAS failed after retries');\n }\n}\n","/**\n * DiffEngine - Text comparison and diff formatting\n */\n\nimport * as Diff from 'diff';\nimport type { TextDiff, ComponentDiff, Correction } from './types';\n\nexport class DiffEngine {\n /**\n * Compute diff between two strings\n */\n static diff(original: string, modified: string): TextDiff[] {\n const changes = Diff.diffLines(original, modified);\n const diffs: TextDiff[] = [];\n let lineNumber = 1;\n\n for (const change of changes) {\n if (change.added) {\n diffs.push({\n type: 'addition',\n modified: change.value.trimEnd(),\n lineNumber,\n });\n } else if (change.removed) {\n diffs.push({\n type: 'deletion',\n original: change.value.trimEnd(),\n lineNumber,\n });\n } else {\n // Track line numbers for unchanged content\n const lines = change.value.split('\\n').length - 1;\n lineNumber += lines;\n }\n\n // Update line number for added content\n if (change.added) {\n lineNumber += change.value.split('\\n').length - 1;\n }\n }\n\n return diffs;\n }\n\n /**\n * Compute word-level diff for more granular changes\n */\n static diffWords(original: string, modified: string): TextDiff[] {\n const changes = Diff.diffWords(original, modified);\n const diffs: TextDiff[] = [];\n\n for (const change of changes) {\n if (change.added) {\n diffs.push({\n type: 'addition',\n modified: change.value,\n });\n } else if (change.removed) {\n diffs.push({\n type: 'deletion',\n original: change.value,\n });\n }\n }\n\n return diffs;\n }\n\n /**\n * Create a ComponentDiff from original and modified content\n */\n static createComponentDiff(\n componentName: string,\n original: string,\n modified: string\n ): ComponentDiff {\n const diffs = this.diff(original, modified);\n const hasChanges = diffs.length > 0;\n\n let summary: string;\n if (!hasChanges) {\n summary = 'No changes';\n } else {\n const additions = diffs.filter((d) => d.type === 'addition').length;\n const deletions = diffs.filter((d) => d.type === 'deletion').length;\n const parts: string[] = [];\n if (additions > 0) parts.push(`${additions} addition${additions > 1 ? 's' : ''}`);\n if (deletions > 0) parts.push(`${deletions} deletion${deletions > 1 ? 's' : ''}`);\n summary = parts.join(', ');\n }\n\n return {\n componentName,\n diffs,\n summary,\n hasChanges,\n };\n }\n\n /**\n * Format diffs for AI prompt consumption\n */\n static formatForPrompt(diffs: TextDiff[]): string {\n if (diffs.length === 0) {\n return 'No changes detected.';\n }\n\n const lines: string[] = [];\n\n for (const diff of diffs) {\n const linePrefix = diff.lineNumber ? `Line ${diff.lineNumber}: ` : '';\n\n if (diff.type === 'addition') {\n lines.push(`${linePrefix}+ ${diff.modified}`);\n } else if (diff.type === 'deletion') {\n lines.push(`${linePrefix}- ${diff.original}`);\n } else if (diff.type === 'change') {\n lines.push(`${linePrefix}\"${diff.original}\" → \"${diff.modified}\"`);\n }\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Format component diffs for AI prompt\n */\n static formatComponentDiffsForPrompt(componentDiffs: ComponentDiff[]): string {\n const sections: string[] = [];\n\n for (const cd of componentDiffs) {\n if (!cd.hasChanges) continue;\n\n sections.push(`## Changes to ${cd.componentName}:`);\n sections.push(this.formatForPrompt(cd.diffs));\n sections.push('');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Create a unified diff view\n */\n static unifiedDiff(\n original: string,\n modified: string,\n options?: { filename?: string; context?: number }\n ): string {\n const filename = options?.filename || 'content';\n const patch = Diff.createPatch(filename, original, modified, '', '', {\n context: options?.context ?? 3,\n });\n return patch;\n }\n\n /**\n * Extract corrections from diffs (specific text replacements)\n */\n static extractCorrections(\n original: string,\n modified: string,\n sourceFile?: string\n ): Correction[] {\n const wordDiffs = Diff.diffWords(original, modified);\n const corrections: Correction[] = [];\n\n let i = 0;\n while (i < wordDiffs.length) {\n const current = wordDiffs[i];\n\n // Look for removal followed by addition (a replacement)\n if (current.removed && i + 1 < wordDiffs.length && wordDiffs[i + 1].added) {\n const removed = current.value.trim();\n const added = wordDiffs[i + 1].value.trim();\n\n if (removed && added && removed !== added) {\n corrections.push({\n original: removed,\n corrected: added,\n sourceFile,\n });\n }\n i += 2;\n } else {\n i++;\n }\n }\n\n return corrections;\n }\n\n /**\n * Check if two strings are meaningfully different\n * (ignoring whitespace differences)\n */\n static hasSignificantChanges(original: string, modified: string): boolean {\n const normalizedOriginal = original.replace(/\\s+/g, ' ').trim();\n const normalizedModified = modified.replace(/\\s+/g, ' ').trim();\n return normalizedOriginal !== normalizedModified;\n }\n}\n","/**\n * PromptBuilder - Context-aware AI prompt construction\n */\n\nimport { DiffEngine } from './diff';\nimport type {\n RegeneratableComponent,\n EntityContext,\n CascadeContext,\n ComponentDiff,\n Correction,\n} from './types';\n\nexport class PromptBuilder {\n /**\n * Build prompt for AI-first mode (user provides instructions)\n */\n static buildAIPrompt(\n userPrompt: string,\n component: RegeneratableComponent,\n entityContext: EntityContext,\n currentContent?: string\n ): string {\n const sections: string[] = [];\n\n // User instruction\n sections.push(`## Instructions for ${component}`);\n sections.push(userPrompt);\n sections.push('');\n\n // Entity context\n sections.push('## Entity Context');\n sections.push(`- PI: ${entityContext.pi}`);\n sections.push(`- Current version: ${entityContext.ver}`);\n if (entityContext.parentPi) {\n sections.push(`- Parent: ${entityContext.parentPi}`);\n }\n if (entityContext.childrenCount > 0) {\n sections.push(`- Children: ${entityContext.childrenCount}`);\n }\n sections.push('');\n\n // Current content reference\n if (currentContent) {\n sections.push(`## Current ${component} content for reference:`);\n sections.push('```');\n sections.push(currentContent.slice(0, 2000)); // Truncate if very long\n if (currentContent.length > 2000) {\n sections.push('... [truncated]');\n }\n sections.push('```');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Build prompt incorporating manual edits and diffs\n */\n static buildEditReviewPrompt(\n componentDiffs: ComponentDiff[],\n corrections: Correction[],\n component: RegeneratableComponent,\n userInstructions?: string\n ): string {\n const sections: string[] = [];\n\n sections.push('## Manual Edits Made');\n sections.push('');\n sections.push('The following manual edits were made to this entity:');\n sections.push('');\n\n // Show diffs\n const diffContent = DiffEngine.formatComponentDiffsForPrompt(componentDiffs);\n if (diffContent) {\n sections.push(diffContent);\n }\n\n // Show corrections\n if (corrections.length > 0) {\n sections.push('## Corrections Identified');\n sections.push('');\n for (const correction of corrections) {\n const source = correction.sourceFile ? ` (in ${correction.sourceFile})` : '';\n sections.push(`- \"${correction.original}\" → \"${correction.corrected}\"${source}`);\n }\n sections.push('');\n }\n\n // User instructions\n sections.push('## Instructions');\n if (userInstructions) {\n sections.push(userInstructions);\n } else {\n sections.push(\n `Update the ${component} to accurately reflect these changes. ` +\n 'Ensure any corrections are incorporated and the content is consistent.'\n );\n }\n sections.push('');\n\n // Specific guidance per component\n sections.push('## Guidance');\n switch (component) {\n case 'pinax':\n sections.push(\n 'Update metadata fields to reflect any corrections. Pay special attention to dates, ' +\n 'names, and other factual information that may have been corrected.'\n );\n break;\n case 'description':\n sections.push(\n 'Regenerate the description incorporating the changes. Maintain the overall tone ' +\n 'and structure while ensuring accuracy based on the corrections.'\n );\n break;\n case 'cheimarros':\n sections.push(\n 'Update the knowledge graph to reflect any new or corrected entities, relationships, ' +\n 'and facts identified in the changes.'\n );\n break;\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Build cascade-aware prompt additions\n */\n static buildCascadePrompt(basePrompt: string, cascadeContext: CascadeContext): string {\n const sections: string[] = [basePrompt];\n\n sections.push('');\n sections.push('## Cascade Context');\n sections.push('');\n sections.push(\n 'This edit is part of a cascading update. After updating this entity, ' +\n 'parent entities will also be updated to reflect these changes.'\n );\n sections.push('');\n\n if (cascadeContext.path.length > 1) {\n sections.push(`Cascade path: ${cascadeContext.path.join(' → ')}`);\n sections.push(`Depth: ${cascadeContext.depth}`);\n }\n\n if (cascadeContext.stopAtPi) {\n sections.push(`Cascade will stop at: ${cascadeContext.stopAtPi}`);\n }\n\n sections.push('');\n sections.push(\n 'Ensure the content accurately represents the source material so parent ' +\n 'aggregations will be correct.'\n );\n\n return sections.join('\\n');\n }\n\n /**\n * Build a general prompt combining multiple instructions\n */\n static buildCombinedPrompt(\n generalPrompt: string | undefined,\n componentPrompt: string | undefined,\n component: RegeneratableComponent\n ): string {\n const sections: string[] = [];\n\n if (generalPrompt) {\n sections.push('## General Instructions');\n sections.push(generalPrompt);\n sections.push('');\n }\n\n if (componentPrompt) {\n sections.push(`## Specific Instructions for ${component}`);\n sections.push(componentPrompt);\n sections.push('');\n }\n\n if (sections.length === 0) {\n return `Regenerate the ${component} based on the current entity content.`;\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Build prompt for correction-based updates\n */\n static buildCorrectionPrompt(corrections: Correction[]): string {\n if (corrections.length === 0) {\n return '';\n }\n\n const sections: string[] = [];\n\n sections.push('## Corrections Applied');\n sections.push('');\n sections.push('The following corrections were made to the source content:');\n sections.push('');\n\n for (const correction of corrections) {\n const source = correction.sourceFile ? ` in ${correction.sourceFile}` : '';\n sections.push(`- \"${correction.original}\" was corrected to \"${correction.corrected}\"${source}`);\n if (correction.context) {\n sections.push(` Context: ${correction.context}`);\n }\n }\n\n sections.push('');\n sections.push(\n 'Update the metadata and description to reflect these corrections. ' +\n 'Previous content may have contained errors based on the incorrect text.'\n );\n\n return sections.join('\\n');\n }\n\n /**\n * Get component-specific regeneration guidance\n */\n static getComponentGuidance(component: RegeneratableComponent): string {\n switch (component) {\n case 'pinax':\n return (\n 'Extract and structure metadata including: institution, creator, title, ' +\n 'date range, subjects, type, and other relevant fields. Ensure accuracy ' +\n 'based on the source content.'\n );\n case 'description':\n return (\n 'Generate a clear, informative description that summarizes the entity content. ' +\n 'Focus on what the material contains, its historical significance, and context. ' +\n 'Write for a general audience unless otherwise specified.'\n );\n case 'cheimarros':\n return (\n 'Extract entities (people, places, organizations, events) and their relationships. ' +\n 'Build a knowledge graph that captures the key facts and connections in the content.'\n );\n default:\n return '';\n }\n }\n}\n","/**\n * EditSession - Stateful session managing an edit workflow\n */\n\nimport { EditClient } from './client';\nimport { DiffEngine } from './diff';\nimport { PromptBuilder } from './prompts';\nimport type {\n Entity,\n EditMode,\n EditSessionConfig,\n EditScope,\n Correction,\n ComponentDiff,\n RegeneratableComponent,\n PromptTarget,\n ChangeSummary,\n EditResult,\n EditStatus,\n PollOptions,\n CustomPrompts,\n} from './types';\nimport { ValidationError } from './errors';\n\nconst DEFAULT_SCOPE: EditScope = {\n components: [],\n cascade: false,\n};\n\nconst DEFAULT_POLL_OPTIONS: Required<Omit<PollOptions, 'onProgress'>> = {\n intervalMs: 2000,\n timeoutMs: 300000, // 5 minutes\n};\n\nexport class EditSession {\n readonly pi: string;\n readonly mode: EditMode;\n readonly aiReviewEnabled: boolean;\n\n private client: EditClient;\n private entity: Entity | null = null;\n private loadedComponents: Record<string, string> = {};\n\n // AI mode state\n private prompts: Record<string, string> = {};\n\n // Manual mode state\n private editedContent: Record<string, string> = {};\n private corrections: Correction[] = [];\n\n // Scope\n private scope: EditScope = { ...DEFAULT_SCOPE };\n\n // Execution state\n private submitting = false;\n private result: EditResult | null = null;\n private statusUrl: string | null = null;\n\n constructor(client: EditClient, pi: string, config?: EditSessionConfig) {\n this.client = client;\n this.pi = pi;\n this.mode = config?.mode ?? 'ai-prompt';\n this.aiReviewEnabled = config?.aiReviewEnabled ?? true;\n }\n\n // ===========================================================================\n // Loading\n // ===========================================================================\n\n /**\n * Load the entity and its key components\n */\n async load(): Promise<void> {\n this.entity = await this.client.getEntity(this.pi);\n\n // Load key components that are commonly edited\n const priorityComponents = ['description.md', 'pinax.json', 'cheimarros.json'];\n\n await Promise.all(\n priorityComponents.map(async (name) => {\n const cid = this.entity!.components[name];\n if (cid) {\n try {\n this.loadedComponents[name] = await this.client.getContent(cid);\n } catch {\n // Component may not exist, that's ok\n }\n }\n })\n );\n }\n\n /**\n * Load a specific component on demand\n */\n async loadComponent(name: string): Promise<string | undefined> {\n if (this.loadedComponents[name]) {\n return this.loadedComponents[name];\n }\n\n if (!this.entity) {\n throw new ValidationError('Session not loaded');\n }\n\n const cid = this.entity.components[name];\n if (!cid) {\n return undefined;\n }\n\n const content = await this.client.getContent(cid);\n this.loadedComponents[name] = content;\n return content;\n }\n\n /**\n * Get the loaded entity\n */\n getEntity(): Entity {\n if (!this.entity) {\n throw new ValidationError('Session not loaded. Call load() first.');\n }\n return this.entity;\n }\n\n /**\n * Get loaded component content\n */\n getComponents(): Record<string, string> {\n return { ...this.loadedComponents };\n }\n\n // ===========================================================================\n // AI Prompt Mode\n // ===========================================================================\n\n /**\n * Set a prompt for AI regeneration\n */\n setPrompt(target: PromptTarget, prompt: string): void {\n if (this.mode === 'manual-only') {\n throw new ValidationError('Cannot set prompts in manual-only mode');\n }\n this.prompts[target] = prompt;\n }\n\n /**\n * Get all prompts\n */\n getPrompts(): Record<string, string> {\n return { ...this.prompts };\n }\n\n /**\n * Clear a prompt\n */\n clearPrompt(target: PromptTarget): void {\n delete this.prompts[target];\n }\n\n // ===========================================================================\n // Manual Edit Mode\n // ===========================================================================\n\n /**\n * Set edited content for a component\n */\n setContent(componentName: string, content: string): void {\n if (this.mode === 'ai-prompt') {\n throw new ValidationError('Cannot set content in ai-prompt mode');\n }\n this.editedContent[componentName] = content;\n }\n\n /**\n * Get all edited content\n */\n getEditedContent(): Record<string, string> {\n return { ...this.editedContent };\n }\n\n /**\n * Clear edited content for a component\n */\n clearContent(componentName: string): void {\n delete this.editedContent[componentName];\n }\n\n /**\n * Add a correction (for OCR fixes, etc.)\n */\n addCorrection(original: string, corrected: string, sourceFile?: string): void {\n this.corrections.push({ original, corrected, sourceFile });\n }\n\n /**\n * Get all corrections\n */\n getCorrections(): Correction[] {\n return [...this.corrections];\n }\n\n /**\n * Clear corrections\n */\n clearCorrections(): void {\n this.corrections = [];\n }\n\n // ===========================================================================\n // Scope Configuration\n // ===========================================================================\n\n /**\n * Set the edit scope\n */\n setScope(scope: Partial<EditScope>): void {\n this.scope = { ...this.scope, ...scope };\n }\n\n /**\n * Get the current scope\n */\n getScope(): EditScope {\n return { ...this.scope };\n }\n\n // ===========================================================================\n // Preview & Summary\n // ===========================================================================\n\n /**\n * Get diffs for manual changes\n */\n getDiff(): ComponentDiff[] {\n const diffs: ComponentDiff[] = [];\n\n for (const [name, edited] of Object.entries(this.editedContent)) {\n const original = this.loadedComponents[name] || '';\n if (DiffEngine.hasSignificantChanges(original, edited)) {\n diffs.push(DiffEngine.createComponentDiff(name, original, edited));\n }\n }\n\n return diffs;\n }\n\n /**\n * Preview what prompts will be sent to AI\n */\n previewPrompt(): Record<RegeneratableComponent, string> {\n const result: Record<string, string> = {};\n\n if (!this.entity) return result as Record<RegeneratableComponent, string>;\n\n const entityContext = {\n pi: this.entity.id,\n ver: this.entity.ver,\n parentPi: this.entity.parent_pi,\n childrenCount: this.entity.children_pi?.length ?? 0,\n currentContent: this.loadedComponents,\n };\n\n for (const component of this.scope.components) {\n let prompt: string;\n\n if (this.mode === 'ai-prompt') {\n // AI prompt mode: use user's prompt\n const componentPrompt = this.prompts[component];\n const generalPrompt = this.prompts['general'];\n const combined = PromptBuilder.buildCombinedPrompt(generalPrompt, componentPrompt, component);\n prompt = PromptBuilder.buildAIPrompt(\n combined,\n component,\n entityContext,\n this.loadedComponents[`${component}.json`] || this.loadedComponents[`${component}.md`]\n );\n } else {\n // Manual mode: build from diffs and corrections\n const diffs = this.getDiff();\n const userInstructions = this.prompts['general'] || this.prompts[component];\n prompt = PromptBuilder.buildEditReviewPrompt(diffs, this.corrections, component, userInstructions);\n }\n\n // Add cascade context if applicable\n if (this.scope.cascade) {\n prompt = PromptBuilder.buildCascadePrompt(prompt, {\n path: [this.entity.id, this.entity.parent_pi || 'root'].filter(Boolean) as string[],\n depth: 0,\n stopAtPi: this.scope.stopAtPi,\n });\n }\n\n result[component] = prompt;\n }\n\n return result as Record<RegeneratableComponent, string>;\n }\n\n /**\n * Get a summary of pending changes\n */\n getChangeSummary(): ChangeSummary {\n const diffs = this.getDiff();\n const hasManualEdits = diffs.some((d) => d.hasChanges);\n\n return {\n mode: this.mode,\n hasManualEdits,\n editedComponents: Object.keys(this.editedContent),\n corrections: [...this.corrections],\n prompts: { ...this.prompts },\n scope: { ...this.scope },\n willRegenerate: [...this.scope.components],\n willCascade: this.scope.cascade,\n willSave: hasManualEdits,\n willReprocess: this.scope.components.length > 0,\n };\n }\n\n // ===========================================================================\n // Execution\n // ===========================================================================\n\n /**\n * Submit changes (saves first if manual edits, then reprocesses)\n */\n async submit(note: string): Promise<EditResult> {\n if (this.submitting) {\n throw new ValidationError('Submit already in progress');\n }\n if (!this.entity) {\n throw new ValidationError('Session not loaded. Call load() first.');\n }\n\n this.submitting = true;\n this.result = {};\n\n try {\n // Phase 1: Save manual edits if any\n const diffs = this.getDiff();\n const hasManualEdits = diffs.some((d) => d.hasChanges);\n\n if (hasManualEdits) {\n // Upload edited components and collect CIDs\n const componentUpdates: Record<string, string> = {};\n\n for (const [name, content] of Object.entries(this.editedContent)) {\n const original = this.loadedComponents[name] || '';\n if (DiffEngine.hasSignificantChanges(original, content)) {\n const cid = await this.client.uploadContent(content, name);\n componentUpdates[name] = cid;\n }\n }\n\n // Update entity\n const version = await this.client.updateEntity(this.pi, {\n expect_tip: this.entity.manifest_cid,\n components: componentUpdates,\n note,\n });\n\n this.result.saved = {\n pi: version.id,\n newVersion: version.ver,\n newTip: version.tip,\n };\n\n // Update our entity reference\n this.entity.manifest_cid = version.tip;\n this.entity.ver = version.ver;\n }\n\n // Phase 2: Trigger reprocessing if components selected\n if (this.scope.components.length > 0) {\n const customPrompts = this.buildCustomPrompts();\n\n const reprocessResult = await this.client.reprocess({\n pi: this.pi,\n phases: this.scope.components,\n cascade: this.scope.cascade,\n options: {\n stop_at_pi: this.scope.stopAtPi,\n custom_prompts: customPrompts,\n custom_note: note,\n },\n });\n\n this.result.reprocess = reprocessResult;\n this.statusUrl = reprocessResult.status_url;\n }\n\n return this.result;\n } finally {\n this.submitting = false;\n }\n }\n\n /**\n * Wait for reprocessing to complete\n */\n async waitForCompletion(options?: PollOptions): Promise<EditStatus> {\n const opts = { ...DEFAULT_POLL_OPTIONS, ...options };\n\n if (!this.statusUrl) {\n return {\n phase: 'complete',\n saveComplete: true,\n };\n }\n\n const startTime = Date.now();\n let isFirstPoll = true;\n\n while (true) {\n // Pass isFirstPoll flag - the client will use longer retry delays on first poll\n // since the orchestrator often needs time to initialize after reprocess is triggered\n const status = await this.client.getReprocessStatus(this.statusUrl, isFirstPoll);\n isFirstPoll = false;\n\n const editStatus: EditStatus = {\n phase: status.status === 'DONE' ? 'complete' : status.status === 'ERROR' ? 'error' : 'reprocessing',\n saveComplete: true,\n reprocessStatus: status,\n error: status.error,\n };\n\n if (opts.onProgress) {\n opts.onProgress(editStatus);\n }\n\n if (status.status === 'DONE' || status.status === 'ERROR') {\n return editStatus;\n }\n\n if (Date.now() - startTime > opts.timeoutMs) {\n return {\n phase: 'error',\n saveComplete: true,\n reprocessStatus: status,\n error: 'Timeout waiting for reprocessing to complete',\n };\n }\n\n await new Promise((resolve) => setTimeout(resolve, opts.intervalMs));\n }\n }\n\n /**\n * Get current status without waiting\n */\n async getStatus(): Promise<EditStatus> {\n if (!this.statusUrl) {\n return {\n phase: this.result?.saved ? 'complete' : 'idle',\n saveComplete: !!this.result?.saved,\n };\n }\n\n const status = await this.client.getReprocessStatus(this.statusUrl);\n\n return {\n phase: status.status === 'DONE' ? 'complete' : status.status === 'ERROR' ? 'error' : 'reprocessing',\n saveComplete: true,\n reprocessStatus: status,\n error: status.error,\n };\n }\n\n // ===========================================================================\n // Private Helpers\n // ===========================================================================\n\n private buildCustomPrompts(): CustomPrompts {\n const custom: CustomPrompts = {};\n\n // In AI prompt mode, prompts go directly to reprocess API\n if (this.mode === 'ai-prompt') {\n if (this.prompts['general']) custom.general = this.prompts['general'];\n if (this.prompts['pinax']) custom.pinax = this.prompts['pinax'];\n if (this.prompts['description']) custom.description = this.prompts['description'];\n if (this.prompts['cheimarros']) custom.cheimarros = this.prompts['cheimarros'];\n } else {\n // Manual mode: build prompts from diffs, corrections, and user instructions\n const diffs = this.getDiff();\n const diffContext = DiffEngine.formatComponentDiffsForPrompt(diffs);\n const correctionContext = PromptBuilder.buildCorrectionPrompt(this.corrections);\n\n // Combine all context: diffs + corrections + user instructions\n const basePrompt = [diffContext, correctionContext, this.prompts['general']]\n .filter(Boolean)\n .join('\\n\\n');\n\n if (basePrompt) {\n custom.general = basePrompt;\n }\n\n // Component-specific prompts\n if (this.prompts['pinax']) custom.pinax = this.prompts['pinax'];\n if (this.prompts['description']) custom.description = this.prompts['description'];\n if (this.prompts['cheimarros']) custom.cheimarros = this.prompts['cheimarros'];\n }\n\n return custom;\n }\n}\n","/**\n * Content package error classes for the Arke SDK\n */\n\n/**\n * Base error class for content operations\n */\nexport class ContentError extends Error {\n constructor(\n message: string,\n public code: string = 'CONTENT_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'ContentError';\n }\n}\n\n/**\n * Thrown when an entity is not found by ID\n */\nexport class EntityNotFoundError extends ContentError {\n constructor(id: string) {\n super(`Entity not found: ${id}`, 'ENTITY_NOT_FOUND', { id });\n this.name = 'EntityNotFoundError';\n }\n}\n\n/**\n * Thrown when content is not found by CID\n */\nexport class ContentNotFoundError extends ContentError {\n constructor(cid: string) {\n super(`Content not found: ${cid}`, 'CONTENT_NOT_FOUND', { cid });\n this.name = 'ContentNotFoundError';\n }\n}\n\n/**\n * Thrown when a component is not found on an entity\n */\nexport class ComponentNotFoundError extends ContentError {\n constructor(id: string, componentName: string) {\n super(\n `Component '${componentName}' not found on entity ${id}`,\n 'COMPONENT_NOT_FOUND',\n { id, componentName }\n );\n this.name = 'ComponentNotFoundError';\n }\n}\n\n/**\n * Thrown when a version is not found\n */\nexport class VersionNotFoundError extends ContentError {\n constructor(id: string, selector: string) {\n super(\n `Version not found: ${selector} for entity ${id}`,\n 'VERSION_NOT_FOUND',\n { id, selector }\n );\n this.name = 'VersionNotFoundError';\n }\n}\n\n/**\n * Thrown when a network error occurs\n */\nexport class NetworkError extends ContentError {\n constructor(message: string, public statusCode?: number) {\n super(message, 'NETWORK_ERROR', { statusCode });\n this.name = 'NetworkError';\n }\n}\n","import {\n ContentError,\n EntityNotFoundError,\n ContentNotFoundError,\n ComponentNotFoundError,\n NetworkError,\n} from './errors.js';\nimport type {\n Entity,\n EntityVersion,\n ListOptions,\n ListResponse,\n VersionsOptions,\n VersionsResponse,\n ResolveResponse,\n RelationshipsComponent,\n PropertiesComponent,\n} from './types.js';\n\n/**\n * Configuration for ContentClient\n */\nexport interface ContentClientConfig {\n /**\n * Gateway base URL (e.g., https://gateway.arke.institute).\n * The client will call /api/* endpoints for IPFS Wrapper.\n */\n gatewayUrl: string;\n /**\n * Optional custom fetch implementation (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\n/**\n * Client for accessing entities and content from the Arke archive.\n *\n * All endpoints are public and do not require authentication.\n *\n * @example\n * ```typescript\n * const content = new ContentClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get an entity\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Download content by CID\n * const blob = await content.download('bafybeihkoviema7g3gxyt6la7vd5ho32jywf7b4c4z3qtwcabpjqxwsumu');\n *\n * // Get component content\n * const pinax = await content.getComponent(entity, 'pinax');\n * ```\n */\nexport class ContentClient {\n private baseUrl: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: ContentClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n query?: Record<string, string | number | boolean | undefined>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, { ...options, headers });\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (response.ok) {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n // Handle 404 specifically\n if (response.status === 404) {\n const errorCode = (body as JsonBody)?.error;\n if (errorCode === 'NOT_FOUND' || errorCode === 'ENTITY_NOT_FOUND') {\n throw new ContentError(\n (body as JsonBody)?.message as string || 'Not found',\n 'NOT_FOUND',\n body\n );\n }\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : (body as JsonBody)?.message && typeof (body as JsonBody).message === 'string'\n ? ((body as JsonBody).message as string)\n : `Request failed with status ${response.status}`;\n\n throw new ContentError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Entity Operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get an entity by its Persistent Identifier (PI).\n *\n * @param pi - Persistent Identifier (ULID or test PI with II prefix)\n * @returns Full entity manifest\n * @throws EntityNotFoundError if the entity doesn't exist\n *\n * @example\n * ```typescript\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * console.log('Version:', entity.ver);\n * console.log('Components:', Object.keys(entity.components));\n * ```\n */\n async get(pi: string): Promise<Entity> {\n try {\n return await this.request<Entity>(`/api/entities/${encodeURIComponent(pi)}`);\n } catch (err) {\n if (err instanceof ContentError && err.code === 'NOT_FOUND') {\n throw new EntityNotFoundError(pi);\n }\n throw err;\n }\n }\n\n /**\n * List entities with pagination.\n *\n * @param options - Pagination and metadata options\n * @returns Paginated list of entity summaries\n *\n * @example\n * ```typescript\n * // Get first page\n * const page1 = await content.list({ limit: 20, include_metadata: true });\n *\n * // Get next page\n * if (page1.next_cursor) {\n * const page2 = await content.list({ cursor: page1.next_cursor });\n * }\n * ```\n */\n async list(options: ListOptions = {}): Promise<ListResponse> {\n return this.request<ListResponse>('/api/entities', {\n query: {\n limit: options.limit,\n cursor: options.cursor,\n include_metadata: options.include_metadata,\n },\n });\n }\n\n /**\n * Get version history for an entity.\n *\n * @param pi - Persistent Identifier\n * @param options - Pagination options\n * @returns Version history (newest first)\n *\n * @example\n * ```typescript\n * const history = await content.versions('01K75HQQXNTDG7BBP7PS9AWYAN');\n * console.log('Total versions:', history.items.length);\n * history.items.forEach(v => {\n * console.log(`v${v.ver}: ${v.ts} - ${v.note || 'no note'}`);\n * });\n * ```\n */\n async versions(pi: string, options: VersionsOptions = {}): Promise<VersionsResponse> {\n try {\n return await this.request<VersionsResponse>(\n `/api/entities/${encodeURIComponent(pi)}/versions`,\n {\n query: {\n limit: options.limit,\n cursor: options.cursor,\n },\n }\n );\n } catch (err) {\n if (err instanceof ContentError && err.code === 'NOT_FOUND') {\n throw new EntityNotFoundError(pi);\n }\n throw err;\n }\n }\n\n /**\n * Get a specific version of an entity.\n *\n * @param pi - Persistent Identifier\n * @param selector - Version selector: 'ver:N' for version number or 'cid:...' for CID\n * @returns Entity manifest for the specified version\n *\n * @example\n * ```typescript\n * // Get version 2\n * const v2 = await content.getVersion('01K75HQQXNTDG7BBP7PS9AWYAN', 'ver:2');\n *\n * // Get by CID\n * const vByCid = await content.getVersion('01K75HQQXNTDG7BBP7PS9AWYAN', 'cid:bafybeih...');\n * ```\n */\n async getVersion(pi: string, selector: string): Promise<Entity> {\n try {\n return await this.request<Entity>(\n `/api/entities/${encodeURIComponent(pi)}/versions/${encodeURIComponent(selector)}`\n );\n } catch (err) {\n if (err instanceof ContentError && err.code === 'NOT_FOUND') {\n throw new EntityNotFoundError(pi);\n }\n throw err;\n }\n }\n\n /**\n * Resolve a PI to its tip CID (fast lookup without fetching manifest).\n *\n * @param pi - Persistent Identifier\n * @returns PI and tip CID\n *\n * @example\n * ```typescript\n * const { tip } = await content.resolve('01K75HQQXNTDG7BBP7PS9AWYAN');\n * console.log('Latest manifest CID:', tip);\n * ```\n */\n async resolve(pi: string): Promise<ResolveResponse> {\n try {\n return await this.request<ResolveResponse>(`/api/resolve/${encodeURIComponent(pi)}`);\n } catch (err) {\n if (err instanceof ContentError && err.code === 'NOT_FOUND') {\n throw new EntityNotFoundError(pi);\n }\n throw err;\n }\n }\n\n /**\n * Get the list of child PIs for an entity (fast, returns only PIs).\n *\n * @param pi - Persistent Identifier of parent entity\n * @returns Array of child PIs\n *\n * @example\n * ```typescript\n * const childPis = await content.children('01K75HQQXNTDG7BBP7PS9AWYAN');\n * console.log('Children:', childPis);\n * ```\n */\n async children(pi: string): Promise<string[]> {\n const entity = await this.get(pi);\n return entity.children_pi || [];\n }\n\n /**\n * Get all child entities for a parent (fetches full entity for each child).\n *\n * @param pi - Persistent Identifier of parent entity\n * @returns Array of child entities\n *\n * @example\n * ```typescript\n * const childEntities = await content.childrenEntities('01K75HQQXNTDG7BBP7PS9AWYAN');\n * childEntities.forEach(child => {\n * console.log(`${child.pi}: v${child.ver}`);\n * });\n * ```\n */\n async childrenEntities(pi: string): Promise<Entity[]> {\n const childPis = await this.children(pi);\n if (childPis.length === 0) {\n return [];\n }\n\n // Fetch all children in parallel\n const results = await Promise.allSettled(\n childPis.map(childPi => this.get(childPi))\n );\n\n // Return only successful fetches\n return results\n .filter((r): r is PromiseFulfilledResult<Entity> => r.status === 'fulfilled')\n .map(r => r.value);\n }\n\n /**\n * Get the Arke origin block (root of the archive tree).\n *\n * @returns Arke origin entity\n *\n * @example\n * ```typescript\n * const origin = await content.arke();\n * console.log('Arke origin:', origin.pi);\n * ```\n */\n async arke(): Promise<Entity> {\n return this.request<Entity>('/api/arke');\n }\n\n // ---------------------------------------------------------------------------\n // Content Download\n // ---------------------------------------------------------------------------\n\n /**\n * Download content by CID.\n *\n * Returns Blob in browser environments, Buffer in Node.js.\n *\n * @param cid - Content Identifier\n * @returns Content as Blob (browser) or Buffer (Node)\n * @throws ContentNotFoundError if the content doesn't exist\n *\n * @example\n * ```typescript\n * const content = await client.download('bafybeih...');\n *\n * // In browser\n * const url = URL.createObjectURL(content as Blob);\n *\n * // In Node.js\n * fs.writeFileSync('output.bin', content as Buffer);\n * ```\n */\n async download(cid: string): Promise<Blob | Buffer> {\n const url = this.buildUrl(`/api/cat/${encodeURIComponent(cid)}`);\n\n let response: Response;\n try {\n response = await this.fetchImpl(url);\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new ContentNotFoundError(cid);\n }\n throw new ContentError(\n `Failed to download content: ${response.status}`,\n 'DOWNLOAD_ERROR',\n { status: response.status }\n );\n }\n\n // Platform-aware response handling\n if (typeof window !== 'undefined') {\n // Browser environment\n return response.blob();\n } else {\n // Node.js environment\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n }\n }\n\n /**\n * Get a direct URL for content by CID.\n *\n * This is useful for embedding in img tags or for direct downloads.\n *\n * @param cid - Content Identifier\n * @returns URL string\n *\n * @example\n * ```typescript\n * const url = content.getUrl('bafybeih...');\n * // Use in img tag: <img src={url} />\n * ```\n */\n getUrl(cid: string): string {\n return `${this.baseUrl}/api/cat/${encodeURIComponent(cid)}`;\n }\n\n /**\n * Stream content by CID.\n *\n * @param cid - Content Identifier\n * @returns ReadableStream of the content\n * @throws ContentNotFoundError if the content doesn't exist\n *\n * @example\n * ```typescript\n * const stream = await content.stream('bafybeih...');\n * const reader = stream.getReader();\n * while (true) {\n * const { done, value } = await reader.read();\n * if (done) break;\n * // Process chunk\n * }\n * ```\n */\n async stream(cid: string): Promise<ReadableStream<Uint8Array>> {\n const url = this.buildUrl(`/api/cat/${encodeURIComponent(cid)}`);\n\n let response: Response;\n try {\n response = await this.fetchImpl(url);\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new ContentNotFoundError(cid);\n }\n throw new ContentError(\n `Failed to stream content: ${response.status}`,\n 'STREAM_ERROR',\n { status: response.status }\n );\n }\n\n if (!response.body) {\n throw new ContentError('Response body is not available', 'STREAM_ERROR');\n }\n\n return response.body;\n }\n\n /**\n * Download a DAG node (JSON) by CID.\n *\n * Use this to fetch JSON components like properties and relationships.\n *\n * @param cid - Content Identifier of the DAG node\n * @returns Parsed JSON object\n * @throws ContentNotFoundError if the content doesn't exist\n *\n * @example\n * ```typescript\n * const relationships = await content.getDag<RelationshipsComponent>(\n * entity.components.relationships\n * );\n * console.log('Relationships:', relationships.relationships);\n * ```\n */\n async getDag<T = unknown>(cid: string): Promise<T> {\n const url = this.buildUrl(`/api/dag/${encodeURIComponent(cid)}`);\n\n let response: Response;\n try {\n response = await this.fetchImpl(url);\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (!response.ok) {\n if (response.status === 404) {\n throw new ContentNotFoundError(cid);\n }\n throw new ContentError(\n `Failed to fetch DAG node: ${response.status}`,\n 'DAG_ERROR',\n { status: response.status }\n );\n }\n\n return (await response.json()) as T;\n }\n\n // ---------------------------------------------------------------------------\n // Component Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Download a component from an entity.\n *\n * @param entity - Entity containing the component\n * @param componentName - Name of the component (e.g., 'pinax', 'description', 'source')\n * @returns Component content as Blob (browser) or Buffer (Node)\n * @throws ComponentNotFoundError if the component doesn't exist\n *\n * @example\n * ```typescript\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * const pinax = await content.getComponent(entity, 'pinax');\n * ```\n */\n async getComponent(entity: Entity, componentName: string): Promise<Blob | Buffer> {\n const cid = entity.components[componentName];\n if (!cid) {\n throw new ComponentNotFoundError(entity.id, componentName);\n }\n return this.download(cid);\n }\n\n /**\n * Get the URL for a component from an entity.\n *\n * @param entity - Entity containing the component\n * @param componentName - Name of the component\n * @returns URL string\n * @throws ComponentNotFoundError if the component doesn't exist\n *\n * @example\n * ```typescript\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * const imageUrl = content.getComponentUrl(entity, 'source');\n * // Use in img tag: <img src={imageUrl} />\n * ```\n */\n getComponentUrl(entity: Entity, componentName: string): string {\n const cid = entity.components[componentName];\n if (!cid) {\n throw new ComponentNotFoundError(entity.id, componentName);\n }\n return this.getUrl(cid);\n }\n\n /**\n * Get the properties component for an entity.\n *\n * @param entity - Entity containing the properties component\n * @returns Properties object, or null if no properties component exists\n *\n * @example\n * ```typescript\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * const props = await content.getProperties(entity);\n * if (props) {\n * console.log('Title:', props.title);\n * }\n * ```\n */\n async getProperties(entity: Entity): Promise<PropertiesComponent | null> {\n const cid = entity.components.properties;\n if (!cid) {\n return null;\n }\n return this.getDag<PropertiesComponent>(cid);\n }\n\n /**\n * Get the relationships component for an entity.\n *\n * @param entity - Entity containing the relationships component\n * @returns Relationships component, or null if no relationships exist\n *\n * @example\n * ```typescript\n * const entity = await content.get('01K75HQQXNTDG7BBP7PS9AWYAN');\n * const rels = await content.getRelationships(entity);\n * if (rels) {\n * rels.relationships.forEach(r => {\n * console.log(`${r.predicate} -> ${r.target_label}`);\n * });\n * }\n * ```\n */\n async getRelationships(entity: Entity): Promise<RelationshipsComponent | null> {\n const cid = entity.components.relationships;\n if (!cid) {\n return null;\n }\n return this.getDag<RelationshipsComponent>(cid);\n }\n}\n","/**\n * Graph package error classes for the Arke SDK\n */\n\n/**\n * Base error class for graph operations\n */\nexport class GraphError extends Error {\n constructor(\n message: string,\n public code: string = 'GRAPH_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'GraphError';\n }\n}\n\n/**\n * Thrown when an entity is not found by canonical ID\n */\nexport class GraphEntityNotFoundError extends GraphError {\n constructor(canonicalId: string) {\n super(`Graph entity not found: ${canonicalId}`, 'ENTITY_NOT_FOUND', { canonicalId });\n this.name = 'GraphEntityNotFoundError';\n }\n}\n\n/**\n * Thrown when no paths are found between entities\n */\nexport class NoPathFoundError extends GraphError {\n constructor(sourceIds: string[], targetIds: string[]) {\n super(\n `No path found between sources and targets`,\n 'NO_PATH_FOUND',\n { sourceIds, targetIds }\n );\n this.name = 'NoPathFoundError';\n }\n}\n\n/**\n * Thrown when a network error occurs\n */\nexport class NetworkError extends GraphError {\n constructor(message: string, public statusCode?: number) {\n super(message, 'NETWORK_ERROR', { statusCode });\n this.name = 'NetworkError';\n }\n}\n","import {\n GraphError,\n NetworkError,\n} from './errors.js';\nimport type {\n GraphEntity,\n EntityWithRelationships,\n Relationship,\n RelationshipDirection,\n Path,\n PathOptions,\n ReachableOptions,\n ListFromPiOptions,\n EntityQueryResponse,\n EntitiesWithRelationshipsResponse,\n PathsResponse,\n LineageResponse,\n} from './types.js';\n\n/**\n * Configuration for GraphClient\n */\nexport interface GraphClientConfig {\n /**\n * Gateway base URL (e.g., https://gateway.arke.institute).\n * The client will call /graphdb/* endpoints for GraphDB Gateway.\n */\n gatewayUrl: string;\n /**\n * Optional custom fetch implementation (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\n/**\n * Client for querying entity relationships and graph traversal from the Arke knowledge graph.\n *\n * The GraphDB is an indexed mirror of entity data stored in IPFS. Use this client for:\n * - **Bidirectional relationship queries** (IPFS only stores outbound relationships)\n * - **Path finding** between entities\n * - **Lineage queries** (PI ancestors/descendants)\n * - **Code-based lookups** (indexed for fast search)\n * - **Listing extracted entities** from a PI\n *\n * For entity CRUD operations, use ContentClient (source of truth in IPFS).\n * For write operations, use EditClient.\n *\n * All endpoints are public and do not require authentication.\n *\n * @example\n * ```typescript\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get BOTH inbound and outbound relationships (GraphDB indexed)\n * const allRels = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Get only inbound relationships (\"who references this entity?\")\n * const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');\n *\n * // Find paths between entities\n * const paths = await graph.findPaths(['entity-1'], ['entity-2'], { max_depth: 4 });\n *\n * // Get PI lineage\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n * ```\n */\nexport class GraphClient {\n private baseUrl: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: GraphClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n query?: Record<string, string | number | boolean | undefined>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, { ...options, headers });\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (response.ok) {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n // Handle 404 specifically\n if (response.status === 404) {\n throw new GraphError(\n (body as JsonBody)?.message as string || 'Not found',\n 'NOT_FOUND',\n body\n );\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : (body as JsonBody)?.message && typeof (body as JsonBody).message === 'string'\n ? ((body as JsonBody).message as string)\n : `Request failed with status ${response.status}`;\n\n throw new GraphError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Code-based Lookups (indexed in GraphDB)\n // ---------------------------------------------------------------------------\n\n /**\n * Query entities by code with optional type filter.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * // Find by code\n * const entities = await graph.queryByCode('person_john');\n *\n * // With type filter\n * const people = await graph.queryByCode('john', 'person');\n * ```\n */\n async queryByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<EntityQueryResponse>(\n '/graphdb/entity/query',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n\n if (!response.found || !response.entity) {\n return [];\n }\n\n return [response.entity];\n }\n\n /**\n * Look up entities by code across all PIs.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * const entities = await graph.lookupByCode('alice_austen', 'person');\n * ```\n */\n async lookupByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/lookup-by-code',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n return response.entities || [];\n }\n\n // ---------------------------------------------------------------------------\n // PI-based Operations\n // ---------------------------------------------------------------------------\n\n /**\n * List entities extracted from a specific PI or multiple PIs.\n *\n * This returns knowledge graph entities (persons, places, events, etc.)\n * that were extracted from the given PI(s), not the PI entity itself.\n *\n * @param pi - Single PI or array of PIs\n * @param options - Filter options\n * @returns Extracted entities from the PI(s)\n *\n * @example\n * ```typescript\n * // From single PI\n * const entities = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // With type filter\n * const people = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN', { type: 'person' });\n *\n * // From multiple PIs\n * const all = await graph.listEntitiesFromPi(['pi-1', 'pi-2']);\n * ```\n */\n async listEntitiesFromPi(\n pi: string | string[],\n options: ListFromPiOptions = {}\n ): Promise<GraphEntity[]> {\n const pis = Array.isArray(pi) ? pi : [pi];\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/list',\n {\n method: 'POST',\n body: JSON.stringify({\n pis,\n type: options.type,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get entities with their relationships from a PI.\n *\n * This is an optimized query that returns entities along with all their\n * relationship data in a single request.\n *\n * @param pi - Persistent Identifier\n * @param type - Optional entity type filter\n * @returns Entities with relationships\n *\n * @example\n * ```typescript\n * const entities = await graph.getEntitiesWithRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n * entities.forEach(e => {\n * console.log(`${e.label} has ${e.relationships.length} relationships`);\n * });\n * ```\n */\n async getEntitiesWithRelationships(\n pi: string,\n type?: string\n ): Promise<EntityWithRelationships[]> {\n const response = await this.request<EntitiesWithRelationshipsResponse>(\n '/graphdb/pi/entities-with-relationships',\n {\n method: 'POST',\n body: JSON.stringify({ pi, type }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get the lineage (ancestors and/or descendants) of a PI.\n *\n * This traverses the PI hierarchy (parent_pi/children_pi relationships)\n * which is indexed in GraphDB for fast lookups.\n *\n * @param pi - Source PI\n * @param direction - 'ancestors', 'descendants', or 'both'\n * @param maxHops - Maximum depth to traverse (default: 10)\n * @returns Lineage data with PIs at each hop level\n *\n * @example\n * ```typescript\n * // Get ancestors (parent chain)\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n *\n * // Get both directions\n * const full = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'both');\n * ```\n */\n async getLineage(\n pi: string,\n direction: 'ancestors' | 'descendants' | 'both' = 'both',\n maxHops: number = 10\n ): Promise<LineageResponse> {\n return this.request<LineageResponse>('/graphdb/pi/lineage', {\n method: 'POST',\n body: JSON.stringify({ sourcePi: pi, direction, maxHops }),\n });\n }\n\n // ---------------------------------------------------------------------------\n // Relationship Operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get relationships for an entity from the GraphDB index.\n *\n * **Important distinction from ContentClient.getRelationships():**\n * - **ContentClient.getRelationships()**: Returns OUTBOUND relationships only\n * (from the entity's relationships.json in IPFS - source of truth)\n * - **GraphClient.getRelationships()**: Returns BOTH inbound AND outbound\n * relationships (from the indexed GraphDB mirror)\n *\n * Use this method when you need to find \"what references this entity\" (inbound)\n * or want a complete bidirectional view.\n *\n * @param id - Entity identifier (works for both PIs and KG entities)\n * @param direction - Filter by direction: 'outgoing', 'incoming', or 'both' (default)\n * @returns Array of relationships with direction indicator\n *\n * @example\n * ```typescript\n * // Get all relationships (both directions)\n * const all = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Get only inbound relationships (\"who references this entity?\")\n * const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');\n *\n * // Get only outbound relationships (similar to IPFS, but from index)\n * const outgoing = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'outgoing');\n *\n * // Process by direction\n * const rels = await graph.getRelationships('entity-id');\n * rels.forEach(r => {\n * if (r.direction === 'incoming') {\n * console.log(`${r.target_label} references this entity via ${r.predicate}`);\n * } else {\n * console.log(`This entity ${r.predicate} -> ${r.target_label}`);\n * }\n * });\n * ```\n */\n async getRelationships(\n id: string,\n direction: RelationshipDirection = 'both'\n ): Promise<Relationship[]> {\n const response = await this.request<{\n found: boolean;\n canonical_id?: string;\n relationships?: Array<{\n direction: 'outgoing' | 'incoming';\n predicate: string;\n target_id: string;\n target_code?: string;\n target_label: string;\n target_type: string;\n properties?: Record<string, unknown>;\n source_pi?: string;\n created_at?: string;\n }>;\n }>(`/graphdb/relationships/${encodeURIComponent(id)}`);\n\n if (!response.found || !response.relationships) {\n return [];\n }\n\n let relationships = response.relationships;\n\n // Filter by direction if specified\n if (direction !== 'both') {\n relationships = relationships.filter(rel => rel.direction === direction);\n }\n\n return relationships.map(rel => ({\n direction: rel.direction,\n predicate: rel.predicate,\n target_id: rel.target_id,\n target_code: rel.target_code || '',\n target_label: rel.target_label,\n target_type: rel.target_type,\n properties: rel.properties,\n source_pi: rel.source_pi,\n created_at: rel.created_at,\n }));\n }\n\n // ---------------------------------------------------------------------------\n // Path Finding\n // ---------------------------------------------------------------------------\n\n /**\n * Find shortest paths between sets of entities.\n *\n * @param sourceIds - Starting entity IDs\n * @param targetIds - Target entity IDs\n * @param options - Path finding options\n * @returns Found paths\n *\n * @example\n * ```typescript\n * const paths = await graph.findPaths(\n * ['entity-alice'],\n * ['entity-bob'],\n * { max_depth: 4, direction: 'both' }\n * );\n *\n * paths.forEach(path => {\n * console.log(`Path of length ${path.length}:`);\n * path.edges.forEach(e => {\n * console.log(` ${e.subject_label} -[${e.predicate}]-> ${e.object_label}`);\n * });\n * });\n * ```\n */\n async findPaths(\n sourceIds: string[],\n targetIds: string[],\n options: PathOptions = {}\n ): Promise<Path[]> {\n const response = await this.request<PathsResponse>('/graphdb/paths/between', {\n method: 'POST',\n body: JSON.stringify({\n source_ids: sourceIds,\n target_ids: targetIds,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n });\n return response.paths || [];\n }\n\n /**\n * Find entities of a specific type reachable from starting entities.\n *\n * @param startIds - Starting entity IDs\n * @param targetType - Type of entities to find\n * @param options - Search options\n * @returns Reachable entities of the specified type\n *\n * @example\n * ```typescript\n * // Find all people reachable from an event\n * const people = await graph.findReachable(\n * ['event-id'],\n * 'person',\n * { max_depth: 3 }\n * );\n * ```\n */\n async findReachable(\n startIds: string[],\n targetType: string,\n options: ReachableOptions = {}\n ): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/paths/reachable',\n {\n method: 'POST',\n body: JSON.stringify({\n start_ids: startIds,\n target_type: targetType,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Check the health of the graph service.\n *\n * @returns Health status\n */\n async health(): Promise<{ status: string; service: string; version: string }> {\n return this.request('/graphdb/health', { method: 'GET' });\n }\n}\n"],"mappings":"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","names":["path","path","fs","dirPath","code","path","path","NodeScanner","BrowserScanner","fs","code","path","code","ValidationError","NetworkError","path","NetworkError","ValidationError","ValidationError","code","EntityNotFoundError","ContentNotFoundError","NetworkError","path","NetworkError","EntityNotFoundError","ContentNotFoundError","code","NetworkError","path","NetworkError","code"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/ArkeClient.ts","../src/client/config.ts","../src/client/errors.ts","../src/operations/folders.ts","../src/operations/batch.ts","../src/operations/crypto.ts"],"sourcesContent":["/**\n * Main Arke SDK Client\n *\n * Provides type-safe access to the Arke API using openapi-fetch.\n */\n\nimport createClient, { type Client } from 'openapi-fetch';\nimport type { paths } from '../generated/types.js';\nimport { ArkeClientConfig, DEFAULT_CONFIG } from './config.js';\n\nexport type ArkeApiClient = Client<paths>;\n\n/**\n * Type-safe client for the Arke API\n *\n * @example\n * ```typescript\n * const arke = new ArkeClient({ authToken: 'your-jwt-token' });\n *\n * // Create an entity\n * const { data, error } = await arke.api.POST('/entities', {\n * body: {\n * collection_id: '01ABC...',\n * type: 'document',\n * properties: { title: 'My Document' }\n * }\n * });\n *\n * // Get an entity\n * const { data } = await arke.api.GET('/entities/{id}', {\n * params: { path: { id: '01XYZ...' } }\n * });\n * ```\n */\nexport class ArkeClient {\n /**\n * The underlying openapi-fetch client with full type safety\n * Use this for all API calls: arke.api.GET, arke.api.POST, etc.\n */\n public api: ArkeApiClient;\n\n private config: ArkeClientConfig;\n\n constructor(config: ArkeClientConfig = {}) {\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n this.api = this.createClient();\n }\n\n private createClient(): ArkeApiClient {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers,\n };\n\n if (this.config.authToken) {\n headers['Authorization'] = `Bearer ${this.config.authToken}`;\n }\n\n if (this.config.network === 'test') {\n headers['X-Arke-Network'] = 'test';\n }\n\n return createClient<paths>({\n baseUrl: this.config.baseUrl ?? DEFAULT_CONFIG.baseUrl,\n headers,\n });\n }\n\n /**\n * Update the authentication token\n * Recreates the underlying client with new headers\n */\n setAuthToken(token: string): void {\n this.config.authToken = token;\n this.api = this.createClient();\n }\n\n /**\n * Clear the authentication token\n */\n clearAuthToken(): void {\n this.config.authToken = undefined;\n this.api = this.createClient();\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): Readonly<ArkeClientConfig> {\n return { ...this.config };\n }\n\n /**\n * Get the base URL\n */\n get baseUrl(): string {\n return this.config.baseUrl ?? DEFAULT_CONFIG.baseUrl;\n }\n\n /**\n * Check if client is authenticated\n */\n get isAuthenticated(): boolean {\n return !!this.config.authToken;\n }\n}\n\n/**\n * Create a new ArkeClient instance\n * Convenience function for those who prefer functional style\n */\nexport function createArkeClient(config?: ArkeClientConfig): ArkeClient {\n return new ArkeClient(config);\n}\n\n// Re-export types and errors\nexport type { ArkeClientConfig } from './config.js';\nexport * from './errors.js';\n","/**\n * SDK configuration types\n */\n\nexport interface ArkeClientConfig {\n /**\n * Base URL for the Arke API\n * @default 'https://arke-v1.arke.institute'\n */\n baseUrl?: string;\n\n /**\n * Authentication token (JWT or API key)\n */\n authToken?: string;\n\n /**\n * Network to use ('main' or 'test')\n * Test network uses 'II' prefixed IDs and isolated data\n * @default 'main'\n */\n network?: 'main' | 'test';\n\n /**\n * Callback to refresh auth token when expired\n * Called automatically on 401 responses\n */\n onTokenRefresh?: () => Promise<string>;\n\n /**\n * Custom headers to include in all requests\n */\n headers?: Record<string, string>;\n}\n\nexport const DEFAULT_CONFIG: Required<Pick<ArkeClientConfig, 'baseUrl' | 'network'>> = {\n baseUrl: 'https://arke-v1.arke.institute',\n network: 'main',\n};\n","/**\n * SDK error classes\n */\n\n/**\n * Base error class for all Arke SDK errors\n */\nexport class ArkeError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly status?: number,\n public readonly details?: unknown\n ) {\n super(message);\n this.name = 'ArkeError';\n // Maintains proper stack trace for where error was thrown\n Error.captureStackTrace?.(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n details: this.details,\n };\n }\n}\n\n/**\n * CAS (Compare-And-Swap) conflict - entity was modified by another request\n */\nexport class CASConflictError extends ArkeError {\n constructor(\n public readonly expectedTip?: string,\n public readonly actualTip?: string\n ) {\n super(\n 'Entity was modified by another request. Refresh and retry with the current tip.',\n 'CAS_CONFLICT',\n 409,\n { expectedTip, actualTip }\n );\n this.name = 'CASConflictError';\n }\n}\n\n/**\n * Resource not found\n */\nexport class NotFoundError extends ArkeError {\n constructor(resourceType: string, id: string) {\n super(`${resourceType} not found: ${id}`, 'NOT_FOUND', 404, { resourceType, id });\n this.name = 'NotFoundError';\n }\n}\n\n/**\n * Validation error - invalid request data\n */\nexport class ValidationError extends ArkeError {\n constructor(\n message: string,\n public readonly field?: string,\n details?: unknown\n ) {\n super(message, 'VALIDATION_ERROR', 400, details ?? { field });\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Authentication required or invalid\n */\nexport class AuthenticationError extends ArkeError {\n constructor(message = 'Authentication required') {\n super(message, 'AUTH_REQUIRED', 401);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Permission denied\n */\nexport class ForbiddenError extends ArkeError {\n constructor(action?: string, resource?: string) {\n const msg = action\n ? `Permission denied: ${action}${resource ? ` on ${resource}` : ''}`\n : 'Permission denied';\n super(msg, 'FORBIDDEN', 403, { action, resource });\n this.name = 'ForbiddenError';\n }\n}\n\n/**\n * Parse API error response into appropriate error class\n */\nexport function parseApiError(status: number, body: unknown): ArkeError {\n const errorBody = body as { error?: string; message?: string; details?: unknown } | null;\n const message = errorBody?.error ?? errorBody?.message ?? 'Unknown error';\n\n switch (status) {\n case 400:\n return new ValidationError(message, undefined, errorBody?.details);\n\n case 401:\n return new AuthenticationError(message);\n\n case 403:\n return new ForbiddenError(message);\n\n case 404:\n return new NotFoundError('Resource', 'unknown');\n\n case 409: {\n // Parse CAS conflict details if available\n const details = errorBody?.details as { expected?: string; actual?: string } | undefined;\n return new CASConflictError(details?.expected, details?.actual);\n }\n\n default:\n return new ArkeError(message, 'API_ERROR', status, errorBody?.details);\n }\n}\n","/**\n * Folder Operations\n *\n * High-level operations for working with folders and directory structures.\n *\n * TODO: Implement folder operations\n * - uploadDirectory: Recursively upload a local directory\n * - createFolderHierarchy: Create folder structure from paths\n * - moveFolderContents: Move files between folders\n */\n\nimport type { ArkeClient } from '../client/ArkeClient.js';\n\nexport interface UploadProgress {\n phase: 'scanning' | 'creating-folders' | 'uploading-files' | 'linking' | 'complete';\n totalFiles: number;\n completedFiles: number;\n totalFolders: number;\n completedFolders: number;\n currentFile?: string;\n}\n\nexport interface UploadDirectoryOptions {\n /** Collection to upload into */\n collectionId: string;\n /** Parent folder ID (optional - creates at root if not provided) */\n parentFolderId?: string;\n /** Progress callback */\n onProgress?: (progress: UploadProgress) => void;\n /** Max concurrent uploads */\n concurrency?: number;\n}\n\nexport interface UploadDirectoryResult {\n /** Root folder entity */\n rootFolder: unknown; // TODO: Type from generated types\n /** All created folder entities */\n folders: unknown[];\n /** All created file entities */\n files: unknown[];\n}\n\n/**\n * Folder operations helper\n *\n * @example\n * ```typescript\n * const folders = new FolderOperations(arkeClient);\n * const result = await folders.uploadDirectory('/path/to/local/folder', {\n * collectionId: '01ABC...',\n * onProgress: (p) => console.log(`${p.completedFiles}/${p.totalFiles} files`),\n * });\n * ```\n */\nexport class FolderOperations {\n constructor(private client: ArkeClient) {}\n\n /**\n * Upload a local directory to Arke\n *\n * TODO: Implement this method\n * Steps:\n * 1. Scan directory structure\n * 2. Create folder hierarchy (depth-first)\n * 3. Upload files in parallel (with concurrency limit)\n * 4. Create bidirectional relationships (folder contains file)\n */\n async uploadDirectory(\n _localPath: string,\n _options: UploadDirectoryOptions\n ): Promise<UploadDirectoryResult> {\n throw new Error('FolderOperations.uploadDirectory is not yet implemented');\n }\n}\n","/**\n * Batch Operations\n *\n * High-level operations for bulk entity and relationship management.\n *\n * TODO: Implement batch operations\n * - createEntities: Create multiple entities in parallel\n * - updateEntities: Update multiple entities in parallel\n * - createRelationships: Create multiple relationships in parallel\n */\n\nimport type { ArkeClient } from '../client/ArkeClient.js';\n\nexport interface BatchCreateOptions {\n /** Max concurrent operations */\n concurrency?: number;\n /** Continue on individual failures */\n continueOnError?: boolean;\n /** Progress callback */\n onProgress?: (completed: number, total: number) => void;\n}\n\nexport interface BatchResult<T> {\n /** Successfully completed operations */\n succeeded: T[];\n /** Failed operations with errors */\n failed: Array<{ input: unknown; error: Error }>;\n}\n\n/**\n * Batch operations helper\n *\n * @example\n * ```typescript\n * const batch = new BatchOperations(arkeClient);\n * const result = await batch.createEntities([\n * { type: 'document', properties: { title: 'Doc 1' } },\n * { type: 'document', properties: { title: 'Doc 2' } },\n * ], { concurrency: 5 });\n * ```\n */\nexport class BatchOperations {\n constructor(private client: ArkeClient) {}\n\n /**\n * Create multiple entities in parallel\n *\n * TODO: Implement this method\n */\n async createEntities(\n _entities: Array<{\n collectionId: string;\n type: string;\n properties?: Record<string, unknown>;\n }>,\n _options?: BatchCreateOptions\n ): Promise<BatchResult<unknown>> {\n throw new Error('BatchOperations.createEntities is not yet implemented');\n }\n\n /**\n * Create multiple relationships in parallel\n *\n * TODO: Implement this method\n */\n async createRelationships(\n _relationships: Array<{\n sourceId: string;\n targetId: string;\n predicate: string;\n bidirectional?: boolean;\n properties?: Record<string, unknown>;\n }>,\n _options?: BatchCreateOptions\n ): Promise<BatchResult<unknown>> {\n throw new Error('BatchOperations.createRelationships is not yet implemented');\n }\n}\n","/**\n * Crypto Operations\n *\n * Cryptographic utilities for agents and content addressing.\n *\n * TODO: Implement crypto operations\n * - generateKeyPair: Generate Ed25519 key pair for agent authentication\n * - signPayload: Sign a payload with agent private key\n * - computeCID: Compute IPFS CID for content\n */\n\n/**\n * Ed25519 key pair for agent authentication\n */\nexport interface KeyPair {\n /** Public key in base64 */\n publicKey: string;\n /** Private key in base64 (keep secret!) */\n privateKey: string;\n}\n\n/**\n * Signed payload with signature\n */\nexport interface SignedPayload {\n /** Original payload */\n payload: string;\n /** Ed25519 signature in base64 */\n signature: string;\n /** Timestamp of signature */\n timestamp: number;\n}\n\n/**\n * Crypto operations helper\n *\n * @example\n * ```typescript\n * // Generate key pair for a new agent\n * const { publicKey, privateKey } = await CryptoOperations.generateKeyPair();\n *\n * // Sign a payload\n * const signed = await CryptoOperations.signPayload(privateKey, payload);\n * ```\n */\nexport class CryptoOperations {\n /**\n * Generate an Ed25519 key pair for agent authentication\n *\n * TODO: Implement using Node.js crypto or Web Crypto API\n */\n static async generateKeyPair(): Promise<KeyPair> {\n throw new Error('CryptoOperations.generateKeyPair is not yet implemented');\n }\n\n /**\n * Sign a payload with an Ed25519 private key\n *\n * TODO: Implement signature generation\n */\n static async signPayload(_privateKey: string, _payload: string): Promise<SignedPayload> {\n throw new Error('CryptoOperations.signPayload is not yet implemented');\n }\n\n /**\n * Verify an Ed25519 signature\n *\n * TODO: Implement signature verification\n */\n static async verifySignature(\n _publicKey: string,\n _payload: string,\n _signature: string\n ): Promise<boolean> {\n throw new Error('CryptoOperations.verifySignature is not yet implemented');\n }\n\n /**\n * Compute IPFS CID for content\n *\n * TODO: Implement using multiformats library\n */\n static async computeCID(_content: Uint8Array): Promise<string> {\n throw new Error('CryptoOperations.computeCID is not yet implemented');\n }\n}\n"],"mappings":"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","names":[]}
|