@arke-institute/sdk 0.1.2 → 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.
Files changed (64) hide show
  1. package/README.md +126 -184
  2. package/dist/generated/index.cjs +19 -0
  3. package/dist/generated/index.cjs.map +1 -0
  4. package/dist/generated/index.d.cts +6192 -0
  5. package/dist/generated/index.d.ts +6192 -0
  6. package/dist/generated/index.js +1 -0
  7. package/dist/generated/index.js.map +1 -0
  8. package/dist/index-BrXke2kI.d.ts +302 -0
  9. package/dist/index-FHcLPBSV.d.cts +302 -0
  10. package/dist/index.cjs +188 -3654
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +62 -7
  13. package/dist/index.d.ts +62 -7
  14. package/dist/index.js +168 -3626
  15. package/dist/index.js.map +1 -1
  16. package/dist/operations/index.cjs +113 -0
  17. package/dist/operations/index.cjs.map +1 -0
  18. package/dist/operations/index.d.cts +3 -0
  19. package/dist/operations/index.d.ts +3 -0
  20. package/dist/operations/index.js +84 -0
  21. package/dist/operations/index.js.map +1 -0
  22. package/package.json +44 -53
  23. package/dist/client-dAk3E64p.d.cts +0 -183
  24. package/dist/client-dAk3E64p.d.ts +0 -183
  25. package/dist/collections/index.cjs +0 -233
  26. package/dist/collections/index.cjs.map +0 -1
  27. package/dist/collections/index.d.cts +0 -9
  28. package/dist/collections/index.d.ts +0 -9
  29. package/dist/collections/index.js +0 -205
  30. package/dist/collections/index.js.map +0 -1
  31. package/dist/content/index.cjs +0 -506
  32. package/dist/content/index.cjs.map +0 -1
  33. package/dist/content/index.d.cts +0 -403
  34. package/dist/content/index.d.ts +0 -403
  35. package/dist/content/index.js +0 -473
  36. package/dist/content/index.js.map +0 -1
  37. package/dist/edit/index.cjs +0 -1029
  38. package/dist/edit/index.cjs.map +0 -1
  39. package/dist/edit/index.d.cts +0 -78
  40. package/dist/edit/index.d.ts +0 -78
  41. package/dist/edit/index.js +0 -983
  42. package/dist/edit/index.js.map +0 -1
  43. package/dist/errors-3L7IiHcr.d.cts +0 -480
  44. package/dist/errors-B82BMmRP.d.cts +0 -343
  45. package/dist/errors-B82BMmRP.d.ts +0 -343
  46. package/dist/errors-BTe8GKRQ.d.ts +0 -480
  47. package/dist/graph/index.cjs +0 -433
  48. package/dist/graph/index.cjs.map +0 -1
  49. package/dist/graph/index.d.cts +0 -456
  50. package/dist/graph/index.d.ts +0 -456
  51. package/dist/graph/index.js +0 -402
  52. package/dist/graph/index.js.map +0 -1
  53. package/dist/query/index.cjs +0 -289
  54. package/dist/query/index.cjs.map +0 -1
  55. package/dist/query/index.d.cts +0 -541
  56. package/dist/query/index.d.ts +0 -541
  57. package/dist/query/index.js +0 -261
  58. package/dist/query/index.js.map +0 -1
  59. package/dist/upload/index.cjs +0 -1634
  60. package/dist/upload/index.cjs.map +0 -1
  61. package/dist/upload/index.d.cts +0 -150
  62. package/dist/upload/index.d.ts +0 -150
  63. package/dist/upload/index.js +0 -1597
  64. package/dist/upload/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/edit/errors.ts","../../src/edit/client.ts","../../src/edit/diff.ts","../../src/edit/prompts.ts","../../src/edit/session.ts"],"sourcesContent":["/**\n * Error classes for edit operations\n */\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\nexport class EntityNotFoundError extends EditError {\n constructor(pi: string) {\n super(`Entity not found: ${pi}`, 'ENTITY_NOT_FOUND', { pi });\n this.name = 'EntityNotFoundError';\n }\n}\n\nexport class CASConflictError extends EditError {\n constructor(pi: string, expectedTip: string, actualTip: string) {\n super(\n `CAS conflict: entity ${pi} was modified (expected ${expectedTip}, got ${actualTip})`,\n 'CAS_CONFLICT',\n { pi, expectedTip, actualTip }\n );\n this.name = 'CASConflictError';\n }\n}\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\nexport class ValidationError extends EditError {\n constructor(message: string, field?: string) {\n super(message, 'VALIDATION_ERROR', { field });\n this.name = 'ValidationError';\n }\n}\n\nexport class PermissionError extends EditError {\n constructor(message: string, pi?: string) {\n super(message, 'PERMISSION_DENIED', { pi });\n this.name = 'PermissionError';\n }\n}\n","/**\n * EditClient - Low-level API client for Arke edit operations\n *\n * Routes through the gateway:\n * - /api/* -> IPFS Wrapper (entities, content, uploads)\n * - /reprocess/* -> Reprocess API\n */\n\nimport type {\n Entity,\n EntityUpdate,\n EntityVersion,\n ReprocessRequest,\n ReprocessResult,\n ReprocessStatus,\n} from './types';\nimport {\n EditError,\n EntityNotFoundError,\n CASConflictError,\n ReprocessError,\n PermissionError,\n} from './errors';\n\n/** Configuration for EditClient */\nexport interface EditClientConfig {\n /** Gateway URL (e.g., https://gateway.arke.io) */\n gatewayUrl: string;\n /** JWT auth token */\n authToken?: string;\n /** Optional transform for status URLs (e.g., for CORS proxy) */\n statusUrlTransform?: (url: string) => string;\n}\n\n/** Default retry options for status polling */\nconst DEFAULT_RETRY_OPTIONS = {\n maxRetries: 5,\n initialDelayMs: 2000, // Start with 2s delay (orchestrator needs time to initialize)\n maxDelayMs: 30000, // Cap at 30s\n backoffMultiplier: 2, // Double each retry\n};\n\nexport class EditClient {\n private gatewayUrl: string;\n private authToken?: string;\n private statusUrlTransform?: (url: string) => string;\n\n constructor(config: EditClientConfig) {\n this.gatewayUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.authToken = config.authToken;\n this.statusUrlTransform = config.statusUrlTransform;\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 * Sleep for a given number of milliseconds\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\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 retryOptions = DEFAULT_RETRY_OPTIONS\n ): Promise<Response> {\n let lastError: Error | null = null;\n let delay = retryOptions.initialDelayMs;\n\n for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) {\n try {\n const response = await fetch(url, options);\n\n // Retry on 5xx errors (server errors)\n if (response.status >= 500 && attempt < retryOptions.maxRetries) {\n lastError = new Error(`Server error: ${response.status} ${response.statusText}`);\n await this.sleep(delay);\n delay = Math.min(delay * retryOptions.backoffMultiplier, retryOptions.maxDelayMs);\n continue;\n }\n\n return response;\n } catch (error) {\n // Network errors - retry\n lastError = error as Error;\n if (attempt < retryOptions.maxRetries) {\n await this.sleep(delay);\n delay = Math.min(delay * retryOptions.backoffMultiplier, retryOptions.maxDelayMs);\n }\n }\n }\n\n throw lastError || new Error('Request failed after retries');\n }\n\n private getHeaders(): HeadersInit {\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n return headers;\n }\n\n /**\n * Handle common error responses\n */\n private handleErrorResponse(response: Response, context: string): never {\n if (response.status === 403) {\n throw new PermissionError(`Permission denied: ${context}`);\n }\n throw new EditError(\n `${context}: ${response.statusText}`,\n 'API_ERROR',\n { status: response.status }\n );\n }\n\n // ===========================================================================\n // IPFS Wrapper Operations (via /api/*)\n // ===========================================================================\n\n /**\n * Fetch an entity by PI\n */\n async getEntity(pi: string): Promise<Entity> {\n const response = await fetch(`${this.gatewayUrl}/api/entities/${pi}`, {\n headers: this.getHeaders(),\n });\n\n if (response.status === 404) {\n throw new EntityNotFoundError(pi);\n }\n\n if (!response.ok) {\n this.handleErrorResponse(response, `Failed to fetch entity ${pi}`);\n }\n\n return response.json();\n }\n\n /**\n * Fetch content by CID\n */\n async getContent(cid: string): Promise<string> {\n const response = await fetch(`${this.gatewayUrl}/api/cat/${cid}`, {\n headers: this.getHeaders(),\n });\n\n if (!response.ok) {\n this.handleErrorResponse(response, `Failed to fetch content ${cid}`);\n }\n\n return response.text();\n }\n\n /**\n * Upload content and get CID\n */\n async uploadContent(content: string, filename: string): Promise<string> {\n const formData = new FormData();\n const blob = new Blob([content], { type: 'text/plain' });\n formData.append('file', blob, filename);\n\n const headers: HeadersInit = {};\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n\n const response = await fetch(`${this.gatewayUrl}/api/upload`, {\n method: 'POST',\n headers,\n body: formData,\n });\n\n if (!response.ok) {\n this.handleErrorResponse(response, 'Failed to upload content');\n }\n\n const result = await response.json();\n // Response format: [{ cid, name, size }]\n return result[0].cid;\n }\n\n /**\n * Update an entity with new components\n */\n async updateEntity(pi: string, update: EntityUpdate): Promise<EntityVersion> {\n const response = await fetch(`${this.gatewayUrl}/api/entities/${pi}/versions`, {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify({\n expect_tip: update.expect_tip,\n components: update.components,\n components_remove: update.components_remove,\n note: update.note,\n }),\n });\n\n if (response.status === 409) {\n // CAS conflict - entity was modified\n const entity = await this.getEntity(pi);\n throw new CASConflictError(\n pi,\n update.expect_tip,\n entity.manifest_cid\n );\n }\n\n if (!response.ok) {\n this.handleErrorResponse(response, `Failed to update entity ${pi}`);\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 fetch(`${this.gatewayUrl}/reprocess/reprocess`, {\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\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(\n error.message || `Reprocess failed: ${response.statusText}`,\n undefined\n );\n }\n\n return response.json();\n }\n\n /**\n * Get reprocessing status by batch ID\n *\n * Uses exponential backoff retry to handle transient 500 errors\n * that occur when the orchestrator is initializing.\n *\n * @param statusUrl - The status URL returned from reprocess()\n * @param isFirstPoll - If true, uses a longer initial delay (orchestrator warmup)\n */\n async getReprocessStatus(statusUrl: string, isFirstPoll = false): Promise<ReprocessStatus> {\n // Use longer initial delay for first poll after triggering reprocess\n const retryOptions = isFirstPoll\n ? { ...DEFAULT_RETRY_OPTIONS, initialDelayMs: 3000 }\n : DEFAULT_RETRY_OPTIONS;\n\n // Apply URL transform if configured (for CORS proxy)\n const fetchUrl = this.statusUrlTransform ? this.statusUrlTransform(statusUrl) : statusUrl;\n\n const response = await this.fetchWithRetry(\n fetchUrl,\n { headers: this.getHeaders() },\n retryOptions\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 * 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.pi,\n ver: this.entity.ver,\n parentPi: this.entity.parent_pi,\n childrenCount: this.entity.children_pi.length,\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.pi, 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.pi,\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"],"mappings":"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","names":[]}
@@ -1,480 +0,0 @@
1
- import { f as CreateCollectionPayload, b as Collection, o as PiPermissions, C as CollectionsClient } from './client-dAk3E64p.cjs';
2
-
3
- /**
4
- * Processing configuration types for per-directory control
5
- */
6
- /**
7
- * Configuration for processing stages applied to files
8
- */
9
- interface ProcessingConfig {
10
- /** Enable OCR on eligible files */
11
- ocr: boolean;
12
- /** Enable description/summary generation */
13
- describe: boolean;
14
- /** Enable pinax metadata generation */
15
- pinax: boolean;
16
- }
17
-
18
- /**
19
- * SDK Configuration Types
20
- */
21
-
22
- /**
23
- * Custom prompts for AI services in the ingest pipeline
24
- * All fields are optional. Prompts are appended to base system prompts.
25
- */
26
- interface CustomPrompts {
27
- /**
28
- * Applied to all AI service calls across all phases
29
- * @example "All content is from 18th century manuscripts. Use period-appropriate terminology."
30
- */
31
- general?: string;
32
- /**
33
- * Phase-specific: file reorganization
34
- * @example "Group documents by subject matter (astronomy, biology, chemistry, physics)."
35
- */
36
- reorganization?: string;
37
- /**
38
- * Phase-specific: PINAX metadata extraction
39
- * @example "Focus on extracting dates, locations, and institutional affiliations. Use Library of Congress Subject Headings."
40
- */
41
- pinax?: string;
42
- /**
43
- * Phase-specific: description generation
44
- * @example "Write descriptions in scholarly, academic tone with focus on historical context."
45
- */
46
- description?: string;
47
- /**
48
- * Phase-specific: knowledge graph extraction
49
- * @example "Focus on extracting people, institutions, and their relationships."
50
- */
51
- cheimarros?: string;
52
- }
53
- /**
54
- * Configuration for the ArkeUploader SDK
55
- */
56
- interface UploaderConfig {
57
- /**
58
- * Gateway base URL (e.g., https://api.arke.institute)
59
- * All requests route through /ingest/* endpoints
60
- * @example 'https://api.arke.institute'
61
- */
62
- gatewayUrl: string;
63
- /**
64
- * Bearer token for authentication (required for all upload operations)
65
- */
66
- authToken: string;
67
- /**
68
- * Name of person/service uploading files
69
- */
70
- uploader: string;
71
- /**
72
- * Root path in the archive hierarchy
73
- * @default '/'
74
- */
75
- rootPath?: string;
76
- /**
77
- * Parent persistent identifier (for hierarchical archives)
78
- */
79
- parentPi?: string;
80
- /**
81
- * Custom metadata to attach to batch
82
- */
83
- metadata?: Record<string, unknown>;
84
- /**
85
- * Custom prompts for AI services in the ingest pipeline
86
- */
87
- customPrompts?: CustomPrompts;
88
- /**
89
- * Processing options (OCR, IIIF, etc.)
90
- */
91
- processing?: ProcessingConfig;
92
- /**
93
- * Number of files to upload in parallel
94
- * @default 5
95
- */
96
- parallelUploads?: number;
97
- /**
98
- * Number of parts to upload in parallel for multipart uploads
99
- * @default 3
100
- */
101
- parallelParts?: number;
102
- /**
103
- * Maximum number of retry attempts for failed requests
104
- * @default 3
105
- */
106
- maxRetries?: number;
107
- /**
108
- * Initial delay between retries in milliseconds
109
- * @default 1000
110
- */
111
- retryInitialDelay?: number;
112
- /**
113
- * Maximum delay between retries in milliseconds
114
- * @default 30000
115
- */
116
- retryMaxDelay?: number;
117
- /**
118
- * Add random jitter to retry delays to prevent thundering herd
119
- * @default true
120
- */
121
- retryJitter?: boolean;
122
- /**
123
- * Timeout for API requests in milliseconds
124
- * @default 30000
125
- */
126
- timeout?: number;
127
- }
128
- /**
129
- * Options for batch upload operation
130
- */
131
- interface UploadOptions {
132
- /**
133
- * Progress callback for upload tracking
134
- */
135
- onProgress?: (progress: UploadProgress) => void;
136
- /**
137
- * Dry run mode - validate without uploading
138
- * @default false
139
- */
140
- dryRun?: boolean;
141
- }
142
- /**
143
- * Progress information during upload
144
- */
145
- interface UploadProgress {
146
- /**
147
- * Current phase of upload
148
- */
149
- phase: 'scanning' | 'uploading' | 'finalizing' | 'discovery' | 'complete';
150
- /**
151
- * Total number of files to upload
152
- */
153
- filesTotal: number;
154
- /**
155
- * Number of files uploaded so far
156
- */
157
- filesUploaded: number;
158
- /**
159
- * Total bytes to upload
160
- */
161
- bytesTotal: number;
162
- /**
163
- * Bytes uploaded so far
164
- */
165
- bytesUploaded: number;
166
- /**
167
- * Current file being processed
168
- */
169
- currentFile?: string;
170
- /**
171
- * Percentage complete (0-100)
172
- */
173
- percentComplete: number;
174
- }
175
- /**
176
- * Result of batch upload
177
- */
178
- interface BatchResult {
179
- /**
180
- * Batch ID assigned by worker
181
- */
182
- batchId: string;
183
- /**
184
- * Root PI of the uploaded content (entity identifier)
185
- * This is the canonical identifier for the uploaded collection.
186
- */
187
- rootPi: string;
188
- /**
189
- * Number of files uploaded
190
- */
191
- filesUploaded: number;
192
- /**
193
- * Total bytes uploaded
194
- */
195
- bytesUploaded: number;
196
- /**
197
- * Upload duration in milliseconds
198
- */
199
- durationMs: number;
200
- }
201
-
202
- /**
203
- * Upload Client with Collections Integration
204
- * Provides high-level upload operations with permission checks
205
- */
206
-
207
- interface UploadClientConfig {
208
- /**
209
- * Gateway base URL (e.g., https://api.arke.institute)
210
- */
211
- gatewayUrl: string;
212
- /**
213
- * Bearer token for authentication
214
- */
215
- authToken: string;
216
- /**
217
- * Name of person/service uploading files (defaults to user ID from JWT)
218
- */
219
- uploader?: string;
220
- /**
221
- * Custom fetch implementation (optional, for testing)
222
- */
223
- fetchImpl?: typeof fetch;
224
- }
225
- interface CreateCollectionUploadOptions {
226
- /**
227
- * Files to upload - directory path (Node.js) or File[]/FileList (browser)
228
- */
229
- files: string | File[] | FileList;
230
- /**
231
- * Collection metadata
232
- */
233
- collectionMetadata: CreateCollectionPayload;
234
- /**
235
- * Custom prompts for AI processing
236
- */
237
- customPrompts?: CustomPrompts;
238
- /**
239
- * Processing options (OCR, IIIF, etc.)
240
- */
241
- processing?: ProcessingConfig;
242
- /**
243
- * Progress callback
244
- */
245
- onProgress?: (progress: UploadProgress) => void;
246
- /**
247
- * Dry run mode
248
- */
249
- dryRun?: boolean;
250
- }
251
- interface AddToCollectionOptions {
252
- /**
253
- * Files to upload - directory path (Node.js) or File[]/FileList (browser)
254
- */
255
- files: string | File[] | FileList;
256
- /**
257
- * Parent PI to add files under (must be within a collection you can edit)
258
- */
259
- parentPi: string;
260
- /**
261
- * Custom prompts for AI processing
262
- */
263
- customPrompts?: CustomPrompts;
264
- /**
265
- * Processing options (OCR, IIIF, etc.)
266
- */
267
- processing?: ProcessingConfig;
268
- /**
269
- * Progress callback
270
- */
271
- onProgress?: (progress: UploadProgress) => void;
272
- /**
273
- * Dry run mode
274
- */
275
- dryRun?: boolean;
276
- }
277
- interface CreateCollectionUploadResult extends BatchResult {
278
- /**
279
- * The created collection
280
- */
281
- collection: Collection & {
282
- rootPi: string;
283
- };
284
- }
285
- /**
286
- * High-level upload client with collections integration
287
- *
288
- * @example
289
- * ```typescript
290
- * import { UploadClient } from '@arke-institute/sdk';
291
- *
292
- * const client = new UploadClient({
293
- * gatewayUrl: 'https://api.arke.institute',
294
- * authToken: 'your-jwt-token',
295
- * uploader: 'my-app',
296
- * });
297
- *
298
- * // Create a new collection from files
299
- * const result = await client.createCollection({
300
- * files: './photos',
301
- * collectionMetadata: { title: 'My Archive', slug: 'my-archive' },
302
- * });
303
- *
304
- * // Add files to an existing collection
305
- * await client.addToCollection({
306
- * files: './more-photos',
307
- * parentPi: result.collection.rootPi,
308
- * });
309
- * ```
310
- */
311
- declare class UploadClient {
312
- private config;
313
- private collectionsClient;
314
- constructor(config: UploadClientConfig);
315
- /**
316
- * Update the auth token (e.g., after token refresh)
317
- */
318
- setAuthToken(token: string): void;
319
- /**
320
- * Create a new collection and upload files to it
321
- *
322
- * Anyone authenticated can create a new collection.
323
- * The root PI of the uploaded files becomes the collection's root.
324
- */
325
- createCollection(options: CreateCollectionUploadOptions): Promise<CreateCollectionUploadResult>;
326
- /**
327
- * Add files to an existing collection
328
- *
329
- * Requires owner or editor role on the collection containing the parent PI.
330
- * Use this to add a folder or files to an existing collection hierarchy.
331
- *
332
- * Note: Permission checks are enforced server-side by the ingest worker.
333
- * The server will return 403 if the user lacks edit access to the parent PI.
334
- */
335
- addToCollection(options: AddToCollectionOptions): Promise<BatchResult>;
336
- /**
337
- * Check if you can edit a specific PI (i.e., add files to its collection)
338
- */
339
- canEdit(pi: string): Promise<PiPermissions>;
340
- /**
341
- * Get access to the underlying collections client for other operations
342
- */
343
- get collections(): CollectionsClient;
344
- }
345
-
346
- /**
347
- * File metadata and upload tracking types
348
- */
349
-
350
- interface FileInfo {
351
- /** Absolute path on local filesystem */
352
- localPath: string;
353
- /** Logical path within the batch (e.g., /series_1/box_7/page_001.tiff) */
354
- logicalPath: string;
355
- /** File name only */
356
- fileName: string;
357
- /** File size in bytes */
358
- size: number;
359
- /** MIME type */
360
- contentType: string;
361
- /** IPFS CID v1 (base32) - optional, may be undefined if computation failed */
362
- cid?: string;
363
- /** Processing configuration for this file */
364
- processingConfig: ProcessingConfig;
365
- }
366
- interface UploadTask extends FileInfo {
367
- /** Current status of the upload */
368
- status: 'pending' | 'uploading' | 'completed' | 'failed';
369
- /** R2 key assigned by worker */
370
- r2Key?: string;
371
- /** Upload type determined by worker */
372
- uploadType?: 'simple' | 'multipart';
373
- /** Multipart upload ID (if applicable) */
374
- uploadId?: string;
375
- /** Completed parts for multipart uploads */
376
- completedParts?: Array<{
377
- part_number: number;
378
- etag: string;
379
- }>;
380
- /** Error message if failed */
381
- error?: string;
382
- /** Bytes uploaded so far */
383
- bytesUploaded?: number;
384
- /** Timestamp when upload started */
385
- startedAt?: Date;
386
- /** Timestamp when upload completed */
387
- completedAt?: Date;
388
- }
389
- interface ScanResult {
390
- files: FileInfo[];
391
- totalSize: number;
392
- totalFiles: number;
393
- largestFile: number;
394
- smallestFile: number;
395
- }
396
-
397
- /**
398
- * Common platform types and utilities
399
- */
400
-
401
- /**
402
- * Platform-specific file source
403
- * Can be a path string (Node.js) or File object (Browser)
404
- */
405
- type FileSource = string | File;
406
-
407
- /**
408
- * Main ArkeUploader SDK class
409
- */
410
-
411
- /**
412
- * Upload client for Arke Institute's ingest service
413
- * Works in Node.js, browsers, and other JavaScript runtimes
414
- */
415
- declare class ArkeUploader {
416
- private config;
417
- private workerClient;
418
- private scanner;
419
- private platform;
420
- constructor(config: UploaderConfig);
421
- /**
422
- * Get platform-specific scanner
423
- */
424
- private getScanner;
425
- /**
426
- * Upload a batch of files
427
- * @param source - Directory path (Node.js) or File[]/FileList (browser)
428
- * @param options - Upload options
429
- */
430
- uploadBatch(source: FileSource | FileSource[], options?: UploadOptions): Promise<BatchResult>;
431
- /**
432
- * Poll for root_pi during async discovery
433
- */
434
- private pollForRootPi;
435
- /**
436
- * Upload files with controlled concurrency
437
- */
438
- private uploadFilesWithConcurrency;
439
- /**
440
- * Upload a single file
441
- */
442
- private uploadSingleFile;
443
- /**
444
- * Get file data based on platform
445
- */
446
- private getFileData;
447
- /**
448
- * Report progress to callback
449
- */
450
- private reportProgress;
451
- }
452
-
453
- /**
454
- * Custom error classes for better error handling
455
- */
456
- declare class WorkerAPIError extends Error {
457
- statusCode?: number | undefined;
458
- details?: any | undefined;
459
- constructor(message: string, statusCode?: number | undefined, details?: any | undefined);
460
- }
461
- declare class UploadError extends Error {
462
- fileName?: string | undefined;
463
- statusCode?: number | undefined;
464
- cause?: Error | undefined;
465
- constructor(message: string, fileName?: string | undefined, statusCode?: number | undefined, cause?: Error | undefined);
466
- }
467
- declare class ValidationError extends Error {
468
- field?: string | undefined;
469
- constructor(message: string, field?: string | undefined);
470
- }
471
- declare class NetworkError extends Error {
472
- cause?: Error | undefined;
473
- constructor(message: string, cause?: Error | undefined);
474
- }
475
- declare class ScanError extends Error {
476
- path?: string | undefined;
477
- constructor(message: string, path?: string | undefined);
478
- }
479
-
480
- export { type AddToCollectionOptions as A, type BatchResult as B, type CreateCollectionUploadOptions as C, type FileInfo as F, NetworkError as N, type ProcessingConfig as P, ScanError as S, UploadClient as U, ValidationError as V, WorkerAPIError as W, type UploadClientConfig as a, type CreateCollectionUploadResult as b, ArkeUploader as c, type UploaderConfig as d, type UploadOptions as e, type UploadProgress as f, type CustomPrompts as g, UploadError as h, type UploadTask as i, type ScanResult as j };