@utaba/deep-memory-storage-cosmosdb 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/CosmosDbProvider.ts","../src/CosmosDbConnection.ts","../src/mapping.ts","../src/queries/repository.ts","../src/queries/vocabulary.ts","../src/queries/entity.ts","../src/queries/relationship.ts","../src/queries/traversal.ts","../src/queries/timeline.ts","../src/queries/bulk.ts"],"sourcesContent":["// CosmosDbProvider — CosmosDB Gremlin implementation of StorageProvider + GraphTraversalProvider\n\nimport type { StorageProvider, EnsureSchemaResult } from '@utaba/deep-memory/providers';\nimport type { GraphTraversalProvider, GraphTraversalCapabilities } from '@utaba/deep-memory/providers';\nimport type {\n StoredEntity,\n StoredEntityUpdate,\n StoredRelationship,\n RelationshipQueryOptions,\n MemoryVocabulary,\n VocabularyChangeRecord,\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n StorageFindQuery,\n StorageExploreOptions,\n StoragePathOptions,\n StorageTimelineOptions,\n PaginationOptions,\n PaginatedResult,\n StorageNeighbourhood,\n StoragePathResult,\n StorageTimelineResult,\n BulkImportResult,\n TraversalSpec,\n TraversalResult,\n QueryMetadata,\n} from '@utaba/deep-memory/types';\nimport type { ExportChunk, ImportChunk, BulkImportOptions, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport crypto from 'node:crypto';\nimport { GremlinCompiler, ProviderError } from '@utaba/deep-memory';\nimport { CosmosDbConnection } from './CosmosDbConnection.js';\nimport { entityFromGremlin } from './mapping.js';\nimport * as repoQueries from './queries/repository.js';\nimport * as vocabQueries from './queries/vocabulary.js';\nimport * as entityQueries from './queries/entity.js';\nimport * as relQueries from './queries/relationship.js';\nimport * as traversalQueries from './queries/traversal.js';\nimport * as timelineQueries from './queries/timeline.js';\nimport * as bulkQueries from './queries/bulk.js';\n\n/** Configuration for CosmosDbProvider. */\nexport interface CosmosDbProviderConfig {\n /** Gremlin WebSocket endpoint (e.g. ws://host.docker.internal:8901/) */\n endpoint: string;\n /** CosmosDB REST endpoint for database/container provisioning (e.g. https://host.docker.internal:8081/) — derived from Gremlin endpoint if omitted */\n restEndpoint?: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Partition key path (default: /repositoryId) */\n partitionKey?: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nconst SCHEMA_VERSION = 1;\nconst META_VERTEX_ID = '_meta:schema';\n\n/**\n * CosmosDB Gremlin storage provider for deep-memory.\n * Implements both StorageProvider (full CRUD) and GraphTraversalProvider (native Gremlin traversals).\n */\nexport class CosmosDbProvider implements StorageProvider, GraphTraversalProvider {\n private readonly conn: CosmosDbConnection;\n private readonly config: CosmosDbProviderConfig;\n private readonly compiler = new GremlinCompiler();\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.conn = new CosmosDbConnection({\n endpoint: config.endpoint,\n key: config.key,\n database: config.database,\n container: config.container,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n rejectUnauthorized: config.rejectUnauthorized,\n });\n }\n\n // ─── Lifecycle ─────────────────────────────────────────────────────\n\n async initialise(): Promise<void> {\n await this.conn.connect();\n }\n\n async dispose(): Promise<void> {\n await this.conn.close();\n }\n\n async ensureSchema(): Promise<EnsureSchemaResult> {\n const restBase = this.getRestEndpoint();\n const partitionKey = this.config.partitionKey ?? '/repositoryId';\n let databaseCreated = false;\n let schemaCreated = false;\n\n try {\n // 1. Create database if not exists\n const dbCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n 'dbs',\n '',\n 'dbs',\n { id: this.config.database },\n this.config.rejectUnauthorized ?? true,\n );\n databaseCreated = dbCreated;\n\n // 2. Create Gremlin graph container if not exists\n const containerCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n `dbs/${this.config.database}/colls`,\n `dbs/${this.config.database}`,\n 'colls',\n {\n id: this.config.container,\n partitionKey: { paths: [partitionKey], kind: 'Hash' },\n },\n this.config.rejectUnauthorized ?? true,\n );\n schemaCreated = containerCreated;\n\n // 3. Reconnect Gremlin client (it may have failed before db/container existed)\n await this.conn.close();\n await this.conn.connect();\n\n // 4. Write schema version meta vertex\n const existing = await this.conn.submit(\n \"g.V().has('id', metaId).hasLabel('_meta').valueMap(true)\",\n { metaId: META_VERTEX_ID },\n );\n\n if (existing.items.length > 0) {\n const props = existing.items[0] as Record<string, unknown>;\n const version = Number(unwrapGremlinValue(props['schemaVersion']) ?? 0);\n if (version >= SCHEMA_VERSION && !databaseCreated && !schemaCreated) {\n return {\n databaseCreated: false,\n schemaCreated: false,\n alreadyUpToDate: true,\n schemaVersion: SCHEMA_VERSION,\n };\n }\n await this.conn.submit(\n \"g.V().has('id', metaId).hasLabel('_meta').property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, ver: SCHEMA_VERSION },\n );\n } else {\n await this.conn.submit(\n \"g.addV('_meta').property('id', metaId).property('repositoryId', pk).property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, pk: '_system', ver: SCHEMA_VERSION },\n );\n schemaCreated = true;\n }\n\n return {\n databaseCreated,\n schemaCreated,\n alreadyUpToDate: !databaseCreated && !schemaCreated,\n schemaVersion: SCHEMA_VERSION,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Failed to ensure CosmosDB schema: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the CosmosDB REST endpoint is accessible and the Gremlin endpoint is reachable.',\n );\n }\n }\n\n /** Derive the REST endpoint from config — either explicit or from the Gremlin endpoint host. */\n private getRestEndpoint(): string {\n if (this.config.restEndpoint) return this.config.restEndpoint.replace(/\\/+$/, '');\n // Derive from Gremlin endpoint: ws(s)://host:port/ → https://host:8081\n const url = new URL(this.config.endpoint);\n return `https://${url.hostname}:8081`;\n }\n\n // ─── Repository ────────────────────────────────────────────────────\n\n async createRepository(config: StorageRepositoryConfig): Promise<StoredRepository> {\n return repoQueries.createRepository(this.conn, config);\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n return repoQueries.getRepository(this.conn, repositoryId);\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return repoQueries.listRepositories(this.conn, filter);\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n return repoQueries.updateRepository(this.conn, repositoryId, updates);\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n return repoQueries.deleteRepository(this.conn, repositoryId, onProgress);\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n return repoQueries.deleteAllContents(this.conn, repositoryId, onProgress);\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n return repoQueries.getRepositoryStats(this.conn, repositoryId);\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n return vocabQueries.getVocabulary(this.conn, repositoryId);\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n return vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary);\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n return vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options);\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n return entityQueries.createEntity(this.conn, repositoryId, entity);\n }\n\n async getEntity(repositoryId: string, entityId: string): Promise<StoredEntity | null> {\n return entityQueries.getEntity(this.conn, repositoryId, entityId);\n }\n\n async getEntityBySlug(repositoryId: string, slug: string): Promise<StoredEntity | null> {\n return entityQueries.getEntityBySlug(this.conn, repositoryId, slug);\n }\n\n async getEntities(repositoryId: string, entityIds: string[]): Promise<Map<string, StoredEntity>> {\n return entityQueries.getEntities(this.conn, repositoryId, entityIds);\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n return entityQueries.updateEntity(this.conn, repositoryId, entityId, updates);\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n return entityQueries.deleteEntity(this.conn, repositoryId, entityId);\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n return entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType);\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery): Promise<PaginatedResult<StoredEntity>> {\n return entityQueries.findEntities(this.conn, repositoryId, query);\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n return relQueries.createRelationship(this.conn, repositoryId, relationship);\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n return relQueries.getRelationship(this.conn, repositoryId, relationshipId);\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n return relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options);\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n return relQueries.deleteRelationship(this.conn, repositoryId, relationshipId);\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n return relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType);\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighbourhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighbourhood> {\n return traversalQueries.exploreNeighbourhood(this.conn, repositoryId, entityId, options);\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n return traversalQueries.findPaths(this.conn, repositoryId, sourceId, targetId, options);\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n return timelineQueries.getTimeline(this.conn, repositoryId, entityId, options);\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n return bulkQueries.exportAll(this.conn, repositoryId);\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n return bulkQueries.importBulk(this.conn, repositoryId, data, options);\n }\n\n // ─── GraphTraversalProvider ────────────────────────────────────────\n\n getCapabilities(): GraphTraversalCapabilities {\n return {\n supportsNativeQuery: true,\n nativeQueryLanguage: 'gremlin',\n maxTraversalDepth: 10,\n supportsRelationshipPropertyFilters: true,\n supportsEntityPropertyFilters: true,\n supportsAggregation: false,\n supportsRepeat: true,\n supportsDedup: true,\n supportsRelationshipSummary: false,\n };\n }\n\n async traverse(\n repositoryId: string,\n spec: TraversalSpec,\n compiledQuery?: string,\n ): Promise<TraversalResult> {\n const startTime = Date.now();\n\n // Get vocabulary for compilation\n const vocabulary = await this.getVocabulary(repositoryId);\n\n // Compile the spec to Gremlin if no compiled query provided\n const compiled = compiledQuery\n ? { query: compiledQuery, params: {}, estimatedFanOut: 100 }\n : this.compiler.compile(spec, vocabulary);\n\n // Inject repositoryId filter into the query\n // The compiled query starts with g.V(), we need to add repository scoping\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n `g.V().has('repositoryId', '${repositoryId}')`,\n );\n\n try {\n const result = await this.conn.submit(scopedQuery, compiled.params);\n const executionTimeMs = Date.now() - startTime;\n\n const entities: TraversalResult['entities'] = [];\n const relationships: NonNullable<TraversalResult['relationships']> = [];\n const paths: NonNullable<TraversalResult['paths']> = [];\n\n if (spec.returnMode === 'path') {\n // Path results need special parsing\n for (const item of result.items) {\n const pathData = item as { objects?: unknown[] };\n if (pathData.objects) {\n const pathEntities: TraversalResult['entities'] = [];\n for (const obj of pathData.objects) {\n const props = obj as Record<string, unknown>;\n if (props['entityType']) {\n pathEntities.push(entityFromGremlin(props));\n }\n }\n if (pathEntities.length > 0) {\n paths.push({\n length: pathEntities.length - 1,\n entities: pathEntities,\n relationships: [],\n });\n }\n }\n }\n } else {\n // Entity results from valueMap(true)\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n entities.push(entity);\n }\n }\n\n const limit = spec.limit ?? 50;\n const queryMetadata: QueryMetadata = {\n executionTimeMs,\n resourceCost: result.requestCharge != null\n ? { units: 'RU', value: result.requestCharge }\n : undefined,\n compiledQuery: scopedQuery,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: {\n maxResults: limit,\n maxDepth: spec.steps?.length,\n },\n truncated: entities.length >= limit,\n truncationReason: entities.length >= limit ? 'result_limit' : undefined,\n };\n\n return {\n entities: spec.returnMode === 'path' ? [] : entities,\n relationships: spec.returnMode === 'path' || spec.returnMode === 'all' ? relationships : undefined,\n paths: spec.returnMode === 'path' ? paths : undefined,\n total: entities.length + paths.length,\n returned: entities.length + paths.length,\n hasMore: entities.length >= limit || paths.length >= limit,\n queryMetadata,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Gremlin traversal failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Check the traversal spec and ensure the CosmosDB connection is healthy.',\n );\n }\n }\n\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<TraversalResult> {\n const startTime = Date.now();\n\n try {\n const result = await this.conn.submit(query, params);\n const executionTimeMs = Date.now() - startTime;\n\n // Best-effort entity mapping from raw results\n const entities: TraversalResult['entities'] = [];\n for (const item of result.items) {\n try {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n if (entity.id) {\n entities.push(entity);\n }\n } catch {\n // Non-entity results are skipped\n }\n }\n\n const queryMetadata: QueryMetadata = {\n executionTimeMs,\n resourceCost: result.requestCharge != null\n ? { units: 'RU', value: result.requestCharge }\n : undefined,\n compiledQuery: query,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: { maxResults: entities.length },\n truncated: false,\n };\n\n return {\n entities,\n total: entities.length,\n returned: entities.length,\n hasMore: false,\n queryMetadata,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Native Gremlin query failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the Gremlin query syntax is valid for CosmosDB.',\n );\n }\n }\n}\n\nfunction unwrapGremlinValue(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n// ─── CosmosDB REST API helpers for database/container provisioning ──\n\n/**\n * Generate a CosmosDB REST API authorization token.\n * See: https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources\n */\nfunction cosmosAuthToken(\n verb: string,\n resourceType: string,\n resourceLink: string,\n date: string,\n key: string,\n): string {\n const payload = `${verb.toLowerCase()}\\n${resourceType.toLowerCase()}\\n${resourceLink}\\n${date.toLowerCase()}\\n\\n`;\n const keyBuffer = Buffer.from(key, 'base64');\n const hmac = crypto.createHmac('sha256', keyBuffer);\n hmac.update(payload);\n const signature = hmac.digest('base64');\n return encodeURIComponent(`type=master&ver=1.0&sig=${signature}`);\n}\n\n/**\n * Create a CosmosDB resource (database or container) via REST API.\n * Returns true if the resource was created, false if it already existed.\n */\nasync function cosmosRestPut(\n restBase: string,\n key: string,\n urlPath: string,\n resourceLink: string,\n resourceType: string,\n body: Record<string, unknown>,\n rejectUnauthorized: boolean,\n): Promise<boolean> {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', resourceType, resourceLink, date, key);\n\n const url = `${restBase}/${urlPath}`;\n\n // Use Node's native fetch (available in Node 18+)\n const options: RequestInit & { dispatcher?: unknown } = {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n\n // For self-signed certs (emulator), we need to disable TLS verification\n if (!rejectUnauthorized) {\n // Use Node.js undici agent to skip TLS verification\n try {\n // @ts-expect-error — Node 18+ fetch supports dispatcher for TLS options\n options.dispatcher = new (await import('undici')).Agent({\n connect: { rejectUnauthorized: false },\n });\n } catch {\n // If undici is not available, set NODE_TLS_REJECT_UNAUTHORIZED as fallback\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n }\n\n const response = await fetch(url, options);\n\n if (response.status === 201) return true; // Created\n if (response.status === 409) return false; // Already exists\n\n const text = await response.text();\n throw new Error(`CosmosDB REST ${response.status}: ${text}`);\n}\n","// CosmosDbConnection — Gremlin client wrapper for CosmosDB\n//\n// Handles WebSocket connection, CosmosDB authentication, TLS for emulator,\n// and retry logic for transient errors (429 throttling, 503 unavailable).\n\n// @ts-expect-error — gremlin has no type declarations\nimport gremlin from 'gremlin';\n\nexport interface CosmosDbConnectionConfig {\n /** Gremlin WebSocket endpoint (e.g. wss://localhost:8901/) */\n endpoint: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nexport interface GremlinResult {\n /** Raw result items */\n items: unknown[];\n /** CosmosDB request charge (RU) from response headers */\n requestCharge?: number;\n}\n\n/**\n * Manages a Gremlin WebSocket connection to CosmosDB.\n * Provides `submit()` for parameterized Gremlin queries with retry on transient errors.\n */\nexport class CosmosDbConnection {\n private client: gremlin.driver.Client | null = null;\n private readonly config: Required<Pick<CosmosDbConnectionConfig, 'maxRetries' | 'defaultTimeoutMs' | 'rejectUnauthorized'>> & CosmosDbConnectionConfig;\n\n constructor(config: CosmosDbConnectionConfig) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n };\n }\n\n /** Open the WebSocket connection to CosmosDB Gremlin endpoint. */\n async connect(): Promise<void> {\n if (this.client) return;\n\n const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n );\n\n this.client = new gremlin.driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: this.config.rejectUnauthorized,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n /** Close the WebSocket connection. */\n async close(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n /**\n * Submit a parameterized Gremlin query with retry on transient errors.\n * All user values should be passed as bindings (never interpolated into the query string).\n */\n async submit(query: string, bindings?: Record<string, unknown>): Promise<GremlinResult> {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const resultSet = await this.client.submit(query, bindings);\n const items = resultSet.toArray();\n const requestCharge = extractRequestCharge(resultSet);\n return { items, requestCharge };\n } catch (err: unknown) {\n lastError = err;\n if (isTransientError(err) && attempt < this.config.maxRetries) {\n const retryAfterMs = getRetryAfterMs(err, attempt);\n await sleep(retryAfterMs);\n continue;\n }\n throw err;\n }\n }\n throw lastError;\n }\n\n /** Get the underlying Gremlin client (for advanced usage). */\n getClient(): gremlin.driver.Client {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n return this.client;\n }\n}\n\n/** Check if an error is a transient CosmosDB error (429 or 503). */\nfunction isTransientError(err: unknown): boolean {\n if (err instanceof Error) {\n const msg = err.message;\n // CosmosDB returns status codes in error messages\n if (msg.includes('429') || msg.includes('RequestRateTooLarge')) return true;\n if (msg.includes('503') || msg.includes('ServiceUnavailable')) return true;\n }\n // Check statusCode property if present\n const statusCode = (err as Record<string, unknown>)?.['statusCode'];\n if (statusCode === 429 || statusCode === 503) return true;\n return false;\n}\n\n/** Extract retry-after from error or use exponential backoff. */\nfunction getRetryAfterMs(err: unknown, attempt: number): number {\n // CosmosDB may include x-ms-retry-after-ms in error attributes\n const retryAfter = (err as Record<string, unknown>)?.['retryAfterMs'];\n if (typeof retryAfter === 'number' && retryAfter > 0) {\n return retryAfter;\n }\n // Exponential backoff: 500ms, 1s, 2s, 4s, ...\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\n/** Extract request charge (RU) from a ResultSet's attributes. */\nfunction extractRequestCharge(resultSet: gremlin.driver.ResultSet): number | undefined {\n const attrs = resultSet.attributes as Record<string, unknown> | undefined;\n if (!attrs) return undefined;\n const charge = attrs['x-ms-request-charge'] ?? attrs['x-ms-total-request-charge'];\n return typeof charge === 'number' ? charge : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Mapping — convert between Gremlin results and StoredEntity/StoredRelationship types\n\nimport type { StoredEntity } from '@utaba/deep-memory/types';\nimport type { StoredRelationship } from '@utaba/deep-memory/types';\nimport type { Provenance } from '@utaba/deep-memory/types';\nimport type { StoredRepository, StoredRepositorySummary } from '@utaba/deep-memory/types';\nimport type { GovernanceConfig } from '@utaba/deep-memory/types';\nimport type { VocabularyChangeRecord, MemoryVocabulary } from '@utaba/deep-memory/types';\n\n// ─── Gremlin property extraction ──────────────────────────────────\n\n/**\n * Gremlin valueMap(true) returns properties as arrays (multi-value).\n * CosmosDB single-cardinality means each array has exactly one element.\n * This helper unwraps the first value.\n */\nfunction unwrap(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/** Safely unwrap a string value from a Gremlin result. */\nfunction unwrapStr(val: unknown): string {\n const v = unwrap(val);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\n/** Safely unwrap an optional string. */\nfunction unwrapOptStr(val: unknown): string | undefined {\n const v = unwrap(val);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\n/** Safely parse JSON, returning a default on failure. */\nfunction safeParseJson<T>(val: unknown, fallback: T): T {\n if (val == null) return fallback;\n const str = typeof val === 'string' ? val : String(unwrap(val));\n if (!str || str === '') return fallback;\n try {\n return JSON.parse(str) as T;\n } catch {\n return fallback;\n }\n}\n\n// ─── Provenance ───────────────────────────────────────────────────\n\nfunction provenanceFromGremlin(props: Record<string, unknown>): Provenance {\n return {\n createdBy: unwrapStr(props['createdBy']),\n createdByType: (unwrapStr(props['createdByType']) || 'agent') as 'user' | 'agent',\n createdAt: unwrapStr(props['createdAt']),\n createdInConversation: unwrapOptStr(props['createdInConversation']),\n createdFromMessage: unwrapOptStr(props['createdFromMessage']),\n modifiedBy: unwrapStr(props['modifiedBy']),\n modifiedByType: (unwrapStr(props['modifiedByType']) || 'agent') as 'user' | 'agent',\n modifiedAt: unwrapStr(props['modifiedAt']),\n modifiedInConversation: unwrapOptStr(props['modifiedInConversation']),\n modifiedFromMessage: unwrapOptStr(props['modifiedFromMessage']),\n };\n}\n\n// ─── Entity mapping ───────────────────────────────────────────────\n\nexport function entityFromGremlin(props: Record<string, unknown>): StoredEntity {\n const embeddingStr = unwrapOptStr(props['embedding']);\n return {\n id: unwrapStr(props['id']),\n slug: unwrapStr(props['slug']),\n entityType: unwrapStr(props['entityType']),\n label: unwrapStr(props['entityLabel']),\n summary: unwrapOptStr(props['summary']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n data: unwrapOptStr(props['data']),\n dataFormat: unwrapOptStr(props['dataFormat']),\n provenance: provenanceFromGremlin(props),\n embedding: embeddingStr ? (safeParseJson<number[] | undefined>(embeddingStr, undefined)) : undefined,\n };\n}\n\n// ─── Relationship mapping ─────────────────────────────────────────\n\nexport function relationshipFromGremlin(props: Record<string, unknown>): StoredRelationship {\n const bidir = unwrap(props['bidirectional']);\n return {\n id: unwrapStr(props['id']),\n relationshipType: unwrapStr(props['relationshipType']),\n sourceEntityId: unwrapStr(props['sourceEntityId']),\n targetEntityId: unwrapStr(props['targetEntityId']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n bidirectional: bidir === true || bidir === 'true',\n provenance: provenanceFromGremlin(props),\n };\n}\n\n// ─── Repository mapping ───────────────────────────────────────────\n\nexport function repositoryFromGremlin(props: Record<string, unknown>): StoredRepository {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n legal: unwrapOptStr(props['legal']),\n owner: unwrapOptStr(props['owner']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n metadata: safeParseJson(unwrap(props['metadata']), undefined),\n createdAt: unwrapStr(props['createdAt']),\n createdBy: unwrapStr(props['createdBy']),\n };\n}\n\nexport function repositorySummaryFromGremlin(props: Record<string, unknown>): StoredRepositorySummary {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n };\n}\n\n// ─── Vocabulary mapping ───────────────────────────────────────────\n\nexport function vocabularyFromGremlin(props: Record<string, unknown>): MemoryVocabulary {\n return safeParseJson<MemoryVocabulary>(unwrap(props['vocabulary']), {\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n });\n}\n\nexport function changeRecordFromGremlin(props: Record<string, unknown>): VocabularyChangeRecord {\n return {\n changeId: unwrapStr(props['changeId']),\n changeType: unwrapStr(props['changeType']) as VocabularyChangeRecord['changeType'],\n typeName: unwrapStr(props['typeName']),\n previousVersion: unwrapOptStr(props['previousVersion']),\n newVersion: unwrapStr(props['newVersion']),\n proposedBy: unwrapStr(props['proposedBy']),\n proposedAt: unwrapStr(props['proposedAt']),\n approvedBy: unwrapOptStr(props['approvedBy']),\n approvedAt: unwrapOptStr(props['approvedAt']),\n reason: unwrapStr(props['reason']),\n };\n}\n\n// ─── Property serialization helpers ───────────────────────────────\n\n/** Build a flat property map for a vertex from a StoredEntity. */\nexport function entityToGremlinProps(\n repositoryId: string,\n entity: StoredEntity,\n): Record<string, string | number | boolean> {\n const props: Record<string, string | number | boolean> = {\n repositoryId,\n entityType: entity.entityType,\n entityLabel: entity.label,\n slug: entity.slug,\n properties: JSON.stringify(entity.properties ?? {}),\n createdBy: entity.provenance.createdBy,\n createdByType: entity.provenance.createdByType,\n createdAt: entity.provenance.createdAt,\n modifiedBy: entity.provenance.modifiedBy,\n modifiedByType: entity.provenance.modifiedByType,\n modifiedAt: entity.provenance.modifiedAt,\n };\n if (entity.summary != null) props['summary'] = entity.summary;\n if (entity.data != null) props['data'] = entity.data;\n if (entity.dataFormat != null) props['dataFormat'] = entity.dataFormat;\n if (entity.provenance.createdInConversation != null) props['createdInConversation'] = entity.provenance.createdInConversation;\n if (entity.provenance.createdFromMessage != null) props['createdFromMessage'] = entity.provenance.createdFromMessage;\n if (entity.provenance.modifiedInConversation != null) props['modifiedInConversation'] = entity.provenance.modifiedInConversation;\n if (entity.provenance.modifiedFromMessage != null) props['modifiedFromMessage'] = entity.provenance.modifiedFromMessage;\n if (entity.embedding != null) props['embedding'] = JSON.stringify(entity.embedding);\n return props;\n}\n\n/** Build a flat property map for an edge from a StoredRelationship. */\nexport function relationshipToGremlinProps(\n repositoryId: string,\n rel: StoredRelationship,\n): Record<string, string | number | boolean> {\n const props: Record<string, string | number | boolean> = {\n repositoryId,\n relationshipType: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n bidirectional: rel.bidirectional,\n properties: JSON.stringify(rel.properties ?? {}),\n createdBy: rel.provenance.createdBy,\n createdByType: rel.provenance.createdByType,\n createdAt: rel.provenance.createdAt,\n modifiedBy: rel.provenance.modifiedBy,\n modifiedByType: rel.provenance.modifiedByType,\n modifiedAt: rel.provenance.modifiedAt,\n };\n if (rel.provenance.createdInConversation != null) props['createdInConversation'] = rel.provenance.createdInConversation;\n if (rel.provenance.createdFromMessage != null) props['createdFromMessage'] = rel.provenance.createdFromMessage;\n if (rel.provenance.modifiedInConversation != null) props['modifiedInConversation'] = rel.provenance.modifiedInConversation;\n if (rel.provenance.modifiedFromMessage != null) props['modifiedFromMessage'] = rel.provenance.modifiedFromMessage;\n return props;\n}\n","// Repository CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n} from '@utaba/deep-memory/types';\nimport type { PaginatedResult, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport { repositoryFromGremlin, repositorySummaryFromGremlin } from '../mapping.js';\nimport { DuplicateRepositoryError, RepositoryNotFoundError } from '@utaba/deep-memory';\n\nconst REPO_LABEL = '_repository';\n\nfunction repoVertexId(repositoryId: string): string {\n return `repo:${repositoryId}`;\n}\n\n/** Build a .property() chain for Gremlin vertex creation/update. */\nfunction propertyChain(bindings: Record<string, unknown>, props: Record<string, string | number | boolean | null | undefined>, startIndex: number): { chain: string; nextIndex: number } {\n const parts: string[] = [];\n let idx = startIndex;\n for (const [key, value] of Object.entries(props)) {\n if (value == null) continue;\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n parts.push(`.property('${key}', ${paramName})`);\n }\n return { chain: parts.join(''), nextIndex: idx };\n}\n\nexport async function createRepository(\n conn: CosmosDbConnection,\n config: StorageRepositoryConfig,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(config.repositoryId);\n\n // Check for existing\n const existing = await conn.submit(\n \"g.V().has('id', vid).has('label', lbl).count()\",\n { vid: vertexId, lbl: REPO_LABEL },\n );\n if (existing.items.length > 0 && Number(existing.items[0]) > 0) {\n throw new DuplicateRepositoryError(config.repositoryId);\n }\n\n const bindings: Record<string, unknown> = {\n vid: vertexId,\n rid: config.repositoryId,\n };\n\n const props: Record<string, string | number | boolean | null | undefined> = {\n repoLabel: config.label,\n description: config.description,\n type: config.type,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: JSON.stringify(config.governanceConfig),\n metadata: config.metadata ? JSON.stringify(config.metadata) : undefined,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n\n const { chain } = propertyChain(bindings, props, 0);\n\n const query = `g.addV('${REPO_LABEL}').property('id', vid).property('repositoryId', rid)${chain}`;\n await conn.submit(query, bindings);\n\n return {\n repositoryId: config.repositoryId,\n type: config.type,\n label: config.label,\n description: config.description,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: config.governanceConfig,\n metadata: config.metadata,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n}\n\nexport async function getRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<StoredRepository | null> {\n const result = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_repository').valueMap(true)\",\n { vid: repoVertexId(repositoryId) },\n );\n if (result.items.length === 0) return null;\n return repositoryFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function listRepositories(\n conn: CosmosDbConnection,\n filter?: RepositoryFilter,\n): Promise<PaginatedResult<StoredRepositorySummary>> {\n const limit = filter?.limit ?? 20;\n const offset = filter?.offset ?? 0;\n\n let countQuery = \"g.V().hasLabel('_repository')\";\n let dataQuery = \"g.V().hasLabel('_repository')\";\n const bindings: Record<string, unknown> = {};\n\n if (filter?.type) {\n countQuery += \".has('type', filterType)\";\n dataQuery += \".has('type', filterType)\";\n bindings['filterType'] = filter.type;\n }\n\n const countResult = await conn.submit(`${countQuery}.count()`, bindings);\n const total = Number(countResult.items[0] ?? 0);\n\n bindings['rangeStart'] = offset;\n bindings['rangeEnd'] = offset + limit;\n const dataResult = await conn.submit(\n `${dataQuery}.range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n const items = (dataResult.items as Record<string, unknown>[]).map(repositorySummaryFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n\nexport async function updateRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n updates: RepositoryUpdate,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(repositoryId);\n\n // Verify exists\n const existing = await getRepository(conn, repositoryId);\n if (!existing) throw new RepositoryNotFoundError(repositoryId);\n\n const bindings: Record<string, unknown> = { vid: vertexId };\n const props: Record<string, string | number | boolean | null | undefined> = {};\n\n if (updates.label !== undefined) props['repoLabel'] = updates.label;\n if (updates.description !== undefined) props['description'] = updates.description;\n if (updates.type !== undefined) props['type'] = updates.type;\n if (updates.legal !== undefined) props['legal'] = updates.legal;\n if (updates.owner !== undefined) props['owner'] = updates.owner;\n if (updates.governanceConfig !== undefined) props['governanceConfig'] = JSON.stringify(updates.governanceConfig);\n if (updates.metadata !== undefined) {\n // Shallow merge with existing metadata\n const merged = { ...existing.metadata, ...updates.metadata };\n props['metadata'] = JSON.stringify(merged);\n }\n\n if (Object.keys(props).length === 0) return existing;\n\n const { chain } = propertyChain(bindings, props, 0);\n const query = `g.V().has('id', vid).hasLabel('_repository')${chain}`;\n await conn.submit(query, bindings);\n\n return (await getRepository(conn, repositoryId))!;\n}\n\nconst DELETE_BATCH_SIZE = 500;\n\nexport async function deleteRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<void> {\n // Get totals for progress reporting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then all vertices, in batches.\n // A single unbounded drop() times out on large repositories.\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n}\n\nexport async function deleteAllContents(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count before deleting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then entity vertices, in batches.\n // Preserves system vertices (_repository, _vocabulary).\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n return { deletedEntities: totalEntities, deletedRelationships: totalRelationships };\n}\n\nexport async function getRepositoryStats(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<RepositoryStats> {\n // Get vocabulary version\n const vocabResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabulary').values('vocabulary')\",\n { rid: repositoryId },\n );\n let vocabVersion = '0.0.0';\n if (vocabResult.items.length > 0) {\n try {\n const vocab = JSON.parse(vocabResult.items[0] as string);\n vocabVersion = vocab.version ?? '0.0.0';\n } catch { /* default */ }\n }\n\n // Count entities by type (exclude system vertices)\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').group().by('entityType').by(count())\",\n { rid: repositoryId },\n );\n const entityTypeBreakdown: Record<string, number> = {};\n let entityCount = 0;\n if (entityResult.items.length > 0) {\n const grouped = entityResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n entityTypeBreakdown[type] = Number(count);\n entityCount += Number(count);\n }\n }\n\n // Count relationships by type\n const relResult = await conn.submit(\n \"g.E().has('repositoryId', rid).group().by('relationshipType').by(count())\",\n { rid: repositoryId },\n );\n const relationshipTypeBreakdown: Record<string, number> = {};\n let relationshipCount = 0;\n if (relResult.items.length > 0) {\n const grouped = relResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n relationshipTypeBreakdown[type] = Number(count);\n relationshipCount += Number(count);\n }\n }\n\n return {\n entityCount,\n relationshipCount,\n vocabularyVersion: vocabVersion,\n entityTypeBreakdown,\n relationshipTypeBreakdown,\n };\n}\n","// Vocabulary Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { MemoryVocabulary, VocabularyChangeRecord } from '@utaba/deep-memory/types';\nimport type { PaginationOptions, PaginatedResult } from '@utaba/deep-memory/types';\nimport { vocabularyFromGremlin, changeRecordFromGremlin } from '../mapping.js';\n\nfunction vocabVertexId(repositoryId: string): string {\n return `vocab:${repositoryId}`;\n}\n\nexport async function getVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<MemoryVocabulary> {\n const result = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').valueMap(true)\",\n { vid: vocabVertexId(repositoryId) },\n );\n if (result.items.length === 0) {\n // Return default empty vocabulary\n return {\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n };\n }\n return vocabularyFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function saveVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n vocabulary: MemoryVocabulary,\n): Promise<void> {\n const vid = vocabVertexId(repositoryId);\n const vocabJson = JSON.stringify(vocabulary);\n\n // Upsert: try to update existing, create if not found\n const existing = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').count()\",\n { vid },\n );\n\n if (Number(existing.items[0] ?? 0) > 0) {\n await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').property('vocabulary', vocabJson)\",\n { vid, vocabJson },\n );\n } else {\n await conn.submit(\n \"g.addV('_vocabulary').property('id', vid).property('repositoryId', rid).property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n }\n}\n\nexport async function getVocabularyChangeLog(\n conn: CosmosDbConnection,\n repositoryId: string,\n options?: PaginationOptions,\n): Promise<PaginatedResult<VocabularyChangeRecord>> {\n const limit = options?.limit ?? 10;\n const offset = options?.offset ?? 0;\n\n const countResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').count()\",\n { rid: repositoryId },\n );\n const total = Number(countResult.items[0] ?? 0);\n\n const dataResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').order().by('proposedAt', decr).range(rangeStart, rangeEnd).valueMap(true)\",\n { rid: repositoryId, rangeStart: offset, rangeEnd: offset + limit },\n );\n\n const items = (dataResult.items as Record<string, unknown>[]).map(changeRecordFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n","// Entity CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredEntity, StoredEntityUpdate } from '@utaba/deep-memory/types';\nimport type { StorageFindQuery, PaginatedResult } from '@utaba/deep-memory/types';\nimport { entityFromGremlin, entityToGremlinProps } from '../mapping.js';\nimport { DuplicateEntityError } from '@utaba/deep-memory';\n\nexport async function createEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<StoredEntity> {\n // Check for duplicate\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).count()\",\n { rid: repositoryId, eid: entity.id },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n throw new DuplicateEntityError(entity.id);\n }\n\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = { vid: entity.id };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // Use entityType as the vertex label for Gremlin graph semantics\n bindings['vertexLabel'] = entity.entityType;\n const query = `g.addV(vertexLabel).property('id', vid)${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return entity;\n}\n\nexport async function getEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap(true)\",\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityBySlug(\n conn: CosmosDbConnection,\n repositoryId: string,\n slug: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('slug', slugVal).has('entityType').valueMap(true)\",\n { rid: repositoryId, slugVal: slug },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityIds: string[],\n): Promise<Map<string, StoredEntity>> {\n if (entityIds.length === 0) return new Map();\n\n // Build within() clause with individual params\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n entityIds.forEach((id, i) => {\n const paramName = `eid${i}`;\n bindings[paramName] = id;\n idParams.push(paramName);\n });\n\n const withinClause = `within(${idParams.join(', ')})`;\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${withinClause}).has('entityType').valueMap(true)`,\n bindings,\n );\n\n const map = new Map<string, StoredEntity>();\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n map.set(entity.id, entity);\n }\n return map;\n}\n\nexport async function updateEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n updates: StoredEntityUpdate,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n const propParts: string[] = [];\n let idx = 0;\n\n const addProp = (key: string, value: string | number | boolean) => {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n };\n\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat !== undefined) addProp('dataFormat', updates.dataFormat);\n if (updates.embedding !== undefined) addProp('embedding', JSON.stringify(updates.embedding));\n\n // Provenance\n addProp('modifiedBy', updates.provenance.modifiedBy);\n addProp('modifiedByType', updates.provenance.modifiedByType);\n addProp('modifiedAt', updates.provenance.modifiedAt);\n if (updates.provenance.modifiedInConversation != null) addProp('modifiedInConversation', updates.provenance.modifiedInConversation);\n if (updates.provenance.modifiedFromMessage != null) addProp('modifiedFromMessage', updates.provenance.modifiedFromMessage);\n\n const query = `g.V().has('repositoryId', rid).has('id', eid).has('entityType')${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return (await getEntity(conn, repositoryId, entityId))!;\n}\n\nexport async function deleteEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<void> {\n // Gremlin drop() on a vertex also drops connected edges\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').drop()\",\n { rid: repositoryId, eid: entityId },\n );\n}\n\nexport async function deleteEntitiesByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityType: string,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count entities of this type\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).count()\",\n { rid: repositoryId, etype: entityType },\n );\n const deletedEntities = Number(entityCountResult.items[0] ?? 0);\n\n // Count relationships connected to these entities\n const relCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).bothE().dedup().count()\",\n { rid: repositoryId, etype: entityType },\n );\n const deletedRelationships = Number(relCountResult.items[0] ?? 0);\n\n // Drop the vertices (and their edges)\n if (deletedEntities > 0) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).drop()\",\n { rid: repositoryId, etype: entityType },\n );\n }\n\n return { deletedEntities, deletedRelationships };\n}\n\nexport async function findEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n query: StorageFindQuery,\n): Promise<PaginatedResult<StoredEntity>> {\n const bindings: Record<string, unknown> = { rid: repositoryId };\n let filterClause = \".has('repositoryId', rid).has('entityType')\";\n\n // Entity type filter\n if (query.entityTypes && query.entityTypes.length > 0) {\n const typeParams: string[] = [];\n query.entityTypes.forEach((t, i) => {\n const paramName = `etype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n filterClause += `.has('entityType', within(${typeParams.join(', ')}))`;\n }\n\n // Search term filter — case-insensitive via TextP.containing() (limited in CosmosDB)\n if (query.searchTerm) {\n bindings['searchTerm'] = query.searchTerm.toLowerCase();\n // CosmosDB Gremlin doesn't have case-insensitive text matching natively.\n // We filter on the server with containing() on entityLabel, then post-filter for case.\n // Since slugs are lowercase, search on slug as a workaround for case-insensitive match.\n filterClause += \".has('slug', containing(searchTerm))\";\n }\n\n // Property filters — stored as JSON in Gremlin, so handled via post-filtering below\n\n // Count\n const countResult = await conn.submit(\n `g.V()${filterClause}.count()`,\n bindings,\n );\n const total = Number(countResult.items[0] ?? 0);\n\n // Data\n bindings['rangeStart'] = query.offset;\n bindings['rangeEnd'] = query.offset + query.limit;\n const dataResult = await conn.submit(\n `g.V()${filterClause}.range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n let items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\n\n // Post-filter for property matches (stored as JSON)\n if (query.properties && Object.keys(query.properties).length > 0) {\n items = items.filter(entity => {\n for (const [key, value] of Object.entries(query.properties!)) {\n if (entity.properties[key] !== value) return false;\n }\n return true;\n });\n }\n\n return {\n items,\n total,\n hasMore: query.offset + query.limit < total,\n limit: query.limit,\n offset: query.offset,\n };\n}\n","// Relationship CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredRelationship, RelationshipQueryOptions } from '@utaba/deep-memory/types';\nimport type { PaginatedResult } from '@utaba/deep-memory/types';\nimport { relationshipFromGremlin, relationshipToGremlinProps } from '../mapping.js';\nimport { DuplicateRelationshipError, matchesPropertyFilters } from '@utaba/deep-memory';\n\nexport async function createRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationship: StoredRelationship,\n): Promise<StoredRelationship> {\n // Check for duplicate\n const existing = await conn.submit(\n \"g.E().has('id', relId).count()\",\n { relId: relationship.id },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n throw new DuplicateRelationshipError(relationship.id);\n }\n\n const props = relationshipToGremlinProps(repositoryId, relationship);\n const bindings: Record<string, unknown> = {\n relId: relationship.id,\n srcId: relationship.sourceEntityId,\n tgtId: relationship.targetEntityId,\n rid: repositoryId,\n edgeLabel: relationship.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // addE requires source and target vertex references\n const query = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return relationship;\n}\n\nexport async function getRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<StoredRelationship | null> {\n const result = await conn.submit(\n \"g.E().has('id', relId).has('repositoryId', rid).valueMap(true)\",\n { relId: relationshipId, rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return relationshipFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityRelationships(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: RelationshipQueryOptions,\n): Promise<PaginatedResult<StoredRelationship>> {\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n const direction = options?.direction ?? 'both';\n\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n eid: entityId,\n };\n\n // Build edge traversal based on direction\n let edgeTraversal: string;\n switch (direction) {\n case 'outbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').outE()\";\n break;\n case 'inbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').inE()\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n break;\n }\n\n // Filter by relationship types\n let typeFilter = '';\n if (options?.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n // For bidirectional support in outbound/inbound:\n // When direction is 'outbound', include inbound edges that are bidirectional\n // When direction is 'inbound', include outbound edges that are bidirectional\n // This requires a union approach.\n let unionQuery: string | null = null;\n if (direction === 'outbound') {\n // outE + inE where bidirectional=true\n unionQuery = `g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(outE()${typeFilter}, inE()${typeFilter}.has('bidirectional', true))`;\n } else if (direction === 'inbound') {\n unionQuery = `g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(inE()${typeFilter}, outE()${typeFilter}.has('bidirectional', true))`;\n }\n\n const baseQuery = unionQuery ?? `${edgeTraversal}${typeFilter}`;\n\n // Count\n const countResult = await conn.submit(`${baseQuery}.dedup().count()`, bindings);\n const total = Number(countResult.items[0] ?? 0);\n\n // Data\n bindings['rangeStart'] = offset;\n bindings['rangeEnd'] = offset + limit;\n const dataResult = await conn.submit(\n `${baseQuery}.dedup().range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n let items = (dataResult.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Post-filter by property filters\n if (options?.propertyFilters && options.propertyFilters.length > 0) {\n items = items.filter(rel => matchesPropertyFilters(rel.properties, options.propertyFilters!));\n }\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n\nexport async function deleteRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<void> {\n await conn.submit(\n \"g.E().has('id', relId).has('repositoryId', rid).drop()\",\n { relId: relationshipId, rid: repositoryId },\n );\n}\n\nexport async function deleteRelationshipsByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipType: string,\n): Promise<{ deletedRelationships: number }> {\n const countResult = await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype).count()\",\n { rid: repositoryId, rtype: relationshipType },\n );\n const deletedRelationships = Number(countResult.items[0] ?? 0);\n\n if (deletedRelationships > 0) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype).drop()\",\n { rid: repositoryId, rtype: relationshipType },\n );\n }\n\n return { deletedRelationships };\n}\n","// Graph traversal + neighbourhood + path Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageExploreOptions,\n StoragePathOptions,\n} from '@utaba/deep-memory/types';\nimport type {\n StorageNeighbourhood,\n StorageNeighbourhoodLayer,\n StoragePathResult,\n StoragePath,\n StoredEntity,\n StoredRelationship,\n} from '@utaba/deep-memory/types';\nimport { entityFromGremlin, relationshipFromGremlin } from '../mapping.js';\nimport { matchesPropertyFilters } from '@utaba/deep-memory';\n\n/**\n * Explore neighbourhood using BFS layer-by-layer.\n * Each layer fetches relationships from the frontier, then loads connected entities.\n */\nexport async function exploreNeighbourhood(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n): Promise<StorageNeighbourhood> {\n const layers: StorageNeighbourhoodLayer[] = [];\n let frontier = new Set<string>([entityId]);\n const visited = new Set<string>([entityId]);\n\n for (let depth = 0; depth < options.depth; depth++) {\n const layer: StorageNeighbourhoodLayer = {};\n const nextFrontier = new Set<string>();\n\n for (const currentId of frontier) {\n // Get relationships from this entity\n const rels = await getRelationshipsForEntity(conn, repositoryId, currentId, options);\n\n for (const rel of rels) {\n const relType = rel.relationshipType;\n if (!layer[relType]) {\n layer[relType] = { total: 0, entities: [], relationships: [] };\n }\n\n // Determine the connected entity ID\n let connectedId: string;\n if (rel.sourceEntityId === currentId) {\n connectedId = rel.targetEntityId;\n } else {\n connectedId = rel.sourceEntityId;\n }\n\n if (!visited.has(connectedId)) {\n // Check entity type filter\n if (options.entityTypes && options.entityTypes.length > 0) {\n const entity = await getEntityLight(conn, repositoryId, connectedId);\n if (!entity || !options.entityTypes.includes(entity.entityType)) continue;\n layer[relType]!.entities.push(entity);\n } else {\n const entity = await getEntityLight(conn, repositoryId, connectedId);\n if (entity) {\n layer[relType]!.entities.push(entity);\n }\n }\n\n visited.add(connectedId);\n nextFrontier.add(connectedId);\n }\n\n layer[relType]!.relationships.push(rel);\n layer[relType]!.total = layer[relType]!.entities.length;\n }\n }\n\n // Apply limitPerType\n for (const relType of Object.keys(layer)) {\n const group = layer[relType]!;\n const start = options.offsetPerType;\n const end = start + options.limitPerType;\n group.entities = group.entities.slice(start, end);\n group.relationships = group.relationships.slice(start, end);\n }\n\n if (Object.keys(layer).length > 0) {\n layers.push(layer);\n }\n frontier = nextFrontier;\n\n if (frontier.size === 0) break;\n }\n\n return { centreId: entityId, layers };\n}\n\n/** Get relationships for a single entity with direction and type filtering. */\nasync function getRelationshipsForEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n): Promise<StoredRelationship[]> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n\n let edgeTraversal: string;\n switch (options.direction) {\n case 'outbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(outE(), inE().has('bidirectional', true))\";\n break;\n case 'inbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(inE(), outE().has('bidirectional', true))\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n break;\n }\n\n let typeFilter = '';\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n const result = await conn.submit(\n `${edgeTraversal}${typeFilter}.dedup().valueMap(true)`,\n bindings,\n );\n\n let rels = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Apply relationship property filters\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n rels = rels.filter(rel => matchesPropertyFilters(rel.properties, options.relationshipPropertyFilters!));\n }\n\n return rels;\n}\n\n/** Get a single entity without embedding (light). */\nasync function getEntityLight(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap(true)\",\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\n/**\n * Find paths between two entities using BFS.\n * Gremlin native path() with simplePath() prevents cycles.\n */\nexport async function findPaths(\n conn: CosmosDbConnection,\n repositoryId: string,\n sourceId: string,\n targetId: string,\n options: StoragePathOptions,\n): Promise<StoragePathResult> {\n // BFS approach layer by layer to find paths\n const paths: StoragePath[] = [];\n const maxDepth = options.maxDepth;\n const limit = options.limit;\n\n // Use application-level BFS to find paths\n // This is more reliable across CosmosDB Gremlin subset limitations\n interface BfsState {\n entityId: string;\n path: string[];\n relationshipIds: string[];\n }\n\n let queue: BfsState[] = [{ entityId: sourceId, path: [sourceId], relationshipIds: [] }];\n\n for (let depth = 0; depth < maxDepth && paths.length < limit; depth++) {\n const nextQueue: BfsState[] = [];\n\n for (const state of queue) {\n if (paths.length >= limit) break;\n\n // Get all relationships for current entity (both directions)\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: state.entityId };\n let edgeQuery = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n edgeQuery += `.hasLabel(${typeParams.join(', ')})`;\n }\n\n const relResult = await conn.submit(`${edgeQuery}.valueMap(true)`, bindings);\n const rels = (relResult.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Filter by relationship property filters\n let filteredRels = rels;\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n filteredRels = rels.filter(r => matchesPropertyFilters(r.properties, options.relationshipPropertyFilters!));\n }\n\n for (const rel of filteredRels) {\n const nextId = rel.sourceEntityId === state.entityId\n ? rel.targetEntityId\n : rel.sourceEntityId;\n\n // Prevent cycles\n if (state.path.includes(nextId)) continue;\n\n // Entity type filter\n if (options.entityTypes && options.entityTypes.length > 0 && nextId !== targetId) {\n const entity = await getEntityLight(conn, repositoryId, nextId);\n if (!entity || !options.entityTypes.includes(entity.entityType)) continue;\n }\n\n const newPath = [...state.path, nextId];\n const newRelIds = [...state.relationshipIds, rel.id];\n\n if (nextId === targetId) {\n paths.push({ entityIds: newPath, relationshipIds: newRelIds });\n if (paths.length >= limit) break;\n } else {\n nextQueue.push({ entityId: nextId, path: newPath, relationshipIds: newRelIds });\n }\n }\n }\n\n queue = nextQueue;\n if (queue.length === 0) break;\n }\n\n return {\n paths,\n totalPaths: paths.length,\n };\n}\n","// Timeline Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StorageTimelineOptions } from '@utaba/deep-memory/types';\nimport type { StorageTimelineResult, StorageTimelineEvent } from '@utaba/deep-memory/types';\n\nexport async function getTimeline(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageTimelineOptions,\n): Promise<StorageTimelineResult> {\n const events: StorageTimelineEvent[] = [];\n\n // Entity creation event\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap('createdAt', 'modifiedAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n if (entityResult.items.length > 0) {\n const props = entityResult.items[0] as Record<string, unknown>;\n const createdAt = unwrapValue(props['createdAt']);\n const modifiedAt = unwrapValue(props['modifiedAt']);\n\n if (createdAt && isInTimeRange(createdAt, options.timeRange)) {\n events.push({\n timestamp: createdAt,\n eventType: 'entity_created',\n entityId,\n });\n }\n if (modifiedAt && modifiedAt !== createdAt && isInTimeRange(modifiedAt, options.timeRange)) {\n events.push({\n timestamp: modifiedAt,\n eventType: 'entity_modified',\n entityId,\n });\n }\n }\n\n // Relationship events connected to this entity\n const relResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE().valueMap('id', 'createdAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n for (const item of relResult.items) {\n const props = item as Record<string, unknown>;\n const relId = unwrapValue(props['id']);\n const relCreatedAt = unwrapValue(props['createdAt']);\n\n if (relCreatedAt && isInTimeRange(relCreatedAt, options.timeRange)) {\n events.push({\n timestamp: relCreatedAt,\n eventType: 'relationship_created',\n entityId,\n relationshipId: relId,\n });\n }\n }\n\n // Sort by timestamp descending\n events.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n\n // Filter by event types\n let filtered = events;\n if (options.eventTypes && options.eventTypes.length > 0) {\n filtered = events.filter(e => options.eventTypes!.includes(e.eventType));\n }\n\n const total = filtered.length;\n const paged = filtered.slice(options.offset, options.offset + options.limit);\n\n return { events: paged, total };\n}\n\nfunction unwrapValue(val: unknown): string {\n if (Array.isArray(val) && val.length > 0) return String(val[0]);\n return String(val ?? '');\n}\n\nfunction isInTimeRange(\n timestamp: string,\n timeRange?: { from: string; to: string },\n): boolean {\n if (!timeRange) return true;\n return timestamp >= timeRange.from && timestamp <= timeRange.to;\n}\n","// Bulk export/import Gremlin queries — optimized for throughput\n//\n// Import optimizations:\n// 1. Parallel execution with concurrency limiter (avoids sequential round-trips)\n// 2. Direct addV/addE when skipExistenceCheck is true (no existence query needed)\n// 3. Gremlin coalesce pattern for atomic upserts when existence checks are needed\n// (1 query instead of 2)\n//\n// Export optimizations:\n// 1. Cursor-based pagination using ID ordering instead of offset-based range()\n// (avoids O(n²) scan on large repositories)\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { ExportChunk, ImportChunk, BulkImportOptions } from '@utaba/deep-memory/types';\nimport type { BulkImportResult, StoredEntity, StoredRelationship } from '@utaba/deep-memory/types';\nimport { entityFromGremlin, entityToGremlinProps, relationshipFromGremlin, relationshipToGremlinProps } from '../mapping.js';\n\nconst EXPORT_BATCH_SIZE = 100;\nconst IMPORT_CONCURRENCY = 8;\n\n// ─── Concurrency limiter ─────────────────────────────────────────\n\n/**\n * Run async tasks with a maximum concurrency limit.\n * Returns results in the same order as the input items.\n */\nasync function runWithConcurrency<T, R>(\n items: T[],\n concurrency: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n let nextIndex = 0;\n const workers: Promise<void>[] = [];\n\n for (let w = 0; w < Math.min(concurrency, items.length); w++) {\n workers.push(\n (async () => {\n while (nextIndex < items.length) {\n const idx = nextIndex++;\n results[idx] = await fn(items[idx]!);\n }\n })(),\n );\n }\n\n await Promise.all(workers);\n return results;\n}\n\n// ─── Export ──────────────────────────────────────────────────────\n\nexport async function* exportAll(\n conn: CosmosDbConnection,\n repositoryId: string,\n): AsyncIterable<ExportChunk> {\n let sequence = 0;\n\n // Export entities using cursor-based pagination (ordered by id)\n let cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const entities = (result.items as Record<string, unknown>[]).map(entityFromGremlin);\n const isLast = entities.length < EXPORT_BATCH_SIZE;\n\n if (entities.length > 0) {\n cursor = entities[entities.length - 1]!.id;\n yield {\n type: 'entities',\n data: entities,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // Export relationships using cursor-based pagination (ordered by id)\n cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.E().has('repositoryId', rid).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const relationships = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n const isLast = relationships.length < EXPORT_BATCH_SIZE;\n\n if (relationships.length > 0) {\n cursor = relationships[relationships.length - 1]!.id;\n yield {\n type: 'relationships',\n data: relationships,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // If nothing was yielded, yield an empty final chunk\n if (sequence === 0) {\n yield {\n type: 'entities',\n data: [],\n sequence: 0,\n isLast: true,\n };\n }\n}\n\n// ─── Import ─────────────────────────────────────────────────────\n\nexport async function importBulk(\n conn: CosmosDbConnection,\n repositoryId: string,\n data: ImportChunk[],\n options?: BulkImportOptions,\n): Promise<BulkImportResult> {\n let entitiesImported = 0;\n let relationshipsImported = 0;\n const errors: Array<{ item: string; error: string }> = [];\n const skipCheck = options?.skipExistenceCheck ?? false;\n\n for (const chunk of data) {\n // Import entities in parallel\n if (chunk.entities && chunk.entities.length > 0) {\n const results = await runWithConcurrency(\n chunk.entities,\n IMPORT_CONCURRENCY,\n async (entity): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertEntity(conn, repositoryId, entity);\n } else {\n await upsertEntity(conn, repositoryId, entity);\n }\n return { ok: true, id: entity.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: entity.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n entitiesImported++;\n } else {\n errors.push({ item: `entity:${r.id}`, error: r.error! });\n }\n }\n }\n\n // Import relationships in parallel\n if (chunk.relationships && chunk.relationships.length > 0) {\n const results = await runWithConcurrency(\n chunk.relationships,\n IMPORT_CONCURRENCY,\n async (rel): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertRelationship(conn, repositoryId, rel);\n } else {\n await upsertRelationship(conn, repositoryId, rel);\n }\n return { ok: true, id: rel.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: rel.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n relationshipsImported++;\n } else {\n errors.push({ item: `relationship:${r.id}`, error: r.error! });\n }\n }\n }\n }\n\n return { entitiesImported, relationshipsImported, errors };\n}\n\n// ─── Direct insert (no existence check) ─────────────────────────\n\n/** Insert an entity directly — assumes it does not exist. */\nasync function insertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = {\n vid: entity.id,\n vertexLabel: entity.entityType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n const query = `g.addV(vertexLabel).property('id', vid)${propParts.join('')}`;\n await conn.submit(query, bindings);\n}\n\n/** Insert a relationship directly — assumes it does not exist. */\nasync function insertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const props = relationshipToGremlinProps(repositoryId, rel);\n const bindings: Record<string, unknown> = {\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n rid: repositoryId,\n edgeLabel: rel.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n const query = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n await conn.submit(query, bindings);\n}\n\n// ─── Atomic upsert (single query with coalesce) ─────────────────\n\n/**\n * Upsert an entity using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n */\nasync function upsertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = {\n vid: entity.id,\n rid: repositoryId,\n vertexLabel: entity.entityType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // coalesce: find existing → update it, or create new\n const query = `g.V().has('repositoryId', rid).has('id', vid).has('entityType').fold().coalesce(unfold()${propParts.join('')}, addV(vertexLabel).property('id', vid)${propParts.join('')})`;\n await conn.submit(query, bindings);\n}\n\n/**\n * Upsert a relationship using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n */\nasync function upsertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const props = relationshipToGremlinProps(repositoryId, rel);\n const bindings: Record<string, unknown> = {\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n rid: repositoryId,\n edgeLabel: rel.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // coalesce: find existing → update it, or create new edge\n const createEdge = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n const query = `g.E().has('id', relId).fold().coalesce(unfold()${propParts.join('')}, ${createEdge})`;\n await conn.submit(query, bindings);\n}\n"],"mappings":";AAgCA,OAAO,YAAY;AACnB,SAAS,iBAAiB,qBAAqB;;;AC3B/C,OAAO,aAAa;AA8Bb,IAAM,qBAAN,MAAyB;AAAA,EACtB,SAAuC;AAAA,EAC9B;AAAA,EAEjB,YAAY,QAAkC;AAC5C,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,YAAY,OAAO,cAAc;AAAA,MACjC,kBAAkB,OAAO,oBAAoB;AAAA,MAC7C,oBAAoB,OAAO,sBAAsB;AAAA,IACnD;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,QAAI,KAAK,OAAQ;AAEjB,UAAM,gBAAgB,IAAI,QAAQ,OAAO,KAAK;AAAA,MAC5C,QAAQ,KAAK,OAAO,QAAQ,UAAU,KAAK,OAAO,SAAS;AAAA,MAC3D,KAAK,OAAO;AAAA,IACd;AAEA,SAAK,SAAS,IAAI,QAAQ,OAAO,OAAO,KAAK,OAAO,UAAU;AAAA,MAC5D;AAAA,MACA,iBAAiB;AAAA,MACjB,oBAAoB,KAAK,OAAO;AAAA,MAChC,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,KAAK,OAAO,KAAK;AAAA,EACzB;AAAA;AAAA,EAGA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ;AACf,YAAM,KAAK,OAAO,MAAM;AACxB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,OAAe,UAA4D;AACtF,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AAEA,QAAI;AACJ,aAAS,UAAU,GAAG,WAAW,KAAK,OAAO,YAAY,WAAW;AAClE,UAAI;AACF,cAAM,YAAY,MAAM,KAAK,OAAO,OAAO,OAAO,QAAQ;AAC1D,cAAM,QAAQ,UAAU,QAAQ;AAChC,cAAM,gBAAgB,qBAAqB,SAAS;AACpD,eAAO,EAAE,OAAO,cAAc;AAAA,MAChC,SAAS,KAAc;AACrB,oBAAY;AACZ,YAAI,iBAAiB,GAAG,KAAK,UAAU,KAAK,OAAO,YAAY;AAC7D,gBAAM,eAAe,gBAAgB,KAAK,OAAO;AACjD,gBAAM,MAAM,YAAY;AACxB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAAA;AAAA,EAGA,YAAmC;AACjC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,WAAO,KAAK;AAAA,EACd;AACF;AAGA,SAAS,iBAAiB,KAAuB;AAC/C,MAAI,eAAe,OAAO;AACxB,UAAM,MAAM,IAAI;AAEhB,QAAI,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,qBAAqB,EAAG,QAAO;AACvE,QAAI,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,oBAAoB,EAAG,QAAO;AAAA,EACxE;AAEA,QAAM,aAAc,MAAkC,YAAY;AAClE,MAAI,eAAe,OAAO,eAAe,IAAK,QAAO;AACrD,SAAO;AACT;AAGA,SAAS,gBAAgB,KAAc,SAAyB;AAE9D,QAAM,aAAc,MAAkC,cAAc;AACpE,MAAI,OAAO,eAAe,YAAY,aAAa,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,IAAI,MAAM,KAAK,IAAI,GAAG,OAAO,GAAG,GAAK;AACnD;AAGA,SAAS,qBAAqB,WAAyD;AACrF,QAAM,QAAQ,UAAU;AACxB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,MAAM,qBAAqB,KAAK,MAAM,2BAA2B;AAChF,SAAO,OAAO,WAAW,WAAW,SAAS;AAC/C;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AACvD;;;ACrIA,SAAS,OAAO,KAAuB;AACrC,MAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS,EAAG,QAAO,IAAI,CAAC;AACtD,SAAO;AACT;AAGA,SAAS,UAAU,KAAsB;AACvC,QAAM,IAAI,OAAO,GAAG;AACpB,SAAO,OAAO,MAAM,WAAW,IAAI,OAAO,KAAK,EAAE;AACnD;AAGA,SAAS,aAAa,KAAkC;AACtD,QAAM,IAAI,OAAO,GAAG;AACpB,SAAO,KAAK,QAAQ,MAAM,KAAK,OAAO,CAAC,IAAI;AAC7C;AAGA,SAAS,cAAiB,KAAc,UAAgB;AACtD,MAAI,OAAO,KAAM,QAAO;AACxB,QAAM,MAAM,OAAO,QAAQ,WAAW,MAAM,OAAO,OAAO,GAAG,CAAC;AAC9D,MAAI,CAAC,OAAO,QAAQ,GAAI,QAAO;AAC/B,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,SAAS,sBAAsB,OAA4C;AACzE,SAAO;AAAA,IACL,WAAW,UAAU,MAAM,WAAW,CAAC;AAAA,IACvC,eAAgB,UAAU,MAAM,eAAe,CAAC,KAAK;AAAA,IACrD,WAAW,UAAU,MAAM,WAAW,CAAC;AAAA,IACvC,uBAAuB,aAAa,MAAM,uBAAuB,CAAC;AAAA,IAClE,oBAAoB,aAAa,MAAM,oBAAoB,CAAC;AAAA,IAC5D,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,gBAAiB,UAAU,MAAM,gBAAgB,CAAC,KAAK;AAAA,IACvD,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,wBAAwB,aAAa,MAAM,wBAAwB,CAAC;AAAA,IACpE,qBAAqB,aAAa,MAAM,qBAAqB,CAAC;AAAA,EAChE;AACF;AAIO,SAAS,kBAAkB,OAA8C;AAC9E,QAAM,eAAe,aAAa,MAAM,WAAW,CAAC;AACpD,SAAO;AAAA,IACL,IAAI,UAAU,MAAM,IAAI,CAAC;AAAA,IACzB,MAAM,UAAU,MAAM,MAAM,CAAC;AAAA,IAC7B,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,OAAO,UAAU,MAAM,aAAa,CAAC;AAAA,IACrC,SAAS,aAAa,MAAM,SAAS,CAAC;AAAA,IACtC,YAAY,cAAc,OAAO,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;AAAA,IACzD,MAAM,aAAa,MAAM,MAAM,CAAC;AAAA,IAChC,YAAY,aAAa,MAAM,YAAY,CAAC;AAAA,IAC5C,YAAY,sBAAsB,KAAK;AAAA,IACvC,WAAW,eAAgB,cAAoC,cAAc,MAAS,IAAK;AAAA,EAC7F;AACF;AAIO,SAAS,wBAAwB,OAAoD;AAC1F,QAAM,QAAQ,OAAO,MAAM,eAAe,CAAC;AAC3C,SAAO;AAAA,IACL,IAAI,UAAU,MAAM,IAAI,CAAC;AAAA,IACzB,kBAAkB,UAAU,MAAM,kBAAkB,CAAC;AAAA,IACrD,gBAAgB,UAAU,MAAM,gBAAgB,CAAC;AAAA,IACjD,gBAAgB,UAAU,MAAM,gBAAgB,CAAC;AAAA,IACjD,YAAY,cAAc,OAAO,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;AAAA,IACzD,eAAe,UAAU,QAAQ,UAAU;AAAA,IAC3C,YAAY,sBAAsB,KAAK;AAAA,EACzC;AACF;AAIO,SAAS,sBAAsB,OAAkD;AACtF,SAAO;AAAA,IACL,cAAc,UAAU,MAAM,cAAc,CAAC;AAAA,IAC7C,MAAM,aAAa,MAAM,MAAM,CAAC;AAAA,IAChC,OAAO,UAAU,MAAM,WAAW,CAAC;AAAA,IACnC,aAAa,aAAa,MAAM,aAAa,CAAC;AAAA,IAC9C,OAAO,aAAa,MAAM,OAAO,CAAC;AAAA,IAClC,OAAO,aAAa,MAAM,OAAO,CAAC;AAAA,IAClC,kBAAkB,cAAgC,OAAO,MAAM,kBAAkB,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC;AAAA,IACrG,UAAU,cAAc,OAAO,MAAM,UAAU,CAAC,GAAG,MAAS;AAAA,IAC5D,WAAW,UAAU,MAAM,WAAW,CAAC;AAAA,IACvC,WAAW,UAAU,MAAM,WAAW,CAAC;AAAA,EACzC;AACF;AAEO,SAAS,6BAA6B,OAAyD;AACpG,SAAO;AAAA,IACL,cAAc,UAAU,MAAM,cAAc,CAAC;AAAA,IAC7C,MAAM,aAAa,MAAM,MAAM,CAAC;AAAA,IAChC,OAAO,UAAU,MAAM,WAAW,CAAC;AAAA,IACnC,aAAa,aAAa,MAAM,aAAa,CAAC;AAAA,IAC9C,kBAAkB,cAAgC,OAAO,MAAM,kBAAkB,CAAC,GAAG,EAAE,MAAM,OAAO,CAAC;AAAA,EACvG;AACF;AAIO,SAAS,sBAAsB,OAAkD;AACtF,SAAO,cAAgC,OAAO,MAAM,YAAY,CAAC,GAAG;AAAA,IAClE,SAAS;AAAA,IACT,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC,YAAY;AAAA,IACZ,aAAa,CAAC;AAAA,IACd,mBAAmB,CAAC;AAAA,EACtB,CAAC;AACH;AAEO,SAAS,wBAAwB,OAAwD;AAC9F,SAAO;AAAA,IACL,UAAU,UAAU,MAAM,UAAU,CAAC;AAAA,IACrC,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,UAAU,UAAU,MAAM,UAAU,CAAC;AAAA,IACrC,iBAAiB,aAAa,MAAM,iBAAiB,CAAC;AAAA,IACtD,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,YAAY,UAAU,MAAM,YAAY,CAAC;AAAA,IACzC,YAAY,aAAa,MAAM,YAAY,CAAC;AAAA,IAC5C,YAAY,aAAa,MAAM,YAAY,CAAC;AAAA,IAC5C,QAAQ,UAAU,MAAM,QAAQ,CAAC;AAAA,EACnC;AACF;AAKO,SAAS,qBACd,cACA,QAC2C;AAC3C,QAAM,QAAmD;AAAA,IACvD;AAAA,IACA,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,IACpB,MAAM,OAAO;AAAA,IACb,YAAY,KAAK,UAAU,OAAO,cAAc,CAAC,CAAC;AAAA,IAClD,WAAW,OAAO,WAAW;AAAA,IAC7B,eAAe,OAAO,WAAW;AAAA,IACjC,WAAW,OAAO,WAAW;AAAA,IAC7B,YAAY,OAAO,WAAW;AAAA,IAC9B,gBAAgB,OAAO,WAAW;AAAA,IAClC,YAAY,OAAO,WAAW;AAAA,EAChC;AACA,MAAI,OAAO,WAAW,KAAM,OAAM,SAAS,IAAI,OAAO;AACtD,MAAI,OAAO,QAAQ,KAAM,OAAM,MAAM,IAAI,OAAO;AAChD,MAAI,OAAO,cAAc,KAAM,OAAM,YAAY,IAAI,OAAO;AAC5D,MAAI,OAAO,WAAW,yBAAyB,KAAM,OAAM,uBAAuB,IAAI,OAAO,WAAW;AACxG,MAAI,OAAO,WAAW,sBAAsB,KAAM,OAAM,oBAAoB,IAAI,OAAO,WAAW;AAClG,MAAI,OAAO,WAAW,0BAA0B,KAAM,OAAM,wBAAwB,IAAI,OAAO,WAAW;AAC1G,MAAI,OAAO,WAAW,uBAAuB,KAAM,OAAM,qBAAqB,IAAI,OAAO,WAAW;AACpG,MAAI,OAAO,aAAa,KAAM,OAAM,WAAW,IAAI,KAAK,UAAU,OAAO,SAAS;AAClF,SAAO;AACT;AAGO,SAAS,2BACd,cACA,KAC2C;AAC3C,QAAM,QAAmD;AAAA,IACvD;AAAA,IACA,kBAAkB,IAAI;AAAA,IACtB,gBAAgB,IAAI;AAAA,IACpB,gBAAgB,IAAI;AAAA,IACpB,eAAe,IAAI;AAAA,IACnB,YAAY,KAAK,UAAU,IAAI,cAAc,CAAC,CAAC;AAAA,IAC/C,WAAW,IAAI,WAAW;AAAA,IAC1B,eAAe,IAAI,WAAW;AAAA,IAC9B,WAAW,IAAI,WAAW;AAAA,IAC1B,YAAY,IAAI,WAAW;AAAA,IAC3B,gBAAgB,IAAI,WAAW;AAAA,IAC/B,YAAY,IAAI,WAAW;AAAA,EAC7B;AACA,MAAI,IAAI,WAAW,yBAAyB,KAAM,OAAM,uBAAuB,IAAI,IAAI,WAAW;AAClG,MAAI,IAAI,WAAW,sBAAsB,KAAM,OAAM,oBAAoB,IAAI,IAAI,WAAW;AAC5F,MAAI,IAAI,WAAW,0BAA0B,KAAM,OAAM,wBAAwB,IAAI,IAAI,WAAW;AACpG,MAAI,IAAI,WAAW,uBAAuB,KAAM,OAAM,qBAAqB,IAAI,IAAI,WAAW;AAC9F,SAAO;AACT;;;AC/LA,SAAS,0BAA0B,+BAA+B;AAElE,IAAM,aAAa;AAEnB,SAAS,aAAa,cAA8B;AAClD,SAAO,QAAQ,YAAY;AAC7B;AAGA,SAAS,cAAc,UAAmC,OAAqE,YAA0D;AACvL,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM;AACV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,SAAS,KAAM;AACnB,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,UAAM,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EAChD;AACA,SAAO,EAAE,OAAO,MAAM,KAAK,EAAE,GAAG,WAAW,IAAI;AACjD;AAEA,eAAsB,iBACpB,MACA,QAC2B;AAC3B,QAAM,WAAW,aAAa,OAAO,YAAY;AAGjD,QAAM,WAAW,MAAM,KAAK;AAAA,IAC1B;AAAA,IACA,EAAE,KAAK,UAAU,KAAK,WAAW;AAAA,EACnC;AACA,MAAI,SAAS,MAAM,SAAS,KAAK,OAAO,SAAS,MAAM,CAAC,CAAC,IAAI,GAAG;AAC9D,UAAM,IAAI,yBAAyB,OAAO,YAAY;AAAA,EACxD;AAEA,QAAM,WAAoC;AAAA,IACxC,KAAK;AAAA,IACL,KAAK,OAAO;AAAA,EACd;AAEA,QAAM,QAAsE;AAAA,IAC1E,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO;AAAA,IACpB,MAAM,OAAO;AAAA,IACb,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,IACd,kBAAkB,KAAK,UAAU,OAAO,gBAAgB;AAAA,IACxD,UAAU,OAAO,WAAW,KAAK,UAAU,OAAO,QAAQ,IAAI;AAAA,IAC9D,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB;AAEA,QAAM,EAAE,MAAM,IAAI,cAAc,UAAU,OAAO,CAAC;AAElD,QAAM,QAAQ,WAAW,UAAU,uDAAuD,KAAK;AAC/F,QAAM,KAAK,OAAO,OAAO,QAAQ;AAEjC,SAAO;AAAA,IACL,cAAc,OAAO;AAAA,IACrB,MAAM,OAAO;AAAA,IACb,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,IACd,kBAAkB,OAAO;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB;AACF;AAEA,eAAsB,cACpB,MACA,cACkC;AAClC,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,KAAK,aAAa,YAAY,EAAE;AAAA,EACpC;AACA,MAAI,OAAO,MAAM,WAAW,EAAG,QAAO;AACtC,SAAO,sBAAsB,OAAO,MAAM,CAAC,CAA4B;AACzE;AAEA,eAAsB,iBACpB,MACA,QACmD;AACnD,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,SAAS,QAAQ,UAAU;AAEjC,MAAI,aAAa;AACjB,MAAI,YAAY;AAChB,QAAM,WAAoC,CAAC;AAE3C,MAAI,QAAQ,MAAM;AAChB,kBAAc;AACd,iBAAa;AACb,aAAS,YAAY,IAAI,OAAO;AAAA,EAClC;AAEA,QAAM,cAAc,MAAM,KAAK,OAAO,GAAG,UAAU,YAAY,QAAQ;AACvE,QAAM,QAAQ,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC;AAE9C,WAAS,YAAY,IAAI;AACzB,WAAS,UAAU,IAAI,SAAS;AAChC,QAAM,aAAa,MAAM,KAAK;AAAA,IAC5B,GAAG,SAAS;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,QAAS,WAAW,MAAoC,IAAI,4BAA4B;AAE9F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,SAAS,QAAQ;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,iBACpB,MACA,cACA,SAC2B;AAC3B,QAAM,WAAW,aAAa,YAAY;AAG1C,QAAM,WAAW,MAAM,cAAc,MAAM,YAAY;AACvD,MAAI,CAAC,SAAU,OAAM,IAAI,wBAAwB,YAAY;AAE7D,QAAM,WAAoC,EAAE,KAAK,SAAS;AAC1D,QAAM,QAAsE,CAAC;AAE7E,MAAI,QAAQ,UAAU,OAAW,OAAM,WAAW,IAAI,QAAQ;AAC9D,MAAI,QAAQ,gBAAgB,OAAW,OAAM,aAAa,IAAI,QAAQ;AACtE,MAAI,QAAQ,SAAS,OAAW,OAAM,MAAM,IAAI,QAAQ;AACxD,MAAI,QAAQ,UAAU,OAAW,OAAM,OAAO,IAAI,QAAQ;AAC1D,MAAI,QAAQ,UAAU,OAAW,OAAM,OAAO,IAAI,QAAQ;AAC1D,MAAI,QAAQ,qBAAqB,OAAW,OAAM,kBAAkB,IAAI,KAAK,UAAU,QAAQ,gBAAgB;AAC/G,MAAI,QAAQ,aAAa,QAAW;AAElC,UAAM,SAAS,EAAE,GAAG,SAAS,UAAU,GAAG,QAAQ,SAAS;AAC3D,UAAM,UAAU,IAAI,KAAK,UAAU,MAAM;AAAA,EAC3C;AAEA,MAAI,OAAO,KAAK,KAAK,EAAE,WAAW,EAAG,QAAO;AAE5C,QAAM,EAAE,MAAM,IAAI,cAAc,UAAU,OAAO,CAAC;AAClD,QAAM,QAAQ,+CAA+C,KAAK;AAClE,QAAM,KAAK,OAAO,OAAO,QAAQ;AAEjC,SAAQ,MAAM,cAAc,MAAM,YAAY;AAChD;AAEA,IAAM,oBAAoB;AAE1B,eAAsB,iBACpB,MACA,cACA,YACe;AAEf,QAAM,oBAAoB,MAAM,KAAK;AAAA,IACnC;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,gBAAgB,OAAO,kBAAkB,MAAM,CAAC,KAAK,CAAC;AAE5D,QAAM,iBAAiB,MAAM,KAAK;AAAA,IAChC;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,qBAAqB,OAAO,eAAe,MAAM,CAAC,KAAK,CAAC;AAE9D,MAAI,uBAAuB;AAC3B,MAAI,kBAAkB;AAItB,SAAO,MAAM;AACX,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD;AACA,UAAM,YAAY,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA,EAAE,KAAK,aAAa;AAAA,IACtB;AACA,UAAM,iBAAiB,OAAO,UAAU,MAAM,CAAC,KAAK,CAAC;AACrD,2BAAuB,qBAAqB;AAC5C,UAAM,aAAa,EAAE,iBAAiB,sBAAsB,eAAe,mBAAmB,CAAC;AAC/F,QAAI,mBAAmB,EAAG;AAAA,EAC5B;AAEA,SAAO,MAAM;AACX,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD;AACA,UAAM,YAAY,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA,EAAE,KAAK,aAAa;AAAA,IACtB;AACA,UAAM,iBAAiB,OAAO,UAAU,MAAM,CAAC,KAAK,CAAC;AACrD,sBAAkB,gBAAgB;AAClC,UAAM,aAAa,EAAE,iBAAiB,sBAAsB,eAAe,mBAAmB,CAAC;AAC/F,QAAI,mBAAmB,EAAG;AAAA,EAC5B;AACF;AAEA,eAAsB,kBACpB,MACA,cACA,YACoE;AAEpE,QAAM,oBAAoB,MAAM,KAAK;AAAA,IACnC;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,gBAAgB,OAAO,kBAAkB,MAAM,CAAC,KAAK,CAAC;AAE5D,QAAM,iBAAiB,MAAM,KAAK;AAAA,IAChC;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,qBAAqB,OAAO,eAAe,MAAM,CAAC,KAAK,CAAC;AAE9D,MAAI,uBAAuB;AAC3B,MAAI,kBAAkB;AAItB,SAAO,MAAM;AACX,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD;AACA,UAAM,YAAY,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA,EAAE,KAAK,aAAa;AAAA,IACtB;AACA,UAAM,iBAAiB,OAAO,UAAU,MAAM,CAAC,KAAK,CAAC;AACrD,2BAAuB,qBAAqB;AAC5C,UAAM,aAAa,EAAE,iBAAiB,sBAAsB,eAAe,mBAAmB,CAAC;AAC/F,QAAI,mBAAmB,EAAG;AAAA,EAC5B;AAEA,SAAO,MAAM;AACX,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD;AACA,UAAM,YAAY,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA,EAAE,KAAK,aAAa;AAAA,IACtB;AACA,UAAM,iBAAiB,OAAO,UAAU,MAAM,CAAC,KAAK,CAAC;AACrD,sBAAkB,gBAAgB;AAClC,UAAM,aAAa,EAAE,iBAAiB,sBAAsB,eAAe,mBAAmB,CAAC;AAC/F,QAAI,mBAAmB,EAAG;AAAA,EAC5B;AAEA,SAAO,EAAE,iBAAiB,eAAe,sBAAsB,mBAAmB;AACpF;AAEA,eAAsB,mBACpB,MACA,cAC0B;AAE1B,QAAM,cAAc,MAAM,KAAK;AAAA,IAC7B;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,MAAI,eAAe;AACnB,MAAI,YAAY,MAAM,SAAS,GAAG;AAChC,QAAI;AACF,YAAM,QAAQ,KAAK,MAAM,YAAY,MAAM,CAAC,CAAW;AACvD,qBAAe,MAAM,WAAW;AAAA,IAClC,QAAQ;AAAA,IAAgB;AAAA,EAC1B;AAGA,QAAM,eAAe,MAAM,KAAK;AAAA,IAC9B;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,sBAA8C,CAAC;AACrD,MAAI,cAAc;AAClB,MAAI,aAAa,MAAM,SAAS,GAAG;AACjC,UAAM,UAAU,aAAa,MAAM,CAAC;AACpC,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,0BAAoB,IAAI,IAAI,OAAO,KAAK;AACxC,qBAAe,OAAO,KAAK;AAAA,IAC7B;AAAA,EACF;AAGA,QAAM,YAAY,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,4BAAoD,CAAC;AAC3D,MAAI,oBAAoB;AACxB,MAAI,UAAU,MAAM,SAAS,GAAG;AAC9B,UAAM,UAAU,UAAU,MAAM,CAAC;AACjC,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,gCAA0B,IAAI,IAAI,OAAO,KAAK;AAC9C,2BAAqB,OAAO,KAAK;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,EACF;AACF;;;ACzUA,SAAS,cAAc,cAA8B;AACnD,SAAO,SAAS,YAAY;AAC9B;AAEA,eAAsB,cACpB,MACA,cAC2B;AAC3B,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,KAAK,cAAc,YAAY,EAAE;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,WAAW,GAAG;AAE7B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MACrC,YAAY;AAAA,MACZ,aAAa,CAAC;AAAA,MACd,mBAAmB,CAAC;AAAA,IACtB;AAAA,EACF;AACA,SAAO,sBAAsB,OAAO,MAAM,CAAC,CAA4B;AACzE;AAEA,eAAsB,eACpB,MACA,cACA,YACe;AACf,QAAM,MAAM,cAAc,YAAY;AACtC,QAAM,YAAY,KAAK,UAAU,UAAU;AAG3C,QAAM,WAAW,MAAM,KAAK;AAAA,IAC1B;AAAA,IACA,EAAE,IAAI;AAAA,EACR;AAEA,MAAI,OAAO,SAAS,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG;AACtC,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,UAAU;AAAA,IACnB;AAAA,EACF,OAAO;AACL,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,KAAK,cAAc,UAAU;AAAA,IACtC;AAAA,EACF;AACF;AAEA,eAAsB,uBACpB,MACA,cACA,SACkD;AAClD,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,SAAS,SAAS,UAAU;AAElC,QAAM,cAAc,MAAM,KAAK;AAAA,IAC7B;AAAA,IACA,EAAE,KAAK,aAAa;AAAA,EACtB;AACA,QAAM,QAAQ,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC;AAE9C,QAAM,aAAa,MAAM,KAAK;AAAA,IAC5B;AAAA,IACA,EAAE,KAAK,cAAc,YAAY,QAAQ,UAAU,SAAS,MAAM;AAAA,EACpE;AAEA,QAAM,QAAS,WAAW,MAAoC,IAAI,uBAAuB;AAEzF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,SAAS,QAAQ;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;;;ACjFA,SAAS,4BAA4B;AAErC,eAAsB,aACpB,MACA,cACA,QACuB;AAEvB,QAAM,WAAW,MAAM,KAAK;AAAA,IAC1B;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,OAAO,GAAG;AAAA,EACtC;AACA,MAAI,OAAO,SAAS,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG;AACtC,UAAM,IAAI,qBAAqB,OAAO,EAAE;AAAA,EAC1C;AAEA,QAAM,QAAQ,qBAAqB,cAAc,MAAM;AACvD,QAAM,WAAoC,EAAE,KAAK,OAAO,GAAG;AAC3D,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAGA,WAAS,aAAa,IAAI,OAAO;AACjC,QAAM,QAAQ,0CAA0C,UAAU,KAAK,EAAE,CAAC;AAC1E,QAAM,KAAK,OAAO,OAAO,QAAQ;AAEjC,SAAO;AACT;AAEA,eAAsB,UACpB,MACA,cACA,UAC8B;AAC9B,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,SAAS;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,WAAW,EAAG,QAAO;AACtC,SAAO,kBAAkB,OAAO,MAAM,CAAC,CAA4B;AACrE;AAEA,eAAsB,gBACpB,MACA,cACA,MAC8B;AAC9B,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,KAAK,cAAc,SAAS,KAAK;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,WAAW,EAAG,QAAO;AACtC,SAAO,kBAAkB,OAAO,MAAM,CAAC,CAA4B;AACrE;AAEA,eAAsB,YACpB,MACA,cACA,WACoC;AACpC,MAAI,UAAU,WAAW,EAAG,QAAO,oBAAI,IAAI;AAG3C,QAAM,WAAoC,EAAE,KAAK,aAAa;AAC9D,QAAM,WAAqB,CAAC;AAC5B,YAAU,QAAQ,CAAC,IAAI,MAAM;AAC3B,UAAM,YAAY,MAAM,CAAC;AACzB,aAAS,SAAS,IAAI;AACtB,aAAS,KAAK,SAAS;AAAA,EACzB,CAAC;AAED,QAAM,eAAe,UAAU,SAAS,KAAK,IAAI,CAAC;AAClD,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB,4CAA4C,YAAY;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,MAAM,oBAAI,IAA0B;AAC1C,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,SAAS,kBAAkB,IAA+B;AAChE,QAAI,IAAI,OAAO,IAAI,MAAM;AAAA,EAC3B;AACA,SAAO;AACT;AAEA,eAAsB,aACpB,MACA,cACA,UACA,SACuB;AACvB,QAAM,WAAoC,EAAE,KAAK,cAAc,KAAK,SAAS;AAC7E,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,QAAM,UAAU,CAAC,KAAa,UAAqC;AACjE,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAEA,MAAI,QAAQ,UAAU,OAAW,SAAQ,eAAe,QAAQ,KAAK;AACrE,MAAI,QAAQ,SAAS,OAAW,SAAQ,QAAQ,QAAQ,IAAI;AAC5D,MAAI,QAAQ,YAAY,OAAW,SAAQ,WAAW,QAAQ,OAAO;AACrE,MAAI,QAAQ,eAAe,OAAW,SAAQ,cAAc,KAAK,UAAU,QAAQ,UAAU,CAAC;AAC9F,MAAI,QAAQ,SAAS,OAAW,SAAQ,QAAQ,QAAQ,IAAI;AAC5D,MAAI,QAAQ,eAAe,OAAW,SAAQ,cAAc,QAAQ,UAAU;AAC9E,MAAI,QAAQ,cAAc,OAAW,SAAQ,aAAa,KAAK,UAAU,QAAQ,SAAS,CAAC;AAG3F,UAAQ,cAAc,QAAQ,WAAW,UAAU;AACnD,UAAQ,kBAAkB,QAAQ,WAAW,cAAc;AAC3D,UAAQ,cAAc,QAAQ,WAAW,UAAU;AACnD,MAAI,QAAQ,WAAW,0BAA0B,KAAM,SAAQ,0BAA0B,QAAQ,WAAW,sBAAsB;AAClI,MAAI,QAAQ,WAAW,uBAAuB,KAAM,SAAQ,uBAAuB,QAAQ,WAAW,mBAAmB;AAEzH,QAAM,QAAQ,kEAAkE,UAAU,KAAK,EAAE,CAAC;AAClG,QAAM,KAAK,OAAO,OAAO,QAAQ;AAEjC,SAAQ,MAAM,UAAU,MAAM,cAAc,QAAQ;AACtD;AAEA,eAAsB,aACpB,MACA,cACA,UACe;AAEf,QAAM,KAAK;AAAA,IACT;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,SAAS;AAAA,EACrC;AACF;AAEA,eAAsB,qBACpB,MACA,cACA,YACoE;AAEpE,QAAM,oBAAoB,MAAM,KAAK;AAAA,IACnC;AAAA,IACA,EAAE,KAAK,cAAc,OAAO,WAAW;AAAA,EACzC;AACA,QAAM,kBAAkB,OAAO,kBAAkB,MAAM,CAAC,KAAK,CAAC;AAG9D,QAAM,iBAAiB,MAAM,KAAK;AAAA,IAChC;AAAA,IACA,EAAE,KAAK,cAAc,OAAO,WAAW;AAAA,EACzC;AACA,QAAM,uBAAuB,OAAO,eAAe,MAAM,CAAC,KAAK,CAAC;AAGhE,MAAI,kBAAkB,GAAG;AACvB,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,OAAO,WAAW;AAAA,IACzC;AAAA,EACF;AAEA,SAAO,EAAE,iBAAiB,qBAAqB;AACjD;AAEA,eAAsB,aACpB,MACA,cACA,OACwC;AACxC,QAAM,WAAoC,EAAE,KAAK,aAAa;AAC9D,MAAI,eAAe;AAGnB,MAAI,MAAM,eAAe,MAAM,YAAY,SAAS,GAAG;AACrD,UAAM,aAAuB,CAAC;AAC9B,UAAM,YAAY,QAAQ,CAAC,GAAG,MAAM;AAClC,YAAM,YAAY,QAAQ,CAAC;AAC3B,eAAS,SAAS,IAAI;AACtB,iBAAW,KAAK,SAAS;AAAA,IAC3B,CAAC;AACD,oBAAgB,6BAA6B,WAAW,KAAK,IAAI,CAAC;AAAA,EACpE;AAGA,MAAI,MAAM,YAAY;AACpB,aAAS,YAAY,IAAI,MAAM,WAAW,YAAY;AAItD,oBAAgB;AAAA,EAClB;AAKA,QAAM,cAAc,MAAM,KAAK;AAAA,IAC7B,QAAQ,YAAY;AAAA,IACpB;AAAA,EACF;AACA,QAAM,QAAQ,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC;AAG9C,WAAS,YAAY,IAAI,MAAM;AAC/B,WAAS,UAAU,IAAI,MAAM,SAAS,MAAM;AAC5C,QAAM,aAAa,MAAM,KAAK;AAAA,IAC5B,QAAQ,YAAY;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,QAAS,WAAW,MAAoC,IAAI,iBAAiB;AAGjF,MAAI,MAAM,cAAc,OAAO,KAAK,MAAM,UAAU,EAAE,SAAS,GAAG;AAChE,YAAQ,MAAM,OAAO,YAAU;AAC7B,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,UAAW,GAAG;AAC5D,YAAI,OAAO,WAAW,GAAG,MAAM,MAAO,QAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,MAAM,SAAS,MAAM,QAAQ;AAAA,IACtC,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,EAChB;AACF;;;AC1OA,SAAS,4BAA4B,8BAA8B;AAEnE,eAAsB,mBACpB,MACA,cACA,cAC6B;AAE7B,QAAM,WAAW,MAAM,KAAK;AAAA,IAC1B;AAAA,IACA,EAAE,OAAO,aAAa,GAAG;AAAA,EAC3B;AACA,MAAI,OAAO,SAAS,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG;AACtC,UAAM,IAAI,2BAA2B,aAAa,EAAE;AAAA,EACtD;AAEA,QAAM,QAAQ,2BAA2B,cAAc,YAAY;AACnE,QAAM,WAAoC;AAAA,IACxC,OAAO,aAAa;AAAA,IACpB,OAAO,aAAa;AAAA,IACpB,OAAO,aAAa;AAAA,IACpB,KAAK;AAAA,IACL,WAAW,aAAa;AAAA,EAC1B;AACA,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAGA,QAAM,QAAQ,gLAAgL,UAAU,KAAK,EAAE,CAAC;AAChN,QAAM,KAAK,OAAO,OAAO,QAAQ;AAEjC,SAAO;AACT;AAEA,eAAsB,gBACpB,MACA,cACA,gBACoC;AACpC,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,OAAO,gBAAgB,KAAK,aAAa;AAAA,EAC7C;AACA,MAAI,OAAO,MAAM,WAAW,EAAG,QAAO;AACtC,SAAO,wBAAwB,OAAO,MAAM,CAAC,CAA4B;AAC3E;AAEA,eAAsB,uBACpB,MACA,cACA,UACA,SAC8C;AAC9C,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,YAAY,SAAS,aAAa;AAExC,QAAM,WAAoC;AAAA,IACxC,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAGA,MAAI;AACJ,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,sBAAgB;AAChB;AAAA,IACF,KAAK;AACH,sBAAgB;AAChB;AAAA,IACF,KAAK;AAAA,IACL;AACE,sBAAgB;AAChB;AAAA,EACJ;AAGA,MAAI,aAAa;AACjB,MAAI,SAAS,qBAAqB,QAAQ,kBAAkB,SAAS,GAAG;AACtE,UAAM,aAAuB,CAAC;AAC9B,YAAQ,kBAAkB,QAAQ,CAAC,GAAG,MAAM;AAC1C,YAAM,YAAY,QAAQ,CAAC;AAC3B,eAAS,SAAS,IAAI;AACtB,iBAAW,KAAK,SAAS;AAAA,IAC3B,CAAC;AACD,iBAAa,aAAa,WAAW,KAAK,IAAI,CAAC;AAAA,EACjD;AAMA,MAAI,aAA4B;AAChC,MAAI,cAAc,YAAY;AAE5B,iBAAa,+EAA+E,UAAU,UAAU,UAAU;AAAA,EAC5H,WAAW,cAAc,WAAW;AAClC,iBAAa,8EAA8E,UAAU,WAAW,UAAU;AAAA,EAC5H;AAEA,QAAM,YAAY,cAAc,GAAG,aAAa,GAAG,UAAU;AAG7D,QAAM,cAAc,MAAM,KAAK,OAAO,GAAG,SAAS,oBAAoB,QAAQ;AAC9E,QAAM,QAAQ,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC;AAG9C,WAAS,YAAY,IAAI;AACzB,WAAS,UAAU,IAAI,SAAS;AAChC,QAAM,aAAa,MAAM,KAAK;AAAA,IAC5B,GAAG,SAAS;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,QAAS,WAAW,MAAoC,IAAI,uBAAuB;AAGvF,MAAI,SAAS,mBAAmB,QAAQ,gBAAgB,SAAS,GAAG;AAClE,YAAQ,MAAM,OAAO,SAAO,uBAAuB,IAAI,YAAY,QAAQ,eAAgB,CAAC;AAAA,EAC9F;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,SAAS,QAAQ;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,MACA,cACA,gBACe;AACf,QAAM,KAAK;AAAA,IACT;AAAA,IACA,EAAE,OAAO,gBAAgB,KAAK,aAAa;AAAA,EAC7C;AACF;AAEA,eAAsB,0BACpB,MACA,cACA,kBAC2C;AAC3C,QAAM,cAAc,MAAM,KAAK;AAAA,IAC7B;AAAA,IACA,EAAE,KAAK,cAAc,OAAO,iBAAiB;AAAA,EAC/C;AACA,QAAM,uBAAuB,OAAO,YAAY,MAAM,CAAC,KAAK,CAAC;AAE7D,MAAI,uBAAuB,GAAG;AAC5B,UAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,OAAO,iBAAiB;AAAA,IAC/C;AAAA,EACF;AAEA,SAAO,EAAE,qBAAqB;AAChC;;;AC7JA,SAAS,0BAAAA,+BAA8B;AAMvC,eAAsB,qBACpB,MACA,cACA,UACA,SAC+B;AAC/B,QAAM,SAAsC,CAAC;AAC7C,MAAI,WAAW,oBAAI,IAAY,CAAC,QAAQ,CAAC;AACzC,QAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAE1C,WAAS,QAAQ,GAAG,QAAQ,QAAQ,OAAO,SAAS;AAClD,UAAM,QAAmC,CAAC;AAC1C,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,aAAa,UAAU;AAEhC,YAAM,OAAO,MAAM,0BAA0B,MAAM,cAAc,WAAW,OAAO;AAEnF,iBAAW,OAAO,MAAM;AACtB,cAAM,UAAU,IAAI;AACpB,YAAI,CAAC,MAAM,OAAO,GAAG;AACnB,gBAAM,OAAO,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG,eAAe,CAAC,EAAE;AAAA,QAC/D;AAGA,YAAI;AACJ,YAAI,IAAI,mBAAmB,WAAW;AACpC,wBAAc,IAAI;AAAA,QACpB,OAAO;AACL,wBAAc,IAAI;AAAA,QACpB;AAEA,YAAI,CAAC,QAAQ,IAAI,WAAW,GAAG;AAE7B,cAAI,QAAQ,eAAe,QAAQ,YAAY,SAAS,GAAG;AACzD,kBAAM,SAAS,MAAM,eAAe,MAAM,cAAc,WAAW;AACnE,gBAAI,CAAC,UAAU,CAAC,QAAQ,YAAY,SAAS,OAAO,UAAU,EAAG;AACjE,kBAAM,OAAO,EAAG,SAAS,KAAK,MAAM;AAAA,UACtC,OAAO;AACL,kBAAM,SAAS,MAAM,eAAe,MAAM,cAAc,WAAW;AACnE,gBAAI,QAAQ;AACV,oBAAM,OAAO,EAAG,SAAS,KAAK,MAAM;AAAA,YACtC;AAAA,UACF;AAEA,kBAAQ,IAAI,WAAW;AACvB,uBAAa,IAAI,WAAW;AAAA,QAC9B;AAEA,cAAM,OAAO,EAAG,cAAc,KAAK,GAAG;AACtC,cAAM,OAAO,EAAG,QAAQ,MAAM,OAAO,EAAG,SAAS;AAAA,MACnD;AAAA,IACF;AAGA,eAAW,WAAW,OAAO,KAAK,KAAK,GAAG;AACxC,YAAM,QAAQ,MAAM,OAAO;AAC3B,YAAM,QAAQ,QAAQ;AACtB,YAAM,MAAM,QAAQ,QAAQ;AAC5B,YAAM,WAAW,MAAM,SAAS,MAAM,OAAO,GAAG;AAChD,YAAM,gBAAgB,MAAM,cAAc,MAAM,OAAO,GAAG;AAAA,IAC5D;AAEA,QAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,eAAW;AAEX,QAAI,SAAS,SAAS,EAAG;AAAA,EAC3B;AAEA,SAAO,EAAE,UAAU,UAAU,OAAO;AACtC;AAGA,eAAe,0BACb,MACA,cACA,UACA,SAC+B;AAC/B,QAAM,WAAoC,EAAE,KAAK,cAAc,KAAK,SAAS;AAE7E,MAAI;AACJ,UAAQ,QAAQ,WAAW;AAAA,IACzB,KAAK;AACH,sBAAgB;AAChB;AAAA,IACF,KAAK;AACH,sBAAgB;AAChB;AAAA,IACF,KAAK;AAAA,IACL;AACE,sBAAgB;AAChB;AAAA,EACJ;AAEA,MAAI,aAAa;AACjB,MAAI,QAAQ,qBAAqB,QAAQ,kBAAkB,SAAS,GAAG;AACrE,UAAM,aAAuB,CAAC;AAC9B,YAAQ,kBAAkB,QAAQ,CAAC,GAAG,MAAM;AAC1C,YAAM,YAAY,QAAQ,CAAC;AAC3B,eAAS,SAAS,IAAI;AACtB,iBAAW,KAAK,SAAS;AAAA,IAC3B,CAAC;AACD,iBAAa,aAAa,WAAW,KAAK,IAAI,CAAC;AAAA,EACjD;AAEA,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB,GAAG,aAAa,GAAG,UAAU;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,OAAQ,OAAO,MAAoC,IAAI,uBAAuB;AAGlF,MAAI,QAAQ,+BAA+B,QAAQ,4BAA4B,SAAS,GAAG;AACzF,WAAO,KAAK,OAAO,SAAOA,wBAAuB,IAAI,YAAY,QAAQ,2BAA4B,CAAC;AAAA,EACxG;AAEA,SAAO;AACT;AAGA,eAAe,eACb,MACA,cACA,UAC8B;AAC9B,QAAM,SAAS,MAAM,KAAK;AAAA,IACxB;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,SAAS;AAAA,EACrC;AACA,MAAI,OAAO,MAAM,WAAW,EAAG,QAAO;AACtC,SAAO,kBAAkB,OAAO,MAAM,CAAC,CAA4B;AACrE;AAMA,eAAsB,UACpB,MACA,cACA,UACA,UACA,SAC4B;AAE5B,QAAM,QAAuB,CAAC;AAC9B,QAAM,WAAW,QAAQ;AACzB,QAAM,QAAQ,QAAQ;AAUtB,MAAI,QAAoB,CAAC,EAAE,UAAU,UAAU,MAAM,CAAC,QAAQ,GAAG,iBAAiB,CAAC,EAAE,CAAC;AAEtF,WAAS,QAAQ,GAAG,QAAQ,YAAY,MAAM,SAAS,OAAO,SAAS;AACrE,UAAM,YAAwB,CAAC;AAE/B,eAAW,SAAS,OAAO;AACzB,UAAI,MAAM,UAAU,MAAO;AAG3B,YAAM,WAAoC,EAAE,KAAK,cAAc,KAAK,MAAM,SAAS;AACnF,UAAI,YAAY;AAEhB,UAAI,QAAQ,qBAAqB,QAAQ,kBAAkB,SAAS,GAAG;AACrE,cAAM,aAAuB,CAAC;AAC9B,gBAAQ,kBAAkB,QAAQ,CAAC,GAAG,MAAM;AAC1C,gBAAM,YAAY,QAAQ,CAAC;AAC3B,mBAAS,SAAS,IAAI;AACtB,qBAAW,KAAK,SAAS;AAAA,QAC3B,CAAC;AACD,qBAAa,aAAa,WAAW,KAAK,IAAI,CAAC;AAAA,MACjD;AAEA,YAAM,YAAY,MAAM,KAAK,OAAO,GAAG,SAAS,mBAAmB,QAAQ;AAC3E,YAAM,OAAQ,UAAU,MAAoC,IAAI,uBAAuB;AAGvF,UAAI,eAAe;AACnB,UAAI,QAAQ,+BAA+B,QAAQ,4BAA4B,SAAS,GAAG;AACzF,uBAAe,KAAK,OAAO,OAAKA,wBAAuB,EAAE,YAAY,QAAQ,2BAA4B,CAAC;AAAA,MAC5G;AAEA,iBAAW,OAAO,cAAc;AAC9B,cAAM,SAAS,IAAI,mBAAmB,MAAM,WACxC,IAAI,iBACJ,IAAI;AAGR,YAAI,MAAM,KAAK,SAAS,MAAM,EAAG;AAGjC,YAAI,QAAQ,eAAe,QAAQ,YAAY,SAAS,KAAK,WAAW,UAAU;AAChF,gBAAM,SAAS,MAAM,eAAe,MAAM,cAAc,MAAM;AAC9D,cAAI,CAAC,UAAU,CAAC,QAAQ,YAAY,SAAS,OAAO,UAAU,EAAG;AAAA,QACnE;AAEA,cAAM,UAAU,CAAC,GAAG,MAAM,MAAM,MAAM;AACtC,cAAM,YAAY,CAAC,GAAG,MAAM,iBAAiB,IAAI,EAAE;AAEnD,YAAI,WAAW,UAAU;AACvB,gBAAM,KAAK,EAAE,WAAW,SAAS,iBAAiB,UAAU,CAAC;AAC7D,cAAI,MAAM,UAAU,MAAO;AAAA,QAC7B,OAAO;AACL,oBAAU,KAAK,EAAE,UAAU,QAAQ,MAAM,SAAS,iBAAiB,UAAU,CAAC;AAAA,QAChF;AAAA,MACF;AAAA,IACF;AAEA,YAAQ;AACR,QAAI,MAAM,WAAW,EAAG;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAY,MAAM;AAAA,EACpB;AACF;;;AClPA,eAAsB,YACpB,MACA,cACA,UACA,SACgC;AAChC,QAAM,SAAiC,CAAC;AAGxC,QAAM,eAAe,MAAM,KAAK;AAAA,IAC9B;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,SAAS;AAAA,EACrC;AAEA,MAAI,aAAa,MAAM,SAAS,GAAG;AACjC,UAAM,QAAQ,aAAa,MAAM,CAAC;AAClC,UAAM,YAAY,YAAY,MAAM,WAAW,CAAC;AAChD,UAAM,aAAa,YAAY,MAAM,YAAY,CAAC;AAElD,QAAI,aAAa,cAAc,WAAW,QAAQ,SAAS,GAAG;AAC5D,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,cAAc,eAAe,aAAa,cAAc,YAAY,QAAQ,SAAS,GAAG;AAC1F,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,YAAY,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,EAAE,KAAK,cAAc,KAAK,SAAS;AAAA,EACrC;AAEA,aAAW,QAAQ,UAAU,OAAO;AAClC,UAAM,QAAQ;AACd,UAAM,QAAQ,YAAY,MAAM,IAAI,CAAC;AACrC,UAAM,eAAe,YAAY,MAAM,WAAW,CAAC;AAEnD,QAAI,gBAAgB,cAAc,cAAc,QAAQ,SAAS,GAAG;AAClE,aAAO,KAAK;AAAA,QACV,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,QACA,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAG5D,MAAI,WAAW;AACf,MAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,GAAG;AACvD,eAAW,OAAO,OAAO,OAAK,QAAQ,WAAY,SAAS,EAAE,SAAS,CAAC;AAAA,EACzE;AAEA,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,SAAS,MAAM,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,KAAK;AAE3E,SAAO,EAAE,QAAQ,OAAO,MAAM;AAChC;AAEA,SAAS,YAAY,KAAsB;AACzC,MAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS,EAAG,QAAO,OAAO,IAAI,CAAC,CAAC;AAC9D,SAAO,OAAO,OAAO,EAAE;AACzB;AAEA,SAAS,cACP,WACA,WACS;AACT,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,aAAa,UAAU,QAAQ,aAAa,UAAU;AAC/D;;;ACvEA,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAQ3B,eAAe,mBACb,OACA,aACA,IACc;AACd,QAAM,UAAe,IAAI,MAAM,MAAM,MAAM;AAC3C,MAAI,YAAY;AAChB,QAAM,UAA2B,CAAC;AAElC,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,aAAa,MAAM,MAAM,GAAG,KAAK;AAC5D,YAAQ;AAAA,OACL,YAAY;AACX,eAAO,YAAY,MAAM,QAAQ;AAC/B,gBAAM,MAAM;AACZ,kBAAQ,GAAG,IAAI,MAAM,GAAG,MAAM,GAAG,CAAE;AAAA,QACrC;AAAA,MACF,GAAG;AAAA,IACL;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAIA,gBAAuB,UACrB,MACA,cAC4B;AAC5B,MAAI,WAAW;AAGf,MAAI,SAAS;AACb,SAAO,MAAM;AACX,UAAM,SAAS,WAAW,KACtB,MAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD,IACA,MAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,QAAQ,WAAW,kBAAkB;AAAA,IAC5D;AAEJ,UAAM,WAAY,OAAO,MAAoC,IAAI,iBAAiB;AAClF,UAAM,SAAS,SAAS,SAAS;AAEjC,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,SAAS,SAAS,SAAS,CAAC,EAAG;AACxC,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAQ;AAAA,EACd;AAGA,WAAS;AACT,SAAO,MAAM;AACX,UAAM,SAAS,WAAW,KACtB,MAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,WAAW,kBAAkB;AAAA,IACpD,IACA,MAAM,KAAK;AAAA,MACT;AAAA,MACA,EAAE,KAAK,cAAc,QAAQ,WAAW,kBAAkB;AAAA,IAC5D;AAEJ,UAAM,gBAAiB,OAAO,MAAoC,IAAI,uBAAuB;AAC7F,UAAM,SAAS,cAAc,SAAS;AAEtC,QAAI,cAAc,SAAS,GAAG;AAC5B,eAAS,cAAc,cAAc,SAAS,CAAC,EAAG;AAClD,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAQ;AAAA,EACd;AAGA,MAAI,aAAa,GAAG;AAClB,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,MAAM,CAAC;AAAA,MACP,UAAU;AAAA,MACV,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAIA,eAAsB,WACpB,MACA,cACA,MACA,SAC2B;AAC3B,MAAI,mBAAmB;AACvB,MAAI,wBAAwB;AAC5B,QAAM,SAAiD,CAAC;AACxD,QAAM,YAAY,SAAS,sBAAsB;AAEjD,aAAW,SAAS,MAAM;AAExB,QAAI,MAAM,YAAY,MAAM,SAAS,SAAS,GAAG;AAC/C,YAAM,UAAU,MAAM;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,QACA,OAAO,WAAiE;AACtE,cAAI;AACF,gBAAI,WAAW;AACb,oBAAM,aAAa,MAAM,cAAc,MAAM;AAAA,YAC/C,OAAO;AACL,oBAAM,aAAa,MAAM,cAAc,MAAM;AAAA,YAC/C;AACA,mBAAO,EAAE,IAAI,MAAM,IAAI,OAAO,GAAG;AAAA,UACnC,SAAS,KAAc;AACrB,mBAAO;AAAA,cACL,IAAI;AAAA,cACJ,IAAI,OAAO;AAAA,cACX,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,KAAK,SAAS;AACvB,YAAI,EAAE,IAAI;AACR;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,EAAE,MAAM,UAAU,EAAE,EAAE,IAAI,OAAO,EAAE,MAAO,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,iBAAiB,MAAM,cAAc,SAAS,GAAG;AACzD,YAAM,UAAU,MAAM;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,QACA,OAAO,QAA8D;AACnE,cAAI;AACF,gBAAI,WAAW;AACb,oBAAM,mBAAmB,MAAM,cAAc,GAAG;AAAA,YAClD,OAAO;AACL,oBAAM,mBAAmB,MAAM,cAAc,GAAG;AAAA,YAClD;AACA,mBAAO,EAAE,IAAI,MAAM,IAAI,IAAI,GAAG;AAAA,UAChC,SAAS,KAAc;AACrB,mBAAO;AAAA,cACL,IAAI;AAAA,cACJ,IAAI,IAAI;AAAA,cACR,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,KAAK,SAAS;AACvB,YAAI,EAAE,IAAI;AACR;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,EAAE,MAAM,gBAAgB,EAAE,EAAE,IAAI,OAAO,EAAE,MAAO,CAAC;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,kBAAkB,uBAAuB,OAAO;AAC3D;AAKA,eAAe,aACb,MACA,cACA,QACe;AACf,QAAM,QAAQ,qBAAqB,cAAc,MAAM;AACvD,QAAM,WAAoC;AAAA,IACxC,KAAK,OAAO;AAAA,IACZ,aAAa,OAAO;AAAA,EACtB;AACA,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAEA,QAAM,QAAQ,0CAA0C,UAAU,KAAK,EAAE,CAAC;AAC1E,QAAM,KAAK,OAAO,OAAO,QAAQ;AACnC;AAGA,eAAe,mBACb,MACA,cACA,KACe;AACf,QAAM,QAAQ,2BAA2B,cAAc,GAAG;AAC1D,QAAM,WAAoC;AAAA,IACxC,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,KAAK;AAAA,IACL,WAAW,IAAI;AAAA,EACjB;AACA,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAEA,QAAM,QAAQ,gLAAgL,UAAU,KAAK,EAAE,CAAC;AAChN,QAAM,KAAK,OAAO,OAAO,QAAQ;AACnC;AAQA,eAAe,aACb,MACA,cACA,QACe;AACf,QAAM,QAAQ,qBAAqB,cAAc,MAAM;AACvD,QAAM,WAAoC;AAAA,IACxC,KAAK,OAAO;AAAA,IACZ,KAAK;AAAA,IACL,aAAa,OAAO;AAAA,EACtB;AACA,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAGA,QAAM,QAAQ,2FAA2F,UAAU,KAAK,EAAE,CAAC,0CAA0C,UAAU,KAAK,EAAE,CAAC;AACvL,QAAM,KAAK,OAAO,OAAO,QAAQ;AACnC;AAMA,eAAe,mBACb,MACA,cACA,KACe;AACf,QAAM,QAAQ,2BAA2B,cAAc,GAAG;AAC1D,QAAM,WAAoC;AAAA,IACxC,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,KAAK;AAAA,IACL,WAAW,IAAI;AAAA,EACjB;AACA,QAAM,YAAsB,CAAC;AAC7B,MAAI,MAAM;AAEV,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAM,YAAY,IAAI,KAAK;AAC3B,aAAS,SAAS,IAAI;AACtB,cAAU,KAAK,cAAc,GAAG,MAAM,SAAS,GAAG;AAAA,EACpD;AAGA,QAAM,aAAa,gLAAgL,UAAU,KAAK,EAAE,CAAC;AACrN,QAAM,QAAQ,kDAAkD,UAAU,KAAK,EAAE,CAAC,KAAK,UAAU;AACjG,QAAM,KAAK,OAAO,OAAO,QAAQ;AACnC;;;ATjQA,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AAMhB,IAAM,mBAAN,MAA0E;AAAA,EAC9D;AAAA,EACA;AAAA,EACA,WAAW,IAAI,gBAAgB;AAAA,EAEhD,YAAY,QAAgC;AAC1C,SAAK,SAAS;AACd,SAAK,OAAO,IAAI,mBAAmB;AAAA,MACjC,UAAU,OAAO;AAAA,MACjB,KAAK,OAAO;AAAA,MACZ,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,YAAY,OAAO;AAAA,MACnB,kBAAkB,OAAO;AAAA,MACzB,oBAAoB,OAAO;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,MAAM,aAA4B;AAChC,UAAM,KAAK,KAAK,QAAQ;AAAA,EAC1B;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK,KAAK,MAAM;AAAA,EACxB;AAAA,EAEA,MAAM,eAA4C;AAChD,UAAM,WAAW,KAAK,gBAAgB;AACtC,UAAM,eAAe,KAAK,OAAO,gBAAgB;AACjD,QAAI,kBAAkB;AACtB,QAAI,gBAAgB;AAEpB,QAAI;AAEF,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA,KAAK,OAAO;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE,IAAI,KAAK,OAAO,SAAS;AAAA,QAC3B,KAAK,OAAO,sBAAsB;AAAA,MACpC;AACA,wBAAkB;AAGlB,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA,KAAK,OAAO;AAAA,QACZ,OAAO,KAAK,OAAO,QAAQ;AAAA,QAC3B,OAAO,KAAK,OAAO,QAAQ;AAAA,QAC3B;AAAA,QACA;AAAA,UACE,IAAI,KAAK,OAAO;AAAA,UAChB,cAAc,EAAE,OAAO,CAAC,YAAY,GAAG,MAAM,OAAO;AAAA,QACtD;AAAA,QACA,KAAK,OAAO,sBAAsB;AAAA,MACpC;AACA,sBAAgB;AAGhB,YAAM,KAAK,KAAK,MAAM;AACtB,YAAM,KAAK,KAAK,QAAQ;AAGxB,YAAM,WAAW,MAAM,KAAK,KAAK;AAAA,QAC/B;AAAA,QACA,EAAE,QAAQ,eAAe;AAAA,MAC3B;AAEA,UAAI,SAAS,MAAM,SAAS,GAAG;AAC7B,cAAM,QAAQ,SAAS,MAAM,CAAC;AAC9B,cAAM,UAAU,OAAO,mBAAmB,MAAM,eAAe,CAAC,KAAK,CAAC;AACtE,YAAI,WAAW,kBAAkB,CAAC,mBAAmB,CAAC,eAAe;AACnE,iBAAO;AAAA,YACL,iBAAiB;AAAA,YACjB,eAAe;AAAA,YACf,iBAAiB;AAAA,YACjB,eAAe;AAAA,UACjB;AAAA,QACF;AACA,cAAM,KAAK,KAAK;AAAA,UACd;AAAA,UACA,EAAE,QAAQ,gBAAgB,KAAK,eAAe;AAAA,QAChD;AAAA,MACF,OAAO;AACL,cAAM,KAAK,KAAK;AAAA,UACd;AAAA,UACA,EAAE,QAAQ,gBAAgB,IAAI,WAAW,KAAK,eAAe;AAAA,QAC/D;AACA,wBAAgB;AAAA,MAClB;AAEA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,iBAAiB,CAAC,mBAAmB,CAAC;AAAA,QACtC,eAAe;AAAA,MACjB;AAAA,IACF,SAAS,KAAc;AACrB,YAAM,IAAI;AAAA,QACR,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,kBAA0B;AAChC,QAAI,KAAK,OAAO,aAAc,QAAO,KAAK,OAAO,aAAa,QAAQ,QAAQ,EAAE;AAEhF,UAAM,MAAM,IAAI,IAAI,KAAK,OAAO,QAAQ;AACxC,WAAO,WAAW,IAAI,QAAQ;AAAA,EAChC;AAAA;AAAA,EAIA,MAAM,iBAAiB,QAA4D;AACjF,WAAmB,iBAAiB,KAAK,MAAM,MAAM;AAAA,EACvD;AAAA,EAEA,MAAM,cAAc,cAAwD;AAC1E,WAAmB,cAAc,KAAK,MAAM,YAAY;AAAA,EAC1D;AAAA,EAEA,MAAM,iBAAiB,QAA8E;AACnG,WAAmB,iBAAiB,KAAK,MAAM,MAAM;AAAA,EACvD;AAAA,EAEA,MAAM,iBAAiB,cAAsB,SAAsD;AACjG,WAAmB,iBAAiB,KAAK,MAAM,cAAc,OAAO;AAAA,EACtE;AAAA,EAEA,MAAM,iBAAiB,cAAsB,YAAoD;AAC/F,WAAmB,iBAAiB,KAAK,MAAM,cAAc,UAAU;AAAA,EACzE;AAAA,EAEA,MAAM,kBAAkB,cAAsB,YAAyG;AACrJ,WAAmB,kBAAkB,KAAK,MAAM,cAAc,UAAU;AAAA,EAC1E;AAAA,EAEA,MAAM,mBAAmB,cAAgD;AACvE,WAAmB,mBAAmB,KAAK,MAAM,YAAY;AAAA,EAC/D;AAAA;AAAA,EAIA,MAAM,cAAc,cAAiD;AACnE,WAAoB,cAAc,KAAK,MAAM,YAAY;AAAA,EAC3D;AAAA,EAEA,MAAM,eAAe,cAAsB,YAA6C;AACtF,WAAoB,eAAe,KAAK,MAAM,cAAc,UAAU;AAAA,EACxE;AAAA,EAEA,MAAM,uBAAuB,cAAsB,SAA+E;AAChI,WAAoB,uBAAuB,KAAK,MAAM,cAAc,OAAO;AAAA,EAC7E;AAAA;AAAA,EAIA,MAAM,aAAa,cAAsB,QAA6C;AACpF,WAAqB,aAAa,KAAK,MAAM,cAAc,MAAM;AAAA,EACnE;AAAA,EAEA,MAAM,UAAU,cAAsB,UAAgD;AACpF,WAAqB,UAAU,KAAK,MAAM,cAAc,QAAQ;AAAA,EAClE;AAAA,EAEA,MAAM,gBAAgB,cAAsB,MAA4C;AACtF,WAAqB,gBAAgB,KAAK,MAAM,cAAc,IAAI;AAAA,EACpE;AAAA,EAEA,MAAM,YAAY,cAAsB,WAAyD;AAC/F,WAAqB,YAAY,KAAK,MAAM,cAAc,SAAS;AAAA,EACrE;AAAA,EAEA,MAAM,aAAa,cAAsB,UAAkB,SAAoD;AAC7G,WAAqB,aAAa,KAAK,MAAM,cAAc,UAAU,OAAO;AAAA,EAC9E;AAAA,EAEA,MAAM,aAAa,cAAsB,UAAiC;AACxE,WAAqB,aAAa,KAAK,MAAM,cAAc,QAAQ;AAAA,EACrE;AAAA,EAEA,MAAM,qBAAqB,cAAsB,YAAwF;AACvI,WAAqB,qBAAqB,KAAK,MAAM,cAAc,UAAU;AAAA,EAC/E;AAAA,EAEA,MAAM,aAAa,cAAsB,OAAiE;AACxG,WAAqB,aAAa,KAAK,MAAM,cAAc,KAAK;AAAA,EAClE;AAAA;AAAA,EAIA,MAAM,mBAAmB,cAAsB,cAA+D;AAC5G,WAAkB,mBAAmB,KAAK,MAAM,cAAc,YAAY;AAAA,EAC5E;AAAA,EAEA,MAAM,gBAAgB,cAAsB,gBAA4D;AACtG,WAAkB,gBAAgB,KAAK,MAAM,cAAc,cAAc;AAAA,EAC3E;AAAA,EAEA,MAAM,uBAAuB,cAAsB,UAAkB,SAAkF;AACrJ,WAAkB,uBAAuB,KAAK,MAAM,cAAc,UAAU,OAAO;AAAA,EACrF;AAAA,EAEA,MAAM,mBAAmB,cAAsB,gBAAuC;AACpF,WAAkB,mBAAmB,KAAK,MAAM,cAAc,cAAc;AAAA,EAC9E;AAAA,EAEA,MAAM,0BAA0B,cAAsB,kBAAqE;AACzH,WAAkB,0BAA0B,KAAK,MAAM,cAAc,gBAAgB;AAAA,EACvF;AAAA;AAAA,EAIA,MAAM,qBAAqB,cAAsB,UAAkB,SAA+D;AAChI,WAAwB,qBAAqB,KAAK,MAAM,cAAc,UAAU,OAAO;AAAA,EACzF;AAAA,EAEA,MAAM,UAAU,cAAsB,UAAkB,UAAkB,SAAyD;AACjI,WAAwB,UAAU,KAAK,MAAM,cAAc,UAAU,UAAU,OAAO;AAAA,EACxF;AAAA;AAAA,EAIA,MAAM,YAAY,cAAsB,UAAkB,SAAiE;AACzH,WAAuB,YAAY,KAAK,MAAM,cAAc,UAAU,OAAO;AAAA,EAC/E;AAAA;AAAA,EAIA,UAAU,cAAkD;AAC1D,WAAmB,UAAU,KAAK,MAAM,YAAY;AAAA,EACtD;AAAA,EAEA,MAAM,WAAW,cAAsB,MAAqB,SAAwD;AAClH,WAAmB,WAAW,KAAK,MAAM,cAAc,MAAM,OAAO;AAAA,EACtE;AAAA;AAAA,EAIA,kBAA8C;AAC5C,WAAO;AAAA,MACL,qBAAqB;AAAA,MACrB,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,qCAAqC;AAAA,MACrC,+BAA+B;AAAA,MAC/B,qBAAqB;AAAA,MACrB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,6BAA6B;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,cACA,MACA,eAC0B;AAC1B,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,aAAa,MAAM,KAAK,cAAc,YAAY;AAGxD,UAAM,WAAW,gBACb,EAAE,OAAO,eAAe,QAAQ,CAAC,GAAG,iBAAiB,IAAI,IACzD,KAAK,SAAS,QAAQ,MAAM,UAAU;AAI1C,UAAM,cAAc,SAAS,MAAM;AAAA,MACjC;AAAA,MACA,8BAA8B,YAAY;AAAA,IAC5C;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,KAAK,OAAO,aAAa,SAAS,MAAM;AAClE,YAAM,kBAAkB,KAAK,IAAI,IAAI;AAErC,YAAM,WAAwC,CAAC;AAC/C,YAAM,gBAA+D,CAAC;AACtE,YAAM,QAA+C,CAAC;AAEtD,UAAI,KAAK,eAAe,QAAQ;AAE9B,mBAAW,QAAQ,OAAO,OAAO;AAC/B,gBAAM,WAAW;AACjB,cAAI,SAAS,SAAS;AACpB,kBAAM,eAA4C,CAAC;AACnD,uBAAW,OAAO,SAAS,SAAS;AAClC,oBAAM,QAAQ;AACd,kBAAI,MAAM,YAAY,GAAG;AACvB,6BAAa,KAAK,kBAAkB,KAAK,CAAC;AAAA,cAC5C;AAAA,YACF;AACA,gBAAI,aAAa,SAAS,GAAG;AAC3B,oBAAM,KAAK;AAAA,gBACT,QAAQ,aAAa,SAAS;AAAA,gBAC9B,UAAU;AAAA,gBACV,eAAe,CAAC;AAAA,cAClB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,mBAAW,QAAQ,OAAO,OAAO;AAC/B,gBAAM,SAAS,kBAAkB,IAA+B;AAChE,mBAAS,KAAK,MAAM;AAAA,QACtB;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,SAAS;AAC5B,YAAM,gBAA+B;AAAA,QACnC;AAAA,QACA,cAAc,OAAO,iBAAiB,OAClC,EAAE,OAAO,MAAM,OAAO,OAAO,cAAc,IAC3C;AAAA,QACJ,eAAe;AAAA,QACf,uBAAuB;AAAA,QACvB,eAAe;AAAA,UACb,YAAY;AAAA,UACZ,UAAU,KAAK,OAAO;AAAA,QACxB;AAAA,QACA,WAAW,SAAS,UAAU;AAAA,QAC9B,kBAAkB,SAAS,UAAU,QAAQ,iBAAiB;AAAA,MAChE;AAEA,aAAO;AAAA,QACL,UAAU,KAAK,eAAe,SAAS,CAAC,IAAI;AAAA,QAC5C,eAAe,KAAK,eAAe,UAAU,KAAK,eAAe,QAAQ,gBAAgB;AAAA,QACzF,OAAO,KAAK,eAAe,SAAS,QAAQ;AAAA,QAC5C,OAAO,SAAS,SAAS,MAAM;AAAA,QAC/B,UAAU,SAAS,SAAS,MAAM;AAAA,QAClC,SAAS,SAAS,UAAU,SAAS,MAAM,UAAU;AAAA,QACrD;AAAA,MACF;AAAA,IACF,SAAS,KAAc;AACrB,YAAM,IAAI;AAAA,QACR,6BAA6B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAC7E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,eACA,OACA,QAC0B;AAC1B,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,KAAK,OAAO,OAAO,MAAM;AACnD,YAAM,kBAAkB,KAAK,IAAI,IAAI;AAGrC,YAAM,WAAwC,CAAC;AAC/C,iBAAW,QAAQ,OAAO,OAAO;AAC/B,YAAI;AACF,gBAAM,SAAS,kBAAkB,IAA+B;AAChE,cAAI,OAAO,IAAI;AACb,qBAAS,KAAK,MAAM;AAAA,UACtB;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,gBAA+B;AAAA,QACnC;AAAA,QACA,cAAc,OAAO,iBAAiB,OAClC,EAAE,OAAO,MAAM,OAAO,OAAO,cAAc,IAC3C;AAAA,QACJ,eAAe;AAAA,QACf,uBAAuB;AAAA,QACvB,eAAe,EAAE,YAAY,SAAS,OAAO;AAAA,QAC7C,WAAW;AAAA,MACb;AAEA,aAAO;AAAA,QACL;AAAA,QACA,OAAO,SAAS;AAAA,QAChB,UAAU,SAAS;AAAA,QACnB,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,KAAc;AACrB,YAAM,IAAI;AAAA,QACR,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAChF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,KAAuB;AACjD,MAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS,EAAG,QAAO,IAAI,CAAC;AACtD,SAAO;AACT;AAQA,SAAS,gBACP,MACA,cACA,cACA,MACA,KACQ;AACR,QAAM,UAAU,GAAG,KAAK,YAAY,CAAC;AAAA,EAAK,aAAa,YAAY,CAAC;AAAA,EAAK,YAAY;AAAA,EAAK,KAAK,YAAY,CAAC;AAAA;AAAA;AAC5G,QAAM,YAAY,OAAO,KAAK,KAAK,QAAQ;AAC3C,QAAM,OAAO,OAAO,WAAW,UAAU,SAAS;AAClD,OAAK,OAAO,OAAO;AACnB,QAAM,YAAY,KAAK,OAAO,QAAQ;AACtC,SAAO,mBAAmB,2BAA2B,SAAS,EAAE;AAClE;AAMA,eAAe,cACb,UACA,KACA,SACA,cACA,cACA,MACA,oBACkB;AAClB,QAAM,QAAO,oBAAI,KAAK,GAAE,YAAY;AACpC,QAAM,QAAQ,gBAAgB,QAAQ,cAAc,cAAc,MAAM,GAAG;AAE3E,QAAM,MAAM,GAAG,QAAQ,IAAI,OAAO;AAGlC,QAAM,UAAkD;AAAA,IACtD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B;AAGA,MAAI,CAAC,oBAAoB;AAEvB,QAAI;AAEF,cAAQ,aAAa,KAAK,MAAM,OAAO,QAAQ,GAAG,MAAM;AAAA,QACtD,SAAS,EAAE,oBAAoB,MAAM;AAAA,MACvC,CAAC;AAAA,IACH,QAAQ;AAEN,cAAQ,IAAI,8BAA8B,IAAI;AAAA,IAChD;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,MAAM,KAAK,OAAO;AAEzC,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,MAAI,SAAS,WAAW,IAAK,QAAO;AAEpC,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAM,IAAI,MAAM,iBAAiB,SAAS,MAAM,KAAK,IAAI,EAAE;AAC7D;","names":["matchesPropertyFilters"]}
1
+ {"version":3,"sources":["../src/CosmosDbProvider.ts","../src/CosmosDbConnection.ts","../src/mapping.ts","../src/queries/repository.ts","../src/queries/vocabulary.ts","../src/queries/entity.ts","../src/queries/relationship.ts","../src/queries/traversal.ts","../src/queries/timeline.ts","../src/queries/bulk.ts"],"sourcesContent":["// CosmosDbProvider — CosmosDB Gremlin implementation of StorageProvider + GraphTraversalProvider\n\nimport type { StorageProvider, EnsureSchemaResult } from '@utaba/deep-memory/providers';\nimport type { GraphTraversalProvider, GraphTraversalCapabilities } from '@utaba/deep-memory/providers';\nimport type {\n StoredEntity,\n StoredEntityUpdate,\n StoredRelationship,\n RelationshipQueryOptions,\n MemoryVocabulary,\n VocabularyChangeRecord,\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n StorageFindQuery,\n StorageExploreOptions,\n StoragePathOptions,\n StorageTimelineOptions,\n PaginationOptions,\n PaginatedResult,\n StorageNeighborhood,\n StoragePathResult,\n StorageTimelineResult,\n BulkImportResult,\n TraversalSpec,\n TraversalResult,\n QueryMetadata,\n} from '@utaba/deep-memory/types';\nimport type { ExportChunk, ImportChunk, BulkImportOptions, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport crypto from 'node:crypto';\nimport { GremlinCompiler, ProviderError } from '@utaba/deep-memory';\nimport { CosmosDbConnection } from './CosmosDbConnection.js';\nimport { entityFromGremlin } from './mapping.js';\nimport * as repoQueries from './queries/repository.js';\nimport * as vocabQueries from './queries/vocabulary.js';\nimport * as entityQueries from './queries/entity.js';\nimport * as relQueries from './queries/relationship.js';\nimport * as traversalQueries from './queries/traversal.js';\nimport * as timelineQueries from './queries/timeline.js';\nimport * as bulkQueries from './queries/bulk.js';\n\n/** Configuration for CosmosDbProvider. */\nexport interface CosmosDbProviderConfig {\n /** Gremlin WebSocket endpoint (e.g. ws://host.docker.internal:8901/) */\n endpoint: string;\n /** CosmosDB REST endpoint for database/container provisioning (e.g. https://host.docker.internal:8081/) — derived from Gremlin endpoint if omitted */\n restEndpoint?: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Partition key path (default: /repositoryId) */\n partitionKey?: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nconst SCHEMA_VERSION = 1;\nconst META_VERTEX_ID = '_meta:schema';\n\n/**\n * CosmosDB Gremlin storage provider for deep-memory.\n * Implements both StorageProvider (full CRUD) and GraphTraversalProvider (native Gremlin traversals).\n */\nexport class CosmosDbProvider implements StorageProvider, GraphTraversalProvider {\n private readonly conn: CosmosDbConnection;\n private readonly config: CosmosDbProviderConfig;\n private readonly compiler = new GremlinCompiler();\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.conn = new CosmosDbConnection({\n endpoint: config.endpoint,\n key: config.key,\n database: config.database,\n container: config.container,\n maxRetries: config.maxRetries,\n defaultTimeoutMs: config.defaultTimeoutMs,\n rejectUnauthorized: config.rejectUnauthorized,\n });\n }\n\n // ─── Lifecycle ─────────────────────────────────────────────────────\n\n async initialize(): Promise<void> {\n await this.conn.connect();\n }\n\n async dispose(): Promise<void> {\n await this.conn.close();\n }\n\n async ensureSchema(): Promise<EnsureSchemaResult> {\n const restBase = this.getRestEndpoint();\n const partitionKey = this.config.partitionKey ?? '/repositoryId';\n let databaseCreated = false;\n let schemaCreated = false;\n\n try {\n // 1. Create database if not exists\n const dbCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n 'dbs',\n '',\n 'dbs',\n { id: this.config.database },\n this.config.rejectUnauthorized ?? true,\n );\n databaseCreated = dbCreated;\n\n // 2. Create Gremlin graph container if not exists\n const containerCreated = await cosmosRestPut(\n restBase,\n this.config.key,\n `dbs/${this.config.database}/colls`,\n `dbs/${this.config.database}`,\n 'colls',\n {\n id: this.config.container,\n partitionKey: { paths: [partitionKey], kind: 'Hash' },\n },\n this.config.rejectUnauthorized ?? true,\n );\n schemaCreated = containerCreated;\n\n // 3. Reconnect Gremlin client (it may have failed before db/container existed)\n await this.conn.close();\n await this.conn.connect();\n\n // 4. Write schema version meta vertex\n const existing = await this.conn.submit(\n \"g.V().has('id', metaId).hasLabel('_meta').valueMap(true)\",\n { metaId: META_VERTEX_ID },\n );\n\n if (existing.items.length > 0) {\n const props = existing.items[0] as Record<string, unknown>;\n const version = Number(unwrapGremlinValue(props['schemaVersion']) ?? 0);\n if (version >= SCHEMA_VERSION && !databaseCreated && !schemaCreated) {\n return {\n databaseCreated: false,\n schemaCreated: false,\n alreadyUpToDate: true,\n schemaVersion: SCHEMA_VERSION,\n };\n }\n await this.conn.submit(\n \"g.V().has('id', metaId).hasLabel('_meta').property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, ver: SCHEMA_VERSION },\n );\n } else {\n await this.conn.submit(\n \"g.addV('_meta').property('id', metaId).property('repositoryId', pk).property('schemaVersion', ver)\",\n { metaId: META_VERTEX_ID, pk: '_system', ver: SCHEMA_VERSION },\n );\n schemaCreated = true;\n }\n\n return {\n databaseCreated,\n schemaCreated,\n alreadyUpToDate: !databaseCreated && !schemaCreated,\n schemaVersion: SCHEMA_VERSION,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Failed to ensure CosmosDB schema: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the CosmosDB REST endpoint is accessible and the Gremlin endpoint is reachable.',\n );\n }\n }\n\n /** Derive the REST endpoint from config — either explicit or from the Gremlin endpoint host. */\n private getRestEndpoint(): string {\n if (this.config.restEndpoint) return this.config.restEndpoint.replace(/\\/+$/, '');\n // Derive from Gremlin endpoint: ws(s)://host:port/ → https://host:8081\n const url = new URL(this.config.endpoint);\n return `https://${url.hostname}:8081`;\n }\n\n // ─── Repository ────────────────────────────────────────────────────\n\n async createRepository(config: StorageRepositoryConfig): Promise<StoredRepository> {\n return repoQueries.createRepository(this.conn, config);\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n return repoQueries.getRepository(this.conn, repositoryId);\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return repoQueries.listRepositories(this.conn, filter);\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n return repoQueries.updateRepository(this.conn, repositoryId, updates);\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n return repoQueries.deleteRepository(this.conn, repositoryId, onProgress);\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n return repoQueries.deleteAllContents(this.conn, repositoryId, onProgress);\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n return repoQueries.getRepositoryStats(this.conn, repositoryId);\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n return vocabQueries.getVocabulary(this.conn, repositoryId);\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n return vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary);\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n return vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options);\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n return entityQueries.createEntity(this.conn, repositoryId, entity);\n }\n\n async getEntity(repositoryId: string, entityId: string): Promise<StoredEntity | null> {\n return entityQueries.getEntity(this.conn, repositoryId, entityId);\n }\n\n async getEntityBySlug(repositoryId: string, slug: string): Promise<StoredEntity | null> {\n return entityQueries.getEntityBySlug(this.conn, repositoryId, slug);\n }\n\n async getEntities(repositoryId: string, entityIds: string[]): Promise<Map<string, StoredEntity>> {\n return entityQueries.getEntities(this.conn, repositoryId, entityIds);\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n return entityQueries.updateEntity(this.conn, repositoryId, entityId, updates);\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n return entityQueries.deleteEntity(this.conn, repositoryId, entityId);\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n return entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType);\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery): Promise<PaginatedResult<StoredEntity>> {\n return entityQueries.findEntities(this.conn, repositoryId, query);\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n return relQueries.createRelationship(this.conn, repositoryId, relationship);\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n return relQueries.getRelationship(this.conn, repositoryId, relationshipId);\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n return relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options);\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n return relQueries.deleteRelationship(this.conn, repositoryId, relationshipId);\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n return relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType);\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighborhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighborhood> {\n return traversalQueries.exploreNeighborhood(this.conn, repositoryId, entityId, options);\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n return traversalQueries.findPaths(this.conn, repositoryId, sourceId, targetId, options);\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n return timelineQueries.getTimeline(this.conn, repositoryId, entityId, options);\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n return bulkQueries.exportAll(this.conn, repositoryId);\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n return bulkQueries.importBulk(this.conn, repositoryId, data, options);\n }\n\n // ─── GraphTraversalProvider ────────────────────────────────────────\n\n getCapabilities(): GraphTraversalCapabilities {\n return {\n supportsNativeQuery: true,\n nativeQueryLanguage: 'gremlin',\n maxTraversalDepth: 10,\n supportsRelationshipPropertyFilters: true,\n supportsEntityPropertyFilters: true,\n supportsAggregation: false,\n supportsRepeat: true,\n supportsDedup: true,\n supportsRelationshipSummary: false,\n };\n }\n\n async traverse(\n repositoryId: string,\n spec: TraversalSpec,\n compiledQuery?: string,\n ): Promise<TraversalResult> {\n const startTime = Date.now();\n\n // Get vocabulary for compilation\n const vocabulary = await this.getVocabulary(repositoryId);\n\n // Compile the spec to Gremlin if no compiled query provided\n const compiled = compiledQuery\n ? { query: compiledQuery, params: {}, estimatedFanOut: 100 }\n : this.compiler.compile(spec, vocabulary);\n\n // Inject repositoryId filter into the query\n // The compiled query starts with g.V(), we need to add repository scoping\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n `g.V().has('repositoryId', '${repositoryId}')`,\n );\n\n try {\n const result = await this.conn.submit(scopedQuery, compiled.params);\n const executionTimeMs = Date.now() - startTime;\n\n const entities: TraversalResult['entities'] = [];\n const relationships: NonNullable<TraversalResult['relationships']> = [];\n const paths: NonNullable<TraversalResult['paths']> = [];\n\n if (spec.returnMode === 'path') {\n // Path results need special parsing\n for (const item of result.items) {\n const pathData = item as { objects?: unknown[] };\n if (pathData.objects) {\n const pathEntities: TraversalResult['entities'] = [];\n for (const obj of pathData.objects) {\n const props = obj as Record<string, unknown>;\n if (props['entityType']) {\n pathEntities.push(entityFromGremlin(props));\n }\n }\n if (pathEntities.length > 0) {\n paths.push({\n length: pathEntities.length - 1,\n entities: pathEntities,\n relationships: [],\n });\n }\n }\n }\n } else {\n // Entity results from valueMap(true)\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n entities.push(entity);\n }\n }\n\n const limit = spec.limit ?? 50;\n const queryMetadata: QueryMetadata = {\n executionTimeMs,\n resourceCost: result.requestCharge != null\n ? { units: 'RU', value: result.requestCharge }\n : undefined,\n compiledQuery: scopedQuery,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: {\n maxResults: limit,\n maxDepth: spec.steps?.length,\n },\n truncated: entities.length >= limit,\n truncationReason: entities.length >= limit ? 'result_limit' : undefined,\n };\n\n return {\n entities: spec.returnMode === 'path' ? [] : entities,\n relationships: spec.returnMode === 'path' || spec.returnMode === 'all' ? relationships : undefined,\n paths: spec.returnMode === 'path' ? paths : undefined,\n total: entities.length + paths.length,\n returned: entities.length + paths.length,\n hasMore: entities.length >= limit || paths.length >= limit,\n queryMetadata,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Gremlin traversal failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Check the traversal spec and ensure the CosmosDB connection is healthy.',\n );\n }\n }\n\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<TraversalResult> {\n const startTime = Date.now();\n\n try {\n const result = await this.conn.submit(query, params);\n const executionTimeMs = Date.now() - startTime;\n\n // Best-effort entity mapping from raw results\n const entities: TraversalResult['entities'] = [];\n for (const item of result.items) {\n try {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n if (entity.id) {\n entities.push(entity);\n }\n } catch {\n // Non-entity results are skipped\n }\n }\n\n const queryMetadata: QueryMetadata = {\n executionTimeMs,\n resourceCost: result.requestCharge != null\n ? { units: 'RU', value: result.requestCharge }\n : undefined,\n compiledQuery: query,\n compiledQueryLanguage: 'gremlin',\n appliedLimits: { maxResults: entities.length },\n truncated: false,\n };\n\n return {\n entities,\n total: entities.length,\n returned: entities.length,\n hasMore: false,\n queryMetadata,\n };\n } catch (err: unknown) {\n throw new ProviderError(\n `Native Gremlin query failed: ${err instanceof Error ? err.message : String(err)}`,\n 'Verify the Gremlin query syntax is valid for CosmosDB.',\n );\n }\n }\n}\n\nfunction unwrapGremlinValue(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n// ─── CosmosDB REST API helpers for database/container provisioning ──\n\n/**\n * Generate a CosmosDB REST API authorization token.\n * See: https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources\n */\nfunction cosmosAuthToken(\n verb: string,\n resourceType: string,\n resourceLink: string,\n date: string,\n key: string,\n): string {\n const payload = `${verb.toLowerCase()}\\n${resourceType.toLowerCase()}\\n${resourceLink}\\n${date.toLowerCase()}\\n\\n`;\n const keyBuffer = Buffer.from(key, 'base64');\n const hmac = crypto.createHmac('sha256', keyBuffer);\n hmac.update(payload);\n const signature = hmac.digest('base64');\n return encodeURIComponent(`type=master&ver=1.0&sig=${signature}`);\n}\n\n/**\n * Create a CosmosDB resource (database or container) via REST API.\n * Returns true if the resource was created, false if it already existed.\n */\nasync function cosmosRestPut(\n restBase: string,\n key: string,\n urlPath: string,\n resourceLink: string,\n resourceType: string,\n body: Record<string, unknown>,\n rejectUnauthorized: boolean,\n): Promise<boolean> {\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', resourceType, resourceLink, date, key);\n\n const url = `${restBase}/${urlPath}`;\n\n // Use Node's native fetch (available in Node 18+)\n const options: RequestInit & { dispatcher?: unknown } = {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2018-12-31',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n };\n\n // For self-signed certs (emulator), we need to disable TLS verification\n if (!rejectUnauthorized) {\n // Use Node.js undici agent to skip TLS verification\n try {\n // @ts-expect-error — Node 18+ fetch supports dispatcher for TLS options\n options.dispatcher = new (await import('undici')).Agent({\n connect: { rejectUnauthorized: false },\n });\n } catch {\n // If undici is not available, set NODE_TLS_REJECT_UNAUTHORIZED as fallback\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n }\n\n const response = await fetch(url, options);\n\n if (response.status === 201) return true; // Created\n if (response.status === 409) return false; // Already exists\n\n const text = await response.text();\n throw new Error(`CosmosDB REST ${response.status}: ${text}`);\n}\n","// CosmosDbConnection — Gremlin client wrapper for CosmosDB\n//\n// Handles WebSocket connection, CosmosDB authentication, TLS for emulator,\n// and retry logic for transient errors (429 throttling, 503 unavailable).\n\n// @ts-expect-error — gremlin has no type declarations\nimport gremlin from 'gremlin';\n\nexport interface CosmosDbConnectionConfig {\n /** Gremlin WebSocket endpoint (e.g. wss://localhost:8901/) */\n endpoint: string;\n /** CosmosDB primary key */\n key: string;\n /** Database name */\n database: string;\n /** Container (graph) name */\n container: string;\n /** Max retries for transient errors (default: 3) */\n maxRetries?: number;\n /** Default query timeout in ms (default: 30000) */\n defaultTimeoutMs?: number;\n /** Whether to reject unauthorized TLS certs — set false for emulator (default: true) */\n rejectUnauthorized?: boolean;\n}\n\nexport interface GremlinResult {\n /** Raw result items */\n items: unknown[];\n /** CosmosDB request charge (RU) from response headers */\n requestCharge?: number;\n}\n\n/**\n * Manages a Gremlin WebSocket connection to CosmosDB.\n * Provides `submit()` for parameterized Gremlin queries with retry on transient errors.\n */\nexport class CosmosDbConnection {\n private client: gremlin.driver.Client | null = null;\n private readonly config: Required<Pick<CosmosDbConnectionConfig, 'maxRetries' | 'defaultTimeoutMs' | 'rejectUnauthorized'>> & CosmosDbConnectionConfig;\n\n constructor(config: CosmosDbConnectionConfig) {\n this.config = {\n ...config,\n maxRetries: config.maxRetries ?? 3,\n defaultTimeoutMs: config.defaultTimeoutMs ?? 30000,\n rejectUnauthorized: config.rejectUnauthorized ?? true,\n };\n }\n\n /** Open the WebSocket connection to CosmosDB Gremlin endpoint. */\n async connect(): Promise<void> {\n if (this.client) return;\n\n const authenticator = new gremlin.driver.auth.PlainTextSaslAuthenticator(\n `/dbs/${this.config.database}/colls/${this.config.container}`,\n this.config.key,\n );\n\n this.client = new gremlin.driver.Client(this.config.endpoint, {\n authenticator,\n traversalsource: 'g',\n rejectUnauthorized: this.config.rejectUnauthorized,\n mimeType: 'application/vnd.gremlin-v2.0+json',\n });\n\n await this.client.open();\n }\n\n /** Close the WebSocket connection. */\n async close(): Promise<void> {\n if (this.client) {\n await this.client.close();\n this.client = null;\n }\n }\n\n /**\n * Submit a parameterized Gremlin query with retry on transient errors.\n * All user values should be passed as bindings (never interpolated into the query string).\n */\n async submit(query: string, bindings?: Record<string, unknown>): Promise<GremlinResult> {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const resultSet = await this.client.submit(query, bindings);\n const items = resultSet.toArray();\n const requestCharge = extractRequestCharge(resultSet);\n return { items, requestCharge };\n } catch (err: unknown) {\n lastError = err;\n if (isTransientError(err) && attempt < this.config.maxRetries) {\n const retryAfterMs = getRetryAfterMs(err, attempt);\n await sleep(retryAfterMs);\n continue;\n }\n throw err;\n }\n }\n throw lastError;\n }\n\n /** Get the underlying Gremlin client (for advanced usage). */\n getClient(): gremlin.driver.Client {\n if (!this.client) {\n throw new Error('CosmosDbConnection: not connected. Call connect() first.');\n }\n return this.client;\n }\n}\n\n/** Check if an error is a transient CosmosDB error (429 or 503). */\nfunction isTransientError(err: unknown): boolean {\n if (err instanceof Error) {\n const msg = err.message;\n // CosmosDB returns status codes in error messages\n if (msg.includes('429') || msg.includes('RequestRateTooLarge')) return true;\n if (msg.includes('503') || msg.includes('ServiceUnavailable')) return true;\n }\n // Check statusCode property if present\n const statusCode = (err as Record<string, unknown>)?.['statusCode'];\n if (statusCode === 429 || statusCode === 503) return true;\n return false;\n}\n\n/** Extract retry-after from error or use exponential backoff. */\nfunction getRetryAfterMs(err: unknown, attempt: number): number {\n // CosmosDB may include x-ms-retry-after-ms in error attributes\n const retryAfter = (err as Record<string, unknown>)?.['retryAfterMs'];\n if (typeof retryAfter === 'number' && retryAfter > 0) {\n return retryAfter;\n }\n // Exponential backoff: 500ms, 1s, 2s, 4s, ...\n return Math.min(500 * Math.pow(2, attempt), 10000);\n}\n\n/** Extract request charge (RU) from a ResultSet's attributes. */\nfunction extractRequestCharge(resultSet: gremlin.driver.ResultSet): number | undefined {\n const attrs = resultSet.attributes as Record<string, unknown> | undefined;\n if (!attrs) return undefined;\n const charge = attrs['x-ms-request-charge'] ?? attrs['x-ms-total-request-charge'];\n return typeof charge === 'number' ? charge : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n","// Mapping — convert between Gremlin results and StoredEntity/StoredRelationship types\n\nimport type { StoredEntity } from '@utaba/deep-memory/types';\nimport type { StoredRelationship } from '@utaba/deep-memory/types';\nimport type { Provenance } from '@utaba/deep-memory/types';\nimport type { StoredRepository, StoredRepositorySummary } from '@utaba/deep-memory/types';\nimport type { GovernanceConfig } from '@utaba/deep-memory/types';\nimport type { VocabularyChangeRecord, MemoryVocabulary } from '@utaba/deep-memory/types';\n\n// ─── Gremlin property extraction ──────────────────────────────────\n\n/**\n * Gremlin valueMap(true) returns properties as arrays (multi-value).\n * CosmosDB single-cardinality means each array has exactly one element.\n * This helper unwraps the first value.\n */\nfunction unwrap(val: unknown): unknown {\n if (Array.isArray(val) && val.length > 0) return val[0];\n return val;\n}\n\n/** Safely unwrap a string value from a Gremlin result. */\nfunction unwrapStr(val: unknown): string {\n const v = unwrap(val);\n return typeof v === 'string' ? v : String(v ?? '');\n}\n\n/** Safely unwrap an optional string. */\nfunction unwrapOptStr(val: unknown): string | undefined {\n const v = unwrap(val);\n return v != null && v !== '' ? String(v) : undefined;\n}\n\n/** Safely parse JSON, returning a default on failure. */\nfunction safeParseJson<T>(val: unknown, fallback: T): T {\n if (val == null) return fallback;\n const str = typeof val === 'string' ? val : String(unwrap(val));\n if (!str || str === '') return fallback;\n try {\n return JSON.parse(str) as T;\n } catch {\n return fallback;\n }\n}\n\n// ─── Provenance ───────────────────────────────────────────────────\n\nfunction provenanceFromGremlin(props: Record<string, unknown>): Provenance {\n return {\n createdBy: unwrapStr(props['createdBy']),\n createdByType: (unwrapStr(props['createdByType']) || 'agent') as 'user' | 'agent',\n createdAt: unwrapStr(props['createdAt']),\n createdInConversation: unwrapOptStr(props['createdInConversation']),\n createdFromMessage: unwrapOptStr(props['createdFromMessage']),\n modifiedBy: unwrapStr(props['modifiedBy']),\n modifiedByType: (unwrapStr(props['modifiedByType']) || 'agent') as 'user' | 'agent',\n modifiedAt: unwrapStr(props['modifiedAt']),\n modifiedInConversation: unwrapOptStr(props['modifiedInConversation']),\n modifiedFromMessage: unwrapOptStr(props['modifiedFromMessage']),\n };\n}\n\n// ─── Entity mapping ───────────────────────────────────────────────\n\nexport function entityFromGremlin(props: Record<string, unknown>): StoredEntity {\n const embeddingStr = unwrapOptStr(props['embedding']);\n return {\n id: unwrapStr(props['id']),\n slug: unwrapStr(props['slug']),\n entityType: unwrapStr(props['entityType']),\n label: unwrapStr(props['entityLabel']),\n summary: unwrapOptStr(props['summary']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n data: unwrapOptStr(props['data']),\n dataFormat: unwrapOptStr(props['dataFormat']),\n provenance: provenanceFromGremlin(props),\n embedding: embeddingStr ? (safeParseJson<number[] | undefined>(embeddingStr, undefined)) : undefined,\n };\n}\n\n// ─── Relationship mapping ─────────────────────────────────────────\n\nexport function relationshipFromGremlin(props: Record<string, unknown>): StoredRelationship {\n const bidir = unwrap(props['bidirectional']);\n return {\n id: unwrapStr(props['id']),\n relationshipType: unwrapStr(props['relationshipType']),\n sourceEntityId: unwrapStr(props['sourceEntityId']),\n targetEntityId: unwrapStr(props['targetEntityId']),\n properties: safeParseJson(unwrap(props['properties']), {}),\n bidirectional: bidir === true || bidir === 'true',\n provenance: provenanceFromGremlin(props),\n };\n}\n\n// ─── Repository mapping ───────────────────────────────────────────\n\nexport function repositoryFromGremlin(props: Record<string, unknown>): StoredRepository {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n legal: unwrapOptStr(props['legal']),\n owner: unwrapOptStr(props['owner']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n metadata: safeParseJson(unwrap(props['metadata']), undefined),\n createdAt: unwrapStr(props['createdAt']),\n createdBy: unwrapStr(props['createdBy']),\n };\n}\n\nexport function repositorySummaryFromGremlin(props: Record<string, unknown>): StoredRepositorySummary {\n return {\n repositoryId: unwrapStr(props['repositoryId']),\n type: unwrapOptStr(props['type']),\n label: unwrapStr(props['repoLabel']),\n description: unwrapOptStr(props['description']),\n governanceConfig: safeParseJson<GovernanceConfig>(unwrap(props['governanceConfig']), { mode: 'open' }),\n };\n}\n\n// ─── Vocabulary mapping ───────────────────────────────────────────\n\nexport function vocabularyFromGremlin(props: Record<string, unknown>): MemoryVocabulary {\n return safeParseJson<MemoryVocabulary>(unwrap(props['vocabulary']), {\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n });\n}\n\nexport function changeRecordFromGremlin(props: Record<string, unknown>): VocabularyChangeRecord {\n return {\n changeId: unwrapStr(props['changeId']),\n changeType: unwrapStr(props['changeType']) as VocabularyChangeRecord['changeType'],\n typeName: unwrapStr(props['typeName']),\n previousVersion: unwrapOptStr(props['previousVersion']),\n newVersion: unwrapStr(props['newVersion']),\n proposedBy: unwrapStr(props['proposedBy']),\n proposedAt: unwrapStr(props['proposedAt']),\n approvedBy: unwrapOptStr(props['approvedBy']),\n approvedAt: unwrapOptStr(props['approvedAt']),\n reason: unwrapStr(props['reason']),\n };\n}\n\n// ─── Property serialization helpers ───────────────────────────────\n\n/** Build a flat property map for a vertex from a StoredEntity. */\nexport function entityToGremlinProps(\n repositoryId: string,\n entity: StoredEntity,\n): Record<string, string | number | boolean> {\n const props: Record<string, string | number | boolean> = {\n repositoryId,\n entityType: entity.entityType,\n entityLabel: entity.label,\n slug: entity.slug,\n properties: JSON.stringify(entity.properties ?? {}),\n createdBy: entity.provenance.createdBy,\n createdByType: entity.provenance.createdByType,\n createdAt: entity.provenance.createdAt,\n modifiedBy: entity.provenance.modifiedBy,\n modifiedByType: entity.provenance.modifiedByType,\n modifiedAt: entity.provenance.modifiedAt,\n };\n if (entity.summary != null) props['summary'] = entity.summary;\n if (entity.data != null) props['data'] = entity.data;\n if (entity.dataFormat != null) props['dataFormat'] = entity.dataFormat;\n if (entity.provenance.createdInConversation != null) props['createdInConversation'] = entity.provenance.createdInConversation;\n if (entity.provenance.createdFromMessage != null) props['createdFromMessage'] = entity.provenance.createdFromMessage;\n if (entity.provenance.modifiedInConversation != null) props['modifiedInConversation'] = entity.provenance.modifiedInConversation;\n if (entity.provenance.modifiedFromMessage != null) props['modifiedFromMessage'] = entity.provenance.modifiedFromMessage;\n if (entity.embedding != null) props['embedding'] = JSON.stringify(entity.embedding);\n return props;\n}\n\n/** Build a flat property map for an edge from a StoredRelationship. */\nexport function relationshipToGremlinProps(\n repositoryId: string,\n rel: StoredRelationship,\n): Record<string, string | number | boolean> {\n const props: Record<string, string | number | boolean> = {\n repositoryId,\n relationshipType: rel.relationshipType,\n sourceEntityId: rel.sourceEntityId,\n targetEntityId: rel.targetEntityId,\n bidirectional: rel.bidirectional,\n properties: JSON.stringify(rel.properties ?? {}),\n createdBy: rel.provenance.createdBy,\n createdByType: rel.provenance.createdByType,\n createdAt: rel.provenance.createdAt,\n modifiedBy: rel.provenance.modifiedBy,\n modifiedByType: rel.provenance.modifiedByType,\n modifiedAt: rel.provenance.modifiedAt,\n };\n if (rel.provenance.createdInConversation != null) props['createdInConversation'] = rel.provenance.createdInConversation;\n if (rel.provenance.createdFromMessage != null) props['createdFromMessage'] = rel.provenance.createdFromMessage;\n if (rel.provenance.modifiedInConversation != null) props['modifiedInConversation'] = rel.provenance.modifiedInConversation;\n if (rel.provenance.modifiedFromMessage != null) props['modifiedFromMessage'] = rel.provenance.modifiedFromMessage;\n return props;\n}\n","// Repository CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageRepositoryConfig,\n StoredRepository,\n StoredRepositorySummary,\n RepositoryFilter,\n RepositoryStats,\n RepositoryUpdate,\n} from '@utaba/deep-memory/types';\nimport type { PaginatedResult, DeleteProgressCallback } from '@utaba/deep-memory/types';\nimport { repositoryFromGremlin, repositorySummaryFromGremlin } from '../mapping.js';\nimport { DuplicateRepositoryError, RepositoryNotFoundError } from '@utaba/deep-memory';\n\nconst REPO_LABEL = '_repository';\n\nfunction repoVertexId(repositoryId: string): string {\n return `repo:${repositoryId}`;\n}\n\n/** Build a .property() chain for Gremlin vertex creation/update. */\nfunction propertyChain(bindings: Record<string, unknown>, props: Record<string, string | number | boolean | null | undefined>, startIndex: number): { chain: string; nextIndex: number } {\n const parts: string[] = [];\n let idx = startIndex;\n for (const [key, value] of Object.entries(props)) {\n if (value == null) continue;\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n parts.push(`.property('${key}', ${paramName})`);\n }\n return { chain: parts.join(''), nextIndex: idx };\n}\n\nexport async function createRepository(\n conn: CosmosDbConnection,\n config: StorageRepositoryConfig,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(config.repositoryId);\n\n // Check for existing\n const existing = await conn.submit(\n \"g.V().has('id', vid).has('label', lbl).count()\",\n { vid: vertexId, lbl: REPO_LABEL },\n );\n if (existing.items.length > 0 && Number(existing.items[0]) > 0) {\n throw new DuplicateRepositoryError(config.repositoryId);\n }\n\n const bindings: Record<string, unknown> = {\n vid: vertexId,\n rid: config.repositoryId,\n };\n\n const props: Record<string, string | number | boolean | null | undefined> = {\n repoLabel: config.label,\n description: config.description,\n type: config.type,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: JSON.stringify(config.governanceConfig),\n metadata: config.metadata ? JSON.stringify(config.metadata) : undefined,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n\n const { chain } = propertyChain(bindings, props, 0);\n\n const query = `g.addV('${REPO_LABEL}').property('id', vid).property('repositoryId', rid)${chain}`;\n await conn.submit(query, bindings);\n\n return {\n repositoryId: config.repositoryId,\n type: config.type,\n label: config.label,\n description: config.description,\n legal: config.legal,\n owner: config.owner,\n governanceConfig: config.governanceConfig,\n metadata: config.metadata,\n createdAt: config.createdAt,\n createdBy: config.createdBy,\n };\n}\n\nexport async function getRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<StoredRepository | null> {\n const result = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_repository').valueMap(true)\",\n { vid: repoVertexId(repositoryId) },\n );\n if (result.items.length === 0) return null;\n return repositoryFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function listRepositories(\n conn: CosmosDbConnection,\n filter?: RepositoryFilter,\n): Promise<PaginatedResult<StoredRepositorySummary>> {\n const limit = filter?.limit ?? 20;\n const offset = filter?.offset ?? 0;\n\n let countQuery = \"g.V().hasLabel('_repository')\";\n let dataQuery = \"g.V().hasLabel('_repository')\";\n const bindings: Record<string, unknown> = {};\n\n if (filter?.type) {\n countQuery += \".has('type', filterType)\";\n dataQuery += \".has('type', filterType)\";\n bindings['filterType'] = filter.type;\n }\n\n const countResult = await conn.submit(`${countQuery}.count()`, bindings);\n const total = Number(countResult.items[0] ?? 0);\n\n bindings['rangeStart'] = offset;\n bindings['rangeEnd'] = offset + limit;\n const dataResult = await conn.submit(\n `${dataQuery}.range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n const items = (dataResult.items as Record<string, unknown>[]).map(repositorySummaryFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n\nexport async function updateRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n updates: RepositoryUpdate,\n): Promise<StoredRepository> {\n const vertexId = repoVertexId(repositoryId);\n\n // Verify exists\n const existing = await getRepository(conn, repositoryId);\n if (!existing) throw new RepositoryNotFoundError(repositoryId);\n\n const bindings: Record<string, unknown> = { vid: vertexId };\n const props: Record<string, string | number | boolean | null | undefined> = {};\n\n if (updates.label !== undefined) props['repoLabel'] = updates.label;\n if (updates.description !== undefined) props['description'] = updates.description;\n if (updates.type !== undefined) props['type'] = updates.type;\n if (updates.legal !== undefined) props['legal'] = updates.legal;\n if (updates.owner !== undefined) props['owner'] = updates.owner;\n if (updates.governanceConfig !== undefined) props['governanceConfig'] = JSON.stringify(updates.governanceConfig);\n if (updates.metadata !== undefined) {\n // Shallow merge with existing metadata\n const merged = { ...existing.metadata, ...updates.metadata };\n props['metadata'] = JSON.stringify(merged);\n }\n\n if (Object.keys(props).length === 0) return existing;\n\n const { chain } = propertyChain(bindings, props, 0);\n const query = `g.V().has('id', vid).hasLabel('_repository')${chain}`;\n await conn.submit(query, bindings);\n\n return (await getRepository(conn, repositoryId))!;\n}\n\nconst DELETE_BATCH_SIZE = 500;\n\nexport async function deleteRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<void> {\n // Get totals for progress reporting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then all vertices, in batches.\n // A single unbounded drop() times out on large repositories.\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n}\n\nexport async function deleteAllContents(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count before deleting\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').count()\",\n { rid: repositoryId },\n );\n const totalEntities = Number(entityCountResult.items[0] ?? 0);\n\n const relCountResult = await conn.submit(\n \"g.E().has('repositoryId', rid).count()\",\n { rid: repositoryId },\n );\n const totalRelationships = Number(relCountResult.items[0] ?? 0);\n\n let relationshipsDeleted = 0;\n let entitiesDeleted = 0;\n\n // Drop edges first (avoids orphan-edge errors), then entity vertices, in batches.\n // Preserves system vertices (_repository, _vocabulary).\n while (true) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.E().has('repositoryId', rid).limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n relationshipsDeleted = totalRelationships - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n while (true) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(batchSize).drop()\",\n { rid: repositoryId, batchSize: DELETE_BATCH_SIZE },\n );\n const remaining = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').limit(1).count()\",\n { rid: repositoryId },\n );\n const remainingCount = Number(remaining.items[0] ?? 0);\n entitiesDeleted = totalEntities - remainingCount;\n await onProgress?.({ entitiesDeleted, relationshipsDeleted, totalEntities, totalRelationships });\n if (remainingCount === 0) break;\n }\n\n return { deletedEntities: totalEntities, deletedRelationships: totalRelationships };\n}\n\nexport async function getRepositoryStats(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<RepositoryStats> {\n // Get vocabulary version\n const vocabResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabulary').values('vocabulary')\",\n { rid: repositoryId },\n );\n let vocabVersion = '0.0.0';\n if (vocabResult.items.length > 0) {\n try {\n const vocab = JSON.parse(vocabResult.items[0] as string);\n vocabVersion = vocab.version ?? '0.0.0';\n } catch { /* default */ }\n }\n\n // Count entities by type (exclude system vertices)\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').group().by('entityType').by(count())\",\n { rid: repositoryId },\n );\n const entityTypeBreakdown: Record<string, number> = {};\n let entityCount = 0;\n if (entityResult.items.length > 0) {\n const grouped = entityResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n entityTypeBreakdown[type] = Number(count);\n entityCount += Number(count);\n }\n }\n\n // Count relationships by type\n const relResult = await conn.submit(\n \"g.E().has('repositoryId', rid).group().by('relationshipType').by(count())\",\n { rid: repositoryId },\n );\n const relationshipTypeBreakdown: Record<string, number> = {};\n let relationshipCount = 0;\n if (relResult.items.length > 0) {\n const grouped = relResult.items[0] as Record<string, number>;\n for (const [type, count] of Object.entries(grouped)) {\n relationshipTypeBreakdown[type] = Number(count);\n relationshipCount += Number(count);\n }\n }\n\n return {\n entityCount,\n relationshipCount,\n vocabularyVersion: vocabVersion,\n entityTypeBreakdown,\n relationshipTypeBreakdown,\n };\n}\n","// Vocabulary Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { MemoryVocabulary, VocabularyChangeRecord } from '@utaba/deep-memory/types';\nimport type { PaginationOptions, PaginatedResult } from '@utaba/deep-memory/types';\nimport { vocabularyFromGremlin, changeRecordFromGremlin } from '../mapping.js';\n\nfunction vocabVertexId(repositoryId: string): string {\n return `vocab:${repositoryId}`;\n}\n\nexport async function getVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n): Promise<MemoryVocabulary> {\n const result = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').valueMap(true)\",\n { vid: vocabVertexId(repositoryId) },\n );\n if (result.items.length === 0) {\n // Return default empty vocabulary\n return {\n version: '0.0.0',\n lastModified: new Date().toISOString(),\n modifiedBy: 'system',\n entityTypes: [],\n relationshipTypes: [],\n };\n }\n return vocabularyFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function saveVocabulary(\n conn: CosmosDbConnection,\n repositoryId: string,\n vocabulary: MemoryVocabulary,\n): Promise<void> {\n const vid = vocabVertexId(repositoryId);\n const vocabJson = JSON.stringify(vocabulary);\n\n // Upsert: try to update existing, create if not found\n const existing = await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').count()\",\n { vid },\n );\n\n if (Number(existing.items[0] ?? 0) > 0) {\n await conn.submit(\n \"g.V().has('id', vid).hasLabel('_vocabulary').property('vocabulary', vocabJson)\",\n { vid, vocabJson },\n );\n } else {\n await conn.submit(\n \"g.addV('_vocabulary').property('id', vid).property('repositoryId', rid).property('vocabulary', vocabJson)\",\n { vid, rid: repositoryId, vocabJson },\n );\n }\n}\n\nexport async function getVocabularyChangeLog(\n conn: CosmosDbConnection,\n repositoryId: string,\n options?: PaginationOptions,\n): Promise<PaginatedResult<VocabularyChangeRecord>> {\n const limit = options?.limit ?? 10;\n const offset = options?.offset ?? 0;\n\n const countResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').count()\",\n { rid: repositoryId },\n );\n const total = Number(countResult.items[0] ?? 0);\n\n const dataResult = await conn.submit(\n \"g.V().has('repositoryId', rid).hasLabel('_vocabularyChangeLog').order().by('proposedAt', decr).range(rangeStart, rangeEnd).valueMap(true)\",\n { rid: repositoryId, rangeStart: offset, rangeEnd: offset + limit },\n );\n\n const items = (dataResult.items as Record<string, unknown>[]).map(changeRecordFromGremlin);\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n","// Entity CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredEntity, StoredEntityUpdate } from '@utaba/deep-memory/types';\nimport type { StorageFindQuery, PaginatedResult } from '@utaba/deep-memory/types';\nimport { entityFromGremlin, entityToGremlinProps } from '../mapping.js';\nimport { DuplicateEntityError } from '@utaba/deep-memory';\n\nexport async function createEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<StoredEntity> {\n // Check for duplicate\n const existing = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).count()\",\n { rid: repositoryId, eid: entity.id },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n throw new DuplicateEntityError(entity.id);\n }\n\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = { vid: entity.id };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // Use entityType as the vertex label for Gremlin graph semantics\n bindings['vertexLabel'] = entity.entityType;\n const query = `g.addV(vertexLabel).property('id', vid)${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return entity;\n}\n\nexport async function getEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap(true)\",\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityBySlug(\n conn: CosmosDbConnection,\n repositoryId: string,\n slug: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('slug', slugVal).has('entityType').valueMap(true)\",\n { rid: repositoryId, slugVal: slug },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityIds: string[],\n): Promise<Map<string, StoredEntity>> {\n if (entityIds.length === 0) return new Map();\n\n // Build within() clause with individual params\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n entityIds.forEach((id, i) => {\n const paramName = `eid${i}`;\n bindings[paramName] = id;\n idParams.push(paramName);\n });\n\n const withinClause = `within(${idParams.join(', ')})`;\n const result = await conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${withinClause}).has('entityType').valueMap(true)`,\n bindings,\n );\n\n const map = new Map<string, StoredEntity>();\n for (const item of result.items) {\n const entity = entityFromGremlin(item as Record<string, unknown>);\n map.set(entity.id, entity);\n }\n return map;\n}\n\nexport async function updateEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n updates: StoredEntityUpdate,\n): Promise<StoredEntity> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n const propParts: string[] = [];\n let idx = 0;\n\n const addProp = (key: string, value: string | number | boolean) => {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n };\n\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat !== undefined) addProp('dataFormat', updates.dataFormat);\n if (updates.embedding !== undefined) addProp('embedding', JSON.stringify(updates.embedding));\n\n // Provenance\n addProp('modifiedBy', updates.provenance.modifiedBy);\n addProp('modifiedByType', updates.provenance.modifiedByType);\n addProp('modifiedAt', updates.provenance.modifiedAt);\n if (updates.provenance.modifiedInConversation != null) addProp('modifiedInConversation', updates.provenance.modifiedInConversation);\n if (updates.provenance.modifiedFromMessage != null) addProp('modifiedFromMessage', updates.provenance.modifiedFromMessage);\n\n const query = `g.V().has('repositoryId', rid).has('id', eid).has('entityType')${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return (await getEntity(conn, repositoryId, entityId))!;\n}\n\nexport async function deleteEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<void> {\n // Gremlin drop() on a vertex also drops connected edges\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').drop()\",\n { rid: repositoryId, eid: entityId },\n );\n}\n\nexport async function deleteEntitiesByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityType: string,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n // Count entities of this type\n const entityCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).count()\",\n { rid: repositoryId, etype: entityType },\n );\n const deletedEntities = Number(entityCountResult.items[0] ?? 0);\n\n // Count relationships connected to these entities\n const relCountResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).bothE().dedup().count()\",\n { rid: repositoryId, etype: entityType },\n );\n const deletedRelationships = Number(relCountResult.items[0] ?? 0);\n\n // Drop the vertices (and their edges)\n if (deletedEntities > 0) {\n await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType', etype).drop()\",\n { rid: repositoryId, etype: entityType },\n );\n }\n\n return { deletedEntities, deletedRelationships };\n}\n\nexport async function findEntities(\n conn: CosmosDbConnection,\n repositoryId: string,\n query: StorageFindQuery,\n): Promise<PaginatedResult<StoredEntity>> {\n const bindings: Record<string, unknown> = { rid: repositoryId };\n let filterClause = \".has('repositoryId', rid).has('entityType')\";\n\n // Entity type filter\n if (query.entityTypes && query.entityTypes.length > 0) {\n const typeParams: string[] = [];\n query.entityTypes.forEach((t, i) => {\n const paramName = `etype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n filterClause += `.has('entityType', within(${typeParams.join(', ')}))`;\n }\n\n // Search term filter — case-insensitive via TextP.containing() (limited in CosmosDB)\n if (query.searchTerm) {\n bindings['searchTerm'] = query.searchTerm.toLowerCase();\n // CosmosDB Gremlin doesn't have case-insensitive text matching natively.\n // We filter on the server with containing() on entityLabel, then post-filter for case.\n // Since slugs are lowercase, search on slug as a workaround for case-insensitive match.\n filterClause += \".has('slug', containing(searchTerm))\";\n }\n\n // Property filters — stored as JSON in Gremlin, so handled via post-filtering below\n\n // Count\n const countResult = await conn.submit(\n `g.V()${filterClause}.count()`,\n bindings,\n );\n const total = Number(countResult.items[0] ?? 0);\n\n // Data\n bindings['rangeStart'] = query.offset;\n bindings['rangeEnd'] = query.offset + query.limit;\n const dataResult = await conn.submit(\n `g.V()${filterClause}.range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n let items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\n\n // Post-filter for property matches (stored as JSON)\n if (query.properties && Object.keys(query.properties).length > 0) {\n items = items.filter(entity => {\n for (const [key, value] of Object.entries(query.properties!)) {\n if (entity.properties[key] !== value) return false;\n }\n return true;\n });\n }\n\n return {\n items,\n total,\n hasMore: query.offset + query.limit < total,\n limit: query.limit,\n offset: query.offset,\n };\n}\n","// Relationship CRUD Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StoredRelationship, RelationshipQueryOptions } from '@utaba/deep-memory/types';\nimport type { PaginatedResult } from '@utaba/deep-memory/types';\nimport { relationshipFromGremlin, relationshipToGremlinProps } from '../mapping.js';\nimport { DuplicateRelationshipError, matchesPropertyFilters } from '@utaba/deep-memory';\n\nexport async function createRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationship: StoredRelationship,\n): Promise<StoredRelationship> {\n // Check for duplicate\n const existing = await conn.submit(\n \"g.E().has('id', relId).count()\",\n { relId: relationship.id },\n );\n if (Number(existing.items[0] ?? 0) > 0) {\n throw new DuplicateRelationshipError(relationship.id);\n }\n\n const props = relationshipToGremlinProps(repositoryId, relationship);\n const bindings: Record<string, unknown> = {\n relId: relationship.id,\n srcId: relationship.sourceEntityId,\n tgtId: relationship.targetEntityId,\n rid: repositoryId,\n edgeLabel: relationship.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // addE requires source and target vertex references\n const query = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n await conn.submit(query, bindings);\n\n return relationship;\n}\n\nexport async function getRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<StoredRelationship | null> {\n const result = await conn.submit(\n \"g.E().has('id', relId).has('repositoryId', rid).valueMap(true)\",\n { relId: relationshipId, rid: repositoryId },\n );\n if (result.items.length === 0) return null;\n return relationshipFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\nexport async function getEntityRelationships(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options?: RelationshipQueryOptions,\n): Promise<PaginatedResult<StoredRelationship>> {\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n const direction = options?.direction ?? 'both';\n\n const bindings: Record<string, unknown> = {\n rid: repositoryId,\n eid: entityId,\n };\n\n // Build edge traversal based on direction\n let edgeTraversal: string;\n switch (direction) {\n case 'outbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').outE()\";\n break;\n case 'inbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').inE()\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n break;\n }\n\n // Filter by relationship types\n let typeFilter = '';\n if (options?.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n // For bidirectional support in outbound/inbound:\n // When direction is 'outbound', include inbound edges that are bidirectional\n // When direction is 'inbound', include outbound edges that are bidirectional\n // This requires a union approach.\n let unionQuery: string | null = null;\n if (direction === 'outbound') {\n // outE + inE where bidirectional=true\n unionQuery = `g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(outE()${typeFilter}, inE()${typeFilter}.has('bidirectional', true))`;\n } else if (direction === 'inbound') {\n unionQuery = `g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(inE()${typeFilter}, outE()${typeFilter}.has('bidirectional', true))`;\n }\n\n const baseQuery = unionQuery ?? `${edgeTraversal}${typeFilter}`;\n\n // Count\n const countResult = await conn.submit(`${baseQuery}.dedup().count()`, bindings);\n const total = Number(countResult.items[0] ?? 0);\n\n // Data\n bindings['rangeStart'] = offset;\n bindings['rangeEnd'] = offset + limit;\n const dataResult = await conn.submit(\n `${baseQuery}.dedup().range(rangeStart, rangeEnd).valueMap(true)`,\n bindings,\n );\n\n let items = (dataResult.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Post-filter by property filters\n if (options?.propertyFilters && options.propertyFilters.length > 0) {\n items = items.filter(rel => matchesPropertyFilters(rel.properties, options.propertyFilters!));\n }\n\n return {\n items,\n total,\n hasMore: offset + limit < total,\n limit,\n offset,\n };\n}\n\nexport async function deleteRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipId: string,\n): Promise<void> {\n await conn.submit(\n \"g.E().has('id', relId).has('repositoryId', rid).drop()\",\n { relId: relationshipId, rid: repositoryId },\n );\n}\n\nexport async function deleteRelationshipsByType(\n conn: CosmosDbConnection,\n repositoryId: string,\n relationshipType: string,\n): Promise<{ deletedRelationships: number }> {\n const countResult = await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype).count()\",\n { rid: repositoryId, rtype: relationshipType },\n );\n const deletedRelationships = Number(countResult.items[0] ?? 0);\n\n if (deletedRelationships > 0) {\n await conn.submit(\n \"g.E().has('repositoryId', rid).hasLabel(rtype).drop()\",\n { rid: repositoryId, rtype: relationshipType },\n );\n }\n\n return { deletedRelationships };\n}\n","// Graph traversal + neighborhood + path Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type {\n StorageExploreOptions,\n StoragePathOptions,\n} from '@utaba/deep-memory/types';\nimport type {\n StorageNeighborhood,\n StorageNeighborhoodLayer,\n StoragePathResult,\n StoragePath,\n StoredEntity,\n StoredRelationship,\n} from '@utaba/deep-memory/types';\nimport { entityFromGremlin, relationshipFromGremlin } from '../mapping.js';\nimport { matchesPropertyFilters } from '@utaba/deep-memory';\n\n/**\n * Explore neighborhood using BFS layer-by-layer.\n * Each layer fetches relationships from the frontier, then loads connected entities.\n */\nexport async function exploreNeighborhood(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n): Promise<StorageNeighborhood> {\n const layers: StorageNeighborhoodLayer[] = [];\n let frontier = new Set<string>([entityId]);\n const visited = new Set<string>([entityId]);\n\n for (let depth = 0; depth < options.depth; depth++) {\n const layer: StorageNeighborhoodLayer = {};\n const nextFrontier = new Set<string>();\n\n for (const currentId of frontier) {\n // Get relationships from this entity\n const rels = await getRelationshipsForEntity(conn, repositoryId, currentId, options);\n\n for (const rel of rels) {\n const relType = rel.relationshipType;\n if (!layer[relType]) {\n layer[relType] = { total: 0, entities: [], relationships: [] };\n }\n\n // Determine the connected entity ID\n let connectedId: string;\n if (rel.sourceEntityId === currentId) {\n connectedId = rel.targetEntityId;\n } else {\n connectedId = rel.sourceEntityId;\n }\n\n if (!visited.has(connectedId)) {\n // Check entity type filter\n if (options.entityTypes && options.entityTypes.length > 0) {\n const entity = await getEntityLight(conn, repositoryId, connectedId);\n if (!entity || !options.entityTypes.includes(entity.entityType)) continue;\n layer[relType]!.entities.push(entity);\n } else {\n const entity = await getEntityLight(conn, repositoryId, connectedId);\n if (entity) {\n layer[relType]!.entities.push(entity);\n }\n }\n\n visited.add(connectedId);\n nextFrontier.add(connectedId);\n }\n\n layer[relType]!.relationships.push(rel);\n layer[relType]!.total = layer[relType]!.entities.length;\n }\n }\n\n // Apply limitPerType\n for (const relType of Object.keys(layer)) {\n const group = layer[relType]!;\n const start = options.offsetPerType;\n const end = start + options.limitPerType;\n group.entities = group.entities.slice(start, end);\n group.relationships = group.relationships.slice(start, end);\n }\n\n if (Object.keys(layer).length > 0) {\n layers.push(layer);\n }\n frontier = nextFrontier;\n\n if (frontier.size === 0) break;\n }\n\n return { centerId: entityId, layers };\n}\n\n/** Get relationships for a single entity with direction and type filtering. */\nasync function getRelationshipsForEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageExploreOptions,\n): Promise<StoredRelationship[]> {\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: entityId };\n\n let edgeTraversal: string;\n switch (options.direction) {\n case 'outbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(outE(), inE().has('bidirectional', true))\";\n break;\n case 'inbound':\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').union(inE(), outE().has('bidirectional', true))\";\n break;\n case 'both':\n default:\n edgeTraversal = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n break;\n }\n\n let typeFilter = '';\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n typeFilter = `.hasLabel(${typeParams.join(', ')})`;\n }\n\n const result = await conn.submit(\n `${edgeTraversal}${typeFilter}.dedup().valueMap(true)`,\n bindings,\n );\n\n let rels = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Apply relationship property filters\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n rels = rels.filter(rel => matchesPropertyFilters(rel.properties, options.relationshipPropertyFilters!));\n }\n\n return rels;\n}\n\n/** Get a single entity without embedding (light). */\nasync function getEntityLight(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n): Promise<StoredEntity | null> {\n const result = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap(true)\",\n { rid: repositoryId, eid: entityId },\n );\n if (result.items.length === 0) return null;\n return entityFromGremlin(result.items[0] as Record<string, unknown>);\n}\n\n/**\n * Find paths between two entities using BFS.\n * Gremlin native path() with simplePath() prevents cycles.\n */\nexport async function findPaths(\n conn: CosmosDbConnection,\n repositoryId: string,\n sourceId: string,\n targetId: string,\n options: StoragePathOptions,\n): Promise<StoragePathResult> {\n // BFS approach layer by layer to find paths\n const paths: StoragePath[] = [];\n const maxDepth = options.maxDepth;\n const limit = options.limit;\n\n // Use application-level BFS to find paths\n // This is more reliable across CosmosDB Gremlin subset limitations\n interface BfsState {\n entityId: string;\n path: string[];\n relationshipIds: string[];\n }\n\n let queue: BfsState[] = [{ entityId: sourceId, path: [sourceId], relationshipIds: [] }];\n\n for (let depth = 0; depth < maxDepth && paths.length < limit; depth++) {\n const nextQueue: BfsState[] = [];\n\n for (const state of queue) {\n if (paths.length >= limit) break;\n\n // Get all relationships for current entity (both directions)\n const bindings: Record<string, unknown> = { rid: repositoryId, eid: state.entityId };\n let edgeQuery = \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE()\";\n\n if (options.relationshipTypes && options.relationshipTypes.length > 0) {\n const typeParams: string[] = [];\n options.relationshipTypes.forEach((t, i) => {\n const paramName = `rtype${i}`;\n bindings[paramName] = t;\n typeParams.push(paramName);\n });\n edgeQuery += `.hasLabel(${typeParams.join(', ')})`;\n }\n\n const relResult = await conn.submit(`${edgeQuery}.valueMap(true)`, bindings);\n const rels = (relResult.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n\n // Filter by relationship property filters\n let filteredRels = rels;\n if (options.relationshipPropertyFilters && options.relationshipPropertyFilters.length > 0) {\n filteredRels = rels.filter(r => matchesPropertyFilters(r.properties, options.relationshipPropertyFilters!));\n }\n\n for (const rel of filteredRels) {\n const nextId = rel.sourceEntityId === state.entityId\n ? rel.targetEntityId\n : rel.sourceEntityId;\n\n // Prevent cycles\n if (state.path.includes(nextId)) continue;\n\n // Entity type filter\n if (options.entityTypes && options.entityTypes.length > 0 && nextId !== targetId) {\n const entity = await getEntityLight(conn, repositoryId, nextId);\n if (!entity || !options.entityTypes.includes(entity.entityType)) continue;\n }\n\n const newPath = [...state.path, nextId];\n const newRelIds = [...state.relationshipIds, rel.id];\n\n if (nextId === targetId) {\n paths.push({ entityIds: newPath, relationshipIds: newRelIds });\n if (paths.length >= limit) break;\n } else {\n nextQueue.push({ entityId: nextId, path: newPath, relationshipIds: newRelIds });\n }\n }\n }\n\n queue = nextQueue;\n if (queue.length === 0) break;\n }\n\n return {\n paths,\n totalPaths: paths.length,\n };\n}\n","// Timeline Gremlin queries\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { StorageTimelineOptions } from '@utaba/deep-memory/types';\nimport type { StorageTimelineResult, StorageTimelineEvent } from '@utaba/deep-memory/types';\n\nexport async function getTimeline(\n conn: CosmosDbConnection,\n repositoryId: string,\n entityId: string,\n options: StorageTimelineOptions,\n): Promise<StorageTimelineResult> {\n const events: StorageTimelineEvent[] = [];\n\n // Entity creation event\n const entityResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').valueMap('createdAt', 'modifiedAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n if (entityResult.items.length > 0) {\n const props = entityResult.items[0] as Record<string, unknown>;\n const createdAt = unwrapValue(props['createdAt']);\n const modifiedAt = unwrapValue(props['modifiedAt']);\n\n if (createdAt && isInTimeRange(createdAt, options.timeRange)) {\n events.push({\n timestamp: createdAt,\n eventType: 'entity_created',\n entityId,\n });\n }\n if (modifiedAt && modifiedAt !== createdAt && isInTimeRange(modifiedAt, options.timeRange)) {\n events.push({\n timestamp: modifiedAt,\n eventType: 'entity_modified',\n entityId,\n });\n }\n }\n\n // Relationship events connected to this entity\n const relResult = await conn.submit(\n \"g.V().has('repositoryId', rid).has('id', eid).has('entityType').bothE().valueMap('id', 'createdAt')\",\n { rid: repositoryId, eid: entityId },\n );\n\n for (const item of relResult.items) {\n const props = item as Record<string, unknown>;\n const relId = unwrapValue(props['id']);\n const relCreatedAt = unwrapValue(props['createdAt']);\n\n if (relCreatedAt && isInTimeRange(relCreatedAt, options.timeRange)) {\n events.push({\n timestamp: relCreatedAt,\n eventType: 'relationship_created',\n entityId,\n relationshipId: relId,\n });\n }\n }\n\n // Sort by timestamp descending\n events.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n\n // Filter by event types\n let filtered = events;\n if (options.eventTypes && options.eventTypes.length > 0) {\n filtered = events.filter(e => options.eventTypes!.includes(e.eventType));\n }\n\n const total = filtered.length;\n const paged = filtered.slice(options.offset, options.offset + options.limit);\n\n return { events: paged, total };\n}\n\nfunction unwrapValue(val: unknown): string {\n if (Array.isArray(val) && val.length > 0) return String(val[0]);\n return String(val ?? '');\n}\n\nfunction isInTimeRange(\n timestamp: string,\n timeRange?: { from: string; to: string },\n): boolean {\n if (!timeRange) return true;\n return timestamp >= timeRange.from && timestamp <= timeRange.to;\n}\n","// Bulk export/import Gremlin queries — optimized for throughput\n//\n// Import optimizations:\n// 1. Parallel execution with concurrency limiter (avoids sequential round-trips)\n// 2. Direct addV/addE when skipExistenceCheck is true (no existence query needed)\n// 3. Gremlin coalesce pattern for atomic upserts when existence checks are needed\n// (1 query instead of 2)\n//\n// Export optimizations:\n// 1. Cursor-based pagination using ID ordering instead of offset-based range()\n// (avoids O(n²) scan on large repositories)\n\nimport type { CosmosDbConnection } from '../CosmosDbConnection.js';\nimport type { ExportChunk, ImportChunk, BulkImportOptions } from '@utaba/deep-memory/types';\nimport type { BulkImportResult, StoredEntity, StoredRelationship } from '@utaba/deep-memory/types';\nimport { entityFromGremlin, entityToGremlinProps, relationshipFromGremlin, relationshipToGremlinProps } from '../mapping.js';\n\nconst EXPORT_BATCH_SIZE = 100;\nconst IMPORT_CONCURRENCY = 20;\n\n// ─── Concurrency limiter ─────────────────────────────────────────\n\n/**\n * Run async tasks with a maximum concurrency limit.\n * Returns results in the same order as the input items.\n */\nasync function runWithConcurrency<T, R>(\n items: T[],\n concurrency: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = new Array(items.length);\n let nextIndex = 0;\n const workers: Promise<void>[] = [];\n\n for (let w = 0; w < Math.min(concurrency, items.length); w++) {\n workers.push(\n (async () => {\n while (nextIndex < items.length) {\n const idx = nextIndex++;\n results[idx] = await fn(items[idx]!);\n }\n })(),\n );\n }\n\n await Promise.all(workers);\n return results;\n}\n\n// ─── Export ──────────────────────────────────────────────────────\n\nexport async function* exportAll(\n conn: CosmosDbConnection,\n repositoryId: string,\n): AsyncIterable<ExportChunk> {\n let sequence = 0;\n\n // Export entities using cursor-based pagination (ordered by id)\n let cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.V().has('repositoryId', rid).has('entityType').has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const entities = (result.items as Record<string, unknown>[]).map(entityFromGremlin);\n const isLast = entities.length < EXPORT_BATCH_SIZE;\n\n if (entities.length > 0) {\n cursor = entities[entities.length - 1]!.id;\n yield {\n type: 'entities',\n data: entities,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // Export relationships using cursor-based pagination (ordered by id)\n cursor = '';\n while (true) {\n const result = cursor === ''\n ? await conn.submit(\n \"g.E().has('repositoryId', rid).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, batchSize: EXPORT_BATCH_SIZE },\n )\n : await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', gt(cursor)).order().by('id').limit(batchSize).valueMap(true)\",\n { rid: repositoryId, cursor, batchSize: EXPORT_BATCH_SIZE },\n );\n\n const relationships = (result.items as Record<string, unknown>[]).map(relationshipFromGremlin);\n const isLast = relationships.length < EXPORT_BATCH_SIZE;\n\n if (relationships.length > 0) {\n cursor = relationships[relationships.length - 1]!.id;\n yield {\n type: 'relationships',\n data: relationships,\n sequence: sequence++,\n isLast,\n };\n }\n\n if (isLast) break;\n }\n\n // If nothing was yielded, yield an empty final chunk\n if (sequence === 0) {\n yield {\n type: 'entities',\n data: [],\n sequence: 0,\n isLast: true,\n };\n }\n}\n\n// ─── Import ─────────────────────────────────────────────────────\n\nexport async function importBulk(\n conn: CosmosDbConnection,\n repositoryId: string,\n data: ImportChunk[],\n options?: BulkImportOptions,\n): Promise<BulkImportResult> {\n let entitiesImported = 0;\n let relationshipsImported = 0;\n const errors: Array<{ item: string; error: string }> = [];\n const skipCheck = options?.skipExistenceCheck ?? false;\n\n for (const chunk of data) {\n // Import entities in parallel\n if (chunk.entities && chunk.entities.length > 0) {\n const results = await runWithConcurrency(\n chunk.entities,\n IMPORT_CONCURRENCY,\n async (entity): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertEntity(conn, repositoryId, entity);\n } else {\n await upsertEntity(conn, repositoryId, entity);\n }\n return { ok: true, id: entity.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: entity.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n entitiesImported++;\n } else {\n errors.push({ item: `entity:${r.id}`, error: r.error! });\n }\n }\n }\n\n // Import relationships in parallel\n if (chunk.relationships && chunk.relationships.length > 0) {\n const results = await runWithConcurrency(\n chunk.relationships,\n IMPORT_CONCURRENCY,\n async (rel): Promise<{ ok: boolean; id: string; error?: string }> => {\n try {\n if (skipCheck) {\n await insertRelationship(conn, repositoryId, rel);\n } else {\n await upsertRelationship(conn, repositoryId, rel);\n }\n return { ok: true, id: rel.id };\n } catch (err: unknown) {\n return {\n ok: false,\n id: rel.id,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n },\n );\n\n for (const r of results) {\n if (r.ok) {\n relationshipsImported++;\n } else {\n errors.push({ item: `relationship:${r.id}`, error: r.error! });\n }\n }\n }\n }\n\n return { entitiesImported, relationshipsImported, errors };\n}\n\n// ─── Direct insert (no existence check) ─────────────────────────\n\n/** Insert an entity directly — assumes it does not exist. */\nasync function insertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = {\n vid: entity.id,\n vertexLabel: entity.entityType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n const query = `g.addV(vertexLabel).property('id', vid)${propParts.join('')}`;\n await conn.submit(query, bindings);\n}\n\n/** Insert a relationship directly — assumes it does not exist. */\nasync function insertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const props = relationshipToGremlinProps(repositoryId, rel);\n const bindings: Record<string, unknown> = {\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n rid: repositoryId,\n edgeLabel: rel.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n const query = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n await conn.submit(query, bindings);\n}\n\n// ─── Atomic upsert (single query with coalesce) ─────────────────\n\n/**\n * Upsert an entity using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n */\nasync function upsertEntity(\n conn: CosmosDbConnection,\n repositoryId: string,\n entity: StoredEntity,\n): Promise<void> {\n const props = entityToGremlinProps(repositoryId, entity);\n const bindings: Record<string, unknown> = {\n vid: entity.id,\n rid: repositoryId,\n vertexLabel: entity.entityType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // coalesce: find existing → update it, or create new\n const query = `g.V().has('repositoryId', rid).has('id', vid).has('entityType').fold().coalesce(unfold()${propParts.join('')}, addV(vertexLabel).property('id', vid)${propParts.join('')})`;\n await conn.submit(query, bindings);\n}\n\n/**\n * Upsert a relationship using Gremlin's coalesce pattern — single query.\n * Replaces the old 2-query check-then-create/update approach.\n */\nasync function upsertRelationship(\n conn: CosmosDbConnection,\n repositoryId: string,\n rel: StoredRelationship,\n): Promise<void> {\n const props = relationshipToGremlinProps(repositoryId, rel);\n const bindings: Record<string, unknown> = {\n relId: rel.id,\n srcId: rel.sourceEntityId,\n tgtId: rel.targetEntityId,\n rid: repositoryId,\n edgeLabel: rel.relationshipType,\n };\n const propParts: string[] = [];\n let idx = 0;\n\n for (const [key, value] of Object.entries(props)) {\n const paramName = `p${idx++}`;\n bindings[paramName] = value;\n propParts.push(`.property('${key}', ${paramName})`);\n }\n\n // coalesce: find existing → update it, or create new edge\n const createEdge = `g.V().has('repositoryId', rid).has('id', srcId).has('entityType').addE(edgeLabel).to(g.V().has('repositoryId', rid).has('id', tgtId).has('entityType')).property('id', relId)${propParts.join('')}`;\n const query = `g.E().has('id', relId).fold().coalesce(unfold()${propParts.join('')}, ${createEdge})`;\n await conn.submit(query, bindings);\n}\n"],"mappings":"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","names":["matchesPropertyFilters"]}