@arke-institute/sdk 0.1.1 → 0.1.2

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 (41) hide show
  1. package/dist/content/index.cjs +506 -0
  2. package/dist/content/index.cjs.map +1 -0
  3. package/dist/content/index.d.cts +403 -0
  4. package/dist/content/index.d.ts +403 -0
  5. package/dist/content/index.js +473 -0
  6. package/dist/content/index.js.map +1 -0
  7. package/dist/edit/index.cjs +1029 -0
  8. package/dist/edit/index.cjs.map +1 -0
  9. package/dist/edit/index.d.cts +78 -0
  10. package/dist/edit/index.d.ts +78 -0
  11. package/dist/edit/index.js +983 -0
  12. package/dist/edit/index.js.map +1 -0
  13. package/dist/{errors-BrNZWPE7.d.cts → errors-3L7IiHcr.d.cts} +3 -0
  14. package/dist/errors-B82BMmRP.d.cts +343 -0
  15. package/dist/errors-B82BMmRP.d.ts +343 -0
  16. package/dist/{errors-CCyp5KCg.d.ts → errors-BTe8GKRQ.d.ts} +3 -0
  17. package/dist/graph/index.cjs +433 -0
  18. package/dist/graph/index.cjs.map +1 -0
  19. package/dist/graph/index.d.cts +456 -0
  20. package/dist/graph/index.d.ts +456 -0
  21. package/dist/graph/index.js +402 -0
  22. package/dist/graph/index.js.map +1 -0
  23. package/dist/index.cjs +2126 -14
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +5 -1
  26. package/dist/index.d.ts +5 -1
  27. package/dist/index.js +2108 -14
  28. package/dist/index.js.map +1 -1
  29. package/dist/query/index.cjs +289 -0
  30. package/dist/query/index.cjs.map +1 -0
  31. package/dist/query/index.d.cts +541 -0
  32. package/dist/query/index.d.ts +541 -0
  33. package/dist/query/index.js +261 -0
  34. package/dist/query/index.js.map +1 -0
  35. package/dist/upload/index.cjs +3 -14
  36. package/dist/upload/index.cjs.map +1 -1
  37. package/dist/upload/index.d.cts +2 -2
  38. package/dist/upload/index.d.ts +2 -2
  39. package/dist/upload/index.js +3 -14
  40. package/dist/upload/index.js.map +1 -1
  41. package/package.json +26 -1
@@ -0,0 +1 @@
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":[]}
@@ -328,6 +328,9 @@ declare class UploadClient {
328
328
  *
329
329
  * Requires owner or editor role on the collection containing the parent PI.
330
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.
331
334
  */
332
335
  addToCollection(options: AddToCollectionOptions): Promise<BatchResult>;
333
336
  /**
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Arke SDK - Edit Package Type Definitions
3
+ */
4
+ type EditMode = 'ai-prompt' | 'manual-with-review' | 'manual-only';
5
+ interface EditSessionConfig {
6
+ mode: EditMode;
7
+ aiReviewEnabled?: boolean;
8
+ }
9
+ interface Entity {
10
+ pi: string;
11
+ ver: number;
12
+ ts: string;
13
+ manifest_cid: string;
14
+ components: Record<string, string>;
15
+ children_pi: string[];
16
+ parent_pi?: string;
17
+ note?: string;
18
+ }
19
+ interface EntityUpdate {
20
+ expect_tip: string;
21
+ components?: Record<string, string>;
22
+ components_remove?: string[];
23
+ note: string;
24
+ }
25
+ interface EntityVersion {
26
+ pi: string;
27
+ tip: string;
28
+ ver: number;
29
+ }
30
+ type RegeneratableComponent = 'pinax' | 'description' | 'cheimarros';
31
+ interface EditScope {
32
+ components: RegeneratableComponent[];
33
+ cascade: boolean;
34
+ stopAtPi?: string;
35
+ }
36
+ interface Correction {
37
+ original: string;
38
+ corrected: string;
39
+ sourceFile?: string;
40
+ context?: string;
41
+ }
42
+ type DiffType = 'addition' | 'deletion' | 'change' | 'unchanged';
43
+ interface TextDiff {
44
+ type: DiffType;
45
+ original?: string;
46
+ modified?: string;
47
+ lineNumber?: number;
48
+ context?: string;
49
+ }
50
+ interface ComponentDiff {
51
+ componentName: string;
52
+ diffs: TextDiff[];
53
+ summary: string;
54
+ hasChanges: boolean;
55
+ }
56
+ type PromptTarget = RegeneratableComponent | 'general' | 'reorganization';
57
+ interface EntityContext {
58
+ pi: string;
59
+ ver: number;
60
+ parentPi?: string;
61
+ childrenCount: number;
62
+ currentContent: Record<string, string>;
63
+ }
64
+ interface CascadeContext {
65
+ path: string[];
66
+ depth: number;
67
+ stopAtPi?: string;
68
+ }
69
+ interface CustomPrompts {
70
+ general?: string;
71
+ pinax?: string;
72
+ description?: string;
73
+ cheimarros?: string;
74
+ reorganization?: string;
75
+ }
76
+ interface ReprocessRequest {
77
+ pi: string;
78
+ phases: RegeneratableComponent[];
79
+ cascade: boolean;
80
+ options?: {
81
+ stop_at_pi?: string;
82
+ custom_prompts?: CustomPrompts;
83
+ custom_note?: string;
84
+ };
85
+ }
86
+ interface ReprocessResult {
87
+ batch_id: string;
88
+ entities_queued: number;
89
+ entity_pis: string[];
90
+ status_url: string;
91
+ }
92
+ type ReprocessPhase = 'QUEUED' | 'DISCOVERY' | 'OCR_IN_PROGRESS' | 'REORGANIZATION' | 'PINAX_EXTRACTION' | 'CHEIMARROS_EXTRACTION' | 'DESCRIPTION' | 'DONE' | 'ERROR';
93
+ interface ReprocessProgress {
94
+ directories_total: number;
95
+ directories_pinax_complete: number;
96
+ directories_cheimarros_complete: number;
97
+ directories_description_complete: number;
98
+ }
99
+ interface ReprocessStatus {
100
+ batch_id: string;
101
+ status: ReprocessPhase;
102
+ progress: ReprocessProgress;
103
+ root_pi?: string;
104
+ error?: string;
105
+ started_at?: string;
106
+ completed_at?: string;
107
+ }
108
+ interface SaveResult {
109
+ pi: string;
110
+ newVersion: number;
111
+ newTip: string;
112
+ }
113
+ interface EditResult {
114
+ saved?: SaveResult;
115
+ reprocess?: ReprocessResult;
116
+ }
117
+ type EditPhase = 'idle' | 'saving' | 'reprocessing' | 'complete' | 'error';
118
+ interface EditStatus {
119
+ phase: EditPhase;
120
+ saveComplete: boolean;
121
+ reprocessStatus?: ReprocessStatus;
122
+ error?: string;
123
+ }
124
+ interface PollOptions {
125
+ intervalMs?: number;
126
+ timeoutMs?: number;
127
+ onProgress?: (status: EditStatus) => void;
128
+ }
129
+ interface ChangeSummary {
130
+ mode: EditMode;
131
+ hasManualEdits: boolean;
132
+ editedComponents: string[];
133
+ corrections: Correction[];
134
+ prompts: Record<string, string>;
135
+ scope: EditScope;
136
+ willRegenerate: RegeneratableComponent[];
137
+ willCascade: boolean;
138
+ willSave: boolean;
139
+ willReprocess: boolean;
140
+ }
141
+
142
+ /**
143
+ * EditClient - Low-level API client for Arke edit operations
144
+ *
145
+ * Routes through the gateway:
146
+ * - /api/* -> IPFS Wrapper (entities, content, uploads)
147
+ * - /reprocess/* -> Reprocess API
148
+ */
149
+
150
+ /** Configuration for EditClient */
151
+ interface EditClientConfig {
152
+ /** Gateway URL (e.g., https://gateway.arke.io) */
153
+ gatewayUrl: string;
154
+ /** JWT auth token */
155
+ authToken?: string;
156
+ /** Optional transform for status URLs (e.g., for CORS proxy) */
157
+ statusUrlTransform?: (url: string) => string;
158
+ }
159
+ declare class EditClient {
160
+ private gatewayUrl;
161
+ private authToken?;
162
+ private statusUrlTransform?;
163
+ constructor(config: EditClientConfig);
164
+ /**
165
+ * Update the auth token (useful for token refresh)
166
+ */
167
+ setAuthToken(token: string): void;
168
+ /**
169
+ * Sleep for a given number of milliseconds
170
+ */
171
+ private sleep;
172
+ /**
173
+ * Execute a fetch with exponential backoff retry on transient errors
174
+ */
175
+ private fetchWithRetry;
176
+ private getHeaders;
177
+ /**
178
+ * Handle common error responses
179
+ */
180
+ private handleErrorResponse;
181
+ /**
182
+ * Fetch an entity by PI
183
+ */
184
+ getEntity(pi: string): Promise<Entity>;
185
+ /**
186
+ * Fetch content by CID
187
+ */
188
+ getContent(cid: string): Promise<string>;
189
+ /**
190
+ * Upload content and get CID
191
+ */
192
+ uploadContent(content: string, filename: string): Promise<string>;
193
+ /**
194
+ * Update an entity with new components
195
+ */
196
+ updateEntity(pi: string, update: EntityUpdate): Promise<EntityVersion>;
197
+ /**
198
+ * Trigger reprocessing for an entity
199
+ */
200
+ reprocess(request: ReprocessRequest): Promise<ReprocessResult>;
201
+ /**
202
+ * Get reprocessing status by batch ID
203
+ *
204
+ * Uses exponential backoff retry to handle transient 500 errors
205
+ * that occur when the orchestrator is initializing.
206
+ *
207
+ * @param statusUrl - The status URL returned from reprocess()
208
+ * @param isFirstPoll - If true, uses a longer initial delay (orchestrator warmup)
209
+ */
210
+ getReprocessStatus(statusUrl: string, isFirstPoll?: boolean): Promise<ReprocessStatus>;
211
+ }
212
+
213
+ /**
214
+ * EditSession - Stateful session managing an edit workflow
215
+ */
216
+
217
+ declare class EditSession {
218
+ readonly pi: string;
219
+ readonly mode: EditMode;
220
+ readonly aiReviewEnabled: boolean;
221
+ private client;
222
+ private entity;
223
+ private loadedComponents;
224
+ private prompts;
225
+ private editedContent;
226
+ private corrections;
227
+ private scope;
228
+ private submitting;
229
+ private result;
230
+ private statusUrl;
231
+ constructor(client: EditClient, pi: string, config?: EditSessionConfig);
232
+ /**
233
+ * Load the entity and its key components
234
+ */
235
+ load(): Promise<void>;
236
+ /**
237
+ * Load a specific component on demand
238
+ */
239
+ loadComponent(name: string): Promise<string | undefined>;
240
+ /**
241
+ * Get the loaded entity
242
+ */
243
+ getEntity(): Entity;
244
+ /**
245
+ * Get loaded component content
246
+ */
247
+ getComponents(): Record<string, string>;
248
+ /**
249
+ * Set a prompt for AI regeneration
250
+ */
251
+ setPrompt(target: PromptTarget, prompt: string): void;
252
+ /**
253
+ * Get all prompts
254
+ */
255
+ getPrompts(): Record<string, string>;
256
+ /**
257
+ * Clear a prompt
258
+ */
259
+ clearPrompt(target: PromptTarget): void;
260
+ /**
261
+ * Set edited content for a component
262
+ */
263
+ setContent(componentName: string, content: string): void;
264
+ /**
265
+ * Get all edited content
266
+ */
267
+ getEditedContent(): Record<string, string>;
268
+ /**
269
+ * Clear edited content for a component
270
+ */
271
+ clearContent(componentName: string): void;
272
+ /**
273
+ * Add a correction (for OCR fixes, etc.)
274
+ */
275
+ addCorrection(original: string, corrected: string, sourceFile?: string): void;
276
+ /**
277
+ * Get all corrections
278
+ */
279
+ getCorrections(): Correction[];
280
+ /**
281
+ * Clear corrections
282
+ */
283
+ clearCorrections(): void;
284
+ /**
285
+ * Set the edit scope
286
+ */
287
+ setScope(scope: Partial<EditScope>): void;
288
+ /**
289
+ * Get the current scope
290
+ */
291
+ getScope(): EditScope;
292
+ /**
293
+ * Get diffs for manual changes
294
+ */
295
+ getDiff(): ComponentDiff[];
296
+ /**
297
+ * Preview what prompts will be sent to AI
298
+ */
299
+ previewPrompt(): Record<RegeneratableComponent, string>;
300
+ /**
301
+ * Get a summary of pending changes
302
+ */
303
+ getChangeSummary(): ChangeSummary;
304
+ /**
305
+ * Submit changes (saves first if manual edits, then reprocesses)
306
+ */
307
+ submit(note: string): Promise<EditResult>;
308
+ /**
309
+ * Wait for reprocessing to complete
310
+ */
311
+ waitForCompletion(options?: PollOptions): Promise<EditStatus>;
312
+ /**
313
+ * Get current status without waiting
314
+ */
315
+ getStatus(): Promise<EditStatus>;
316
+ private buildCustomPrompts;
317
+ }
318
+
319
+ /**
320
+ * Error classes for edit operations
321
+ */
322
+ declare class EditError extends Error {
323
+ code: string;
324
+ details?: unknown | undefined;
325
+ constructor(message: string, code?: string, details?: unknown | undefined);
326
+ }
327
+ declare class EntityNotFoundError extends EditError {
328
+ constructor(pi: string);
329
+ }
330
+ declare class CASConflictError extends EditError {
331
+ constructor(pi: string, expectedTip: string, actualTip: string);
332
+ }
333
+ declare class ReprocessError extends EditError {
334
+ constructor(message: string, batchId?: string);
335
+ }
336
+ declare class ValidationError extends EditError {
337
+ constructor(message: string, field?: string);
338
+ }
339
+ declare class PermissionError extends EditError {
340
+ constructor(message: string, pi?: string);
341
+ }
342
+
343
+ export { ReprocessError as A, type ComponentDiff as C, type DiffType as D, EditClient as E, PermissionError as P, type RegeneratableComponent as R, type SaveResult as S, type TextDiff as T, ValidationError as V, type EditClientConfig as a, EditSession as b, EditError as c, type EditMode as d, type EditSessionConfig as e, type EditScope as f, type EditResult as g, type EditStatus as h, type EditPhase as i, type ReprocessResult as j, type ReprocessStatus as k, type Correction as l, type EntityContext as m, type CascadeContext as n, type Entity as o, type EntityUpdate as p, type EntityVersion as q, type PromptTarget as r, type CustomPrompts as s, type ReprocessRequest as t, type ReprocessPhase as u, type ReprocessProgress as v, type PollOptions as w, type ChangeSummary as x, EntityNotFoundError as y, CASConflictError as z };