@utaba/deep-memory-storage-cosmosdb 0.9.1 → 0.10.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.cjs +33 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +33 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../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":["// @utaba/deep-memory-storage-cosmosdb — CosmosDB Gremlin StorageProvider + GraphTraversalProvider\n\nexport { CosmosDbProvider } from './CosmosDbProvider.js';\nexport type { CosmosDbProviderConfig } from './CosmosDbProvider.js';\nexport { CosmosDbConnection } from './CosmosDbConnection.js';\nexport type { CosmosDbConnectionConfig, GremlinResult } from './CosmosDbConnection.js';\n","// 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 UsageSink,\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, InvalidInputError, isValidUuid, projectEntity, createSafeSink } from '@utaba/deep-memory';\nimport { CosmosDbConnection, usageScope } from './CosmosDbConnection.js';\nimport type { UsageAccumulator } 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 * Optional usage sink. When provided, the provider emits one\n * {@link OperationUsage} record per public method call with the aggregated\n * CosmosDB request charge (RU). Never exposed to AI agents — the MCP server\n * deliberately does not plumb this sink through.\n */\n reportUsage?: UsageSink;\n}\n\nconst PROVIDER_NAME = 'cosmosdb';\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 private readonly reportUsage: UsageSink | undefined;\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.reportUsage = createSafeSink(config.reportUsage);\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 /**\n * Run the given operation inside an async-local usage scope. While the\n * operation runs, every `conn.submit()` call accumulates its request charge\n * into a shared accumulator. When the operation completes (success or\n * failure), a single {@link OperationUsage} record is emitted to the sink.\n *\n * Nested public-method calls (e.g. `traverse` internally calls\n * `getVocabulary`) are detected: the inner call joins the outer scope\n * instead of starting a new one, so one user-visible operation produces\n * exactly one usage record covering all its internal round-trips.\n *\n * If no sink is configured, this is a zero-overhead pass-through.\n */\n private async track<T>(\n operation: string,\n repositoryId: string | undefined,\n fn: () => Promise<T>,\n ): Promise<T> {\n if (!this.reportUsage) return fn();\n // Already inside a parent scope — join it rather than emitting a\n // separate record. The outermost call owns emission.\n if (usageScope.getStore()) return fn();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n return await usageScope.run(acc, fn);\n } finally {\n if (acc.calls > 0) {\n this.reportUsage({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n ...(repositoryId ? { repositoryId } : {}),\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n }\n }\n\n /**\n * Reject any repositoryId that is not a valid v4 UUID.\n *\n * Every partition-scoped query filters on repositoryId. Since repositoryId is\n * the CosmosDB partition key, a predicate with a different value would target\n * a different partition. Strict format validation at the provider boundary\n * prevents injection (e.g. strings containing quotes or Gremlin syntax) from\n * ever reaching query construction.\n */\n private assertValidRepositoryId(repositoryId: string): void {\n if (!isValidUuid(repositoryId)) {\n throw new InvalidInputError(\n 'repositoryId',\n `repositoryId must be a valid v4 UUID; got '${repositoryId}'`,\n );\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 return this.track('ensureSchema', undefined, () => this.ensureSchemaImpl());\n }\n\n private async ensureSchemaImpl(): 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 this.assertValidRepositoryId(config.repositoryId);\n return this.track('createRepository', config.repositoryId, () =>\n repoQueries.createRepository(this.conn, config),\n );\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepository', repositoryId, () =>\n repoQueries.getRepository(this.conn, repositoryId),\n );\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return this.track('listRepositories', undefined, () =>\n repoQueries.listRepositories(this.conn, filter),\n );\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateRepository', repositoryId, () =>\n repoQueries.updateRepository(this.conn, repositoryId, updates),\n );\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRepository', repositoryId, () =>\n repoQueries.deleteRepository(this.conn, repositoryId, onProgress),\n );\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteAllContents', repositoryId, () =>\n repoQueries.deleteAllContents(this.conn, repositoryId, onProgress),\n );\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepositoryStats', repositoryId, () =>\n repoQueries.getRepositoryStats(this.conn, repositoryId),\n );\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabulary', repositoryId, () =>\n vocabQueries.getVocabulary(this.conn, repositoryId),\n );\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('saveVocabulary', repositoryId, () =>\n vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary),\n );\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabularyChangeLog', repositoryId, () =>\n vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options),\n );\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createEntity', repositoryId, () =>\n entityQueries.createEntity(this.conn, repositoryId, entity),\n );\n }\n\n async getEntity(repositoryId: string, entityId: string): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntity', repositoryId, () =>\n entityQueries.getEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async getEntityBySlug(repositoryId: string, slug: string): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityBySlug', repositoryId, () =>\n entityQueries.getEntityBySlug(this.conn, repositoryId, slug),\n );\n }\n\n async getEntities(repositoryId: string, entityIds: string[]): Promise<Map<string, StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntities', repositoryId, () =>\n entityQueries.getEntities(this.conn, repositoryId, entityIds),\n );\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateEntity', repositoryId, () =>\n entityQueries.updateEntity(this.conn, repositoryId, entityId, updates),\n );\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntity', repositoryId, () =>\n entityQueries.deleteEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async deleteEntities(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntities', repositoryId, () => this.deleteEntitiesImpl(repositoryId, ids));\n }\n\n private async deleteEntitiesImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n // Find which vertex IDs actually exist using P.within\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `P.within(${idParams.join(', ')})`;\n const existResult = await this.conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${withinExpr}).has('entityType').values('id')`,\n bindings,\n );\n const found = existResult.items as string[];\n\n if (found.length > 0) {\n // Drop vertices — Gremlin drop() automatically cascades to connected edges\n const dropBindings: Record<string, unknown> = { rid: repositoryId };\n const dropIdParams: string[] = [];\n for (let j = 0; j < found.length; j++) {\n const p = `did${j}`;\n dropBindings[p] = found[j];\n dropIdParams.push(p);\n }\n const dropWithinExpr = `P.within(${dropIdParams.join(', ')})`;\n await this.conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${dropWithinExpr}).has('entityType').drop()`,\n dropBindings,\n );\n deleted.push(...found);\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntitiesByType', repositoryId, () =>\n entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType),\n );\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery): Promise<PaginatedResult<StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findEntities', repositoryId, () =>\n entityQueries.findEntities(this.conn, repositoryId, query),\n );\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createRelationship', repositoryId, () =>\n relQueries.createRelationship(this.conn, repositoryId, relationship),\n );\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRelationship', repositoryId, () =>\n relQueries.getRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityRelationships', repositoryId, () =>\n relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options),\n );\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationship', repositoryId, () =>\n relQueries.deleteRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async deleteRelationships(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationships', repositoryId, () => this.deleteRelationshipsImpl(repositoryId, ids));\n }\n\n private async deleteRelationshipsImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n // Build Gremlin P.within(...) query to find which IDs actually exist\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `P.within(${idParams.join(', ')})`;\n const existResult = await this.conn.submit(\n `g.E().has('repositoryId', rid).has('id', ${withinExpr}).values('id')`,\n bindings,\n );\n const found = existResult.items as string[];\n\n if (found.length > 0) {\n await cosmosRestBatchDelete(\n this.getRestEndpoint(),\n this.config.key,\n this.config.database,\n this.config.container,\n repositoryId,\n found,\n this.config.rejectUnauthorized ?? true,\n );\n deleted.push(...found);\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationshipsByType', repositoryId, () =>\n relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType),\n );\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighborhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighborhood> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('exploreNeighborhood', repositoryId, () =>\n traversalQueries.exploreNeighborhood(this.conn, repositoryId, entityId, options),\n );\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findPaths', repositoryId, () =>\n traversalQueries.findPaths(this.conn, repositoryId, sourceId, targetId, options),\n );\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getTimeline', repositoryId, () =>\n timelineQueries.getTimeline(this.conn, repositoryId, entityId, options),\n );\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n this.assertValidRepositoryId(repositoryId);\n // exportAll is a streaming iterator — each chunk consumed drives new\n // submits. Wrapping the entire iteration in a single usage scope would\n // require holding the scope open across consumer awaits, which breaks\n // the AsyncLocalStorage contract. Instead, wrap each submit as its own\n // sub-operation by running the iterator generator inside the scope.\n return this.trackIterable('exportAll', repositoryId, bulkQueries.exportAll(this.conn, repositoryId));\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('importBulk', repositoryId, () =>\n bulkQueries.importBulk(this.conn, repositoryId, data, options),\n );\n }\n\n /**\n * Wrap an AsyncIterable so every emitted chunk is generated inside the\n * usage scope. On each iteration step, the scope aggregates charges from\n * the next chunk's submits; when the iterator completes (or is closed), a\n * single usage record is emitted for the whole stream.\n */\n private trackIterable<T>(operation: string, repositoryId: string, source: AsyncIterable<T>): AsyncIterable<T> {\n if (!this.reportUsage) return source;\n const sink = this.reportUsage;\n return {\n [Symbol.asyncIterator]: (): AsyncIterator<T> => {\n const iter = source[Symbol.asyncIterator]();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n let emitted = false;\n const emit = (): void => {\n if (emitted) return;\n emitted = true;\n if (acc.calls > 0) {\n sink({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n repositoryId,\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n };\n return {\n async next(): Promise<IteratorResult<T>> {\n const step = await usageScope.run(acc, () => iter.next());\n if (step.done) emit();\n return step;\n },\n async return(value?: T): Promise<IteratorResult<T>> {\n emit();\n if (iter.return) return iter.return(value);\n return { done: true, value: value as T };\n },\n async throw(err?: unknown): Promise<IteratorResult<T>> {\n emit();\n if (iter.throw) return iter.throw(err);\n throw err;\n },\n };\n },\n };\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 ): Promise<TraversalResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('traverse', repositoryId, () => this.traverseImpl(repositoryId, spec));\n }\n\n private async traverseImpl(\n repositoryId: string,\n spec: TraversalSpec,\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 — the provider owns compilation.\n const compiled = this.compiler.compile(spec, vocabulary);\n\n // Scope the traversal to this repository's partition.\n // repositoryId is the CosmosDB partition key — the predicate both filters\n // and routes the query to a single physical partition. Bind it as a\n // parameter (never concatenated) so it cannot become Gremlin syntax even\n // if the upstream GUID check is ever bypassed.\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n \"g.V().has('repositoryId', pRid)\",\n );\n const scopedParams = { ...compiled.params, pRid: repositoryId };\n\n try {\n const result = await this.conn.submit(scopedQuery, scopedParams);\n const executionTimeMs = Date.now() - startTime;\n\n // Project stored entities to the requested detail level. This strips\n // embeddings and any other internal fields at every level — the\n // projection contract never surfaces embeddings via traversal results.\n const detailLevel = spec.detailLevel ?? 'summary';\n const entities: TraversalResult['entities'] = [];\n const relationships: NonNullable<TraversalResult['relationships']> = [];\n const paths: NonNullable<TraversalResult['paths']> = [];\n\n if (spec.returnMode === 'path') {\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 const stored = entityFromGremlin(props);\n pathEntities.push(projectEntity(stored, detailLevel) as TraversalResult['entities'][number]);\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 for (const item of result.items) {\n const stored = entityFromGremlin(item as Record<string, unknown>);\n entities.push(projectEntity(stored, detailLevel) as TraversalResult['entities'][number]);\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 /**\n * Execute a raw Gremlin query with caller-supplied bindings.\n *\n * ⚠️ ELEVATED PRIVILEGE — SYSTEM-LEVEL OPERATION ⚠️\n *\n * This method is an unscoped pass-through: it does not filter by repository,\n * does not inject the partition key, and performs no validation on the query\n * string. A single call can read or mutate any vertex or edge in the\n * container regardless of which repository (partition) it belongs to.\n *\n * DO NOT expose this method to AI agents, end users, or any untrusted caller.\n * It is intended for:\n * - administrative tooling (migrations, diagnostics, repairs)\n * - internal library operations that need cross-partition reach\n *\n * `repositoryId` is accepted for interface symmetry but is intentionally\n * ignored here — the caller is trusted to scope the query themselves.\n *\n * For agent-facing graph queries use {@link traverse}, which enforces the\n * repositoryId partition predicate.\n */\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<TraversalResult> {\n // executeNativeQuery is cross-partition by design; no repositoryId is\n // stamped on the usage record because the query isn't scoped to one.\n return this.track('executeNativeQuery', undefined, () => this.executeNativeQueryImpl(query, params));\n }\n\n private async executeNativeQueryImpl(\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 const options: RequestInit = {\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), disable TLS verification process-wide.\n // Caller explicitly opted in via rejectUnauthorized: false.\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\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\n/**\n * Delete multiple CosmosDB documents in a single Transactional Batch request.\n * All documents must share the same partition key value (repositoryId).\n * Max 100 operations per batch — caller is responsible for chunking.\n */\nasync function cosmosRestBatchDelete(\n restBase: string,\n key: string,\n database: string,\n container: string,\n partitionKeyValue: string,\n ids: string[],\n rejectUnauthorized: boolean,\n): Promise<void> {\n const resourceLink = `dbs/${database}/colls/${container}`;\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', 'docs', resourceLink, date, key);\n\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const ops = ids.map((id) => ({ operationType: 'Delete', id }));\n\n const response = await fetch(`${restBase}/${resourceLink}/docs`, {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2020-07-15',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n 'x-ms-documentdb-partitionkey': JSON.stringify([partitionKeyValue]),\n 'x-ms-cosmos-is-batch-request': 'true',\n 'x-ms-cosmos-batch-atomic': 'true',\n },\n body: JSON.stringify(ops),\n });\n\n // 200 (non-atomic) or 207 (atomic) indicate the batch was processed\n if (response.status !== 200 && response.status !== 207) {\n const text = await response.text();\n throw new ProviderError(`CosmosDB batch delete failed (${response.status}): ${text}`);\n }\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';\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/** Per-operation RU accumulator kept in async-local storage. */\nexport interface UsageAccumulator {\n /** Total request charge (RU) across all submits in the current operation. */\n ru: number;\n /** Number of gremlin submit() calls. */\n calls: number;\n /** Number of transient-retry waits observed. */\n retries: number;\n}\n\n/**\n * Module-level AsyncLocalStorage so any `submit()` executed inside a\n * `usageScope.run(...)` block contributes its RU/retry counts to the active\n * accumulator. Providers wrap each public method in a scope and read the\n * aggregated result when the method returns.\n */\nexport const usageScope = new AsyncLocalStorage<UsageAccumulator>();\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 const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n if (typeof requestCharge === 'number') acc.ru += requestCharge;\n }\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 const acc = usageScope.getStore();\n if (acc) acc.retries++;\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 // Gremlin has no \"set to null\" — to clear a property we drop it with a\n // sideEffect step. Drops run before sets because `.sideEffect(...)` is\n // appended to `propParts` in traversal order.\n const dropProp = (key: string) => {\n propParts.push(`.sideEffect(properties('${key}').drop())`);\n };\n\n // Note: entityType drives both the Gremlin vertex label (set at addV) and the\n // `entityType` property. The vertex label is immutable in Gremlin, but every\n // entity query in this provider filters by the `entityType` property rather\n // than vertex label, so updating the property is sufficient for functional\n // correctness. The vertex label becomes a stale hint only.\n if (updates.entityType !== undefined) addProp('entityType', updates.entityType);\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary === null) dropProp('summary');\n else if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data === null) dropProp('data');\n else if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat === null) dropProp('dataFormat');\n else 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 // searchTerm and properties can't be filtered server-side: CosmosDB Gremlin\n // silently drops TextP.containing(), and properties are stored as a JSON blob.\n // When either is present, load all type-matched vertices and filter in memory\n // so pagination and total counts reflect the real result set.\n const hasPropertyFilter =\n query.properties != null && Object.keys(query.properties).length > 0;\n const needsClientFilter = Boolean(query.searchTerm) || hasPropertyFilter;\n\n if (needsClientFilter) {\n const dataResult = await conn.submit(\n `g.V()${filterClause}.valueMap(true)`,\n bindings,\n );\n let items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\n\n if (query.searchTerm) {\n const term = query.searchTerm.toLowerCase();\n items = items.filter(\n (e) =>\n e.label.toLowerCase().includes(term) ||\n e.slug.toLowerCase().includes(term) ||\n (e.summary != null && e.summary.toLowerCase().includes(term)),\n );\n }\n\n if (hasPropertyFilter) {\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 const total = items.length;\n const paged = items.slice(query.offset, query.offset + query.limit);\n\n return {\n items: paged,\n total,\n hasMore: query.offset + query.limit < total,\n limit: query.limit,\n offset: query.offset,\n };\n }\n\n // Fast path: server-side pagination when no client-side filters are needed.\n const countResult = await conn.submit(\n `g.V()${filterClause}.count()`,\n bindings,\n );\n const total = Number(countResult.items[0] ?? 0);\n\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 const items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\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 — scoped by repositoryId so the same relationship id\n // in a different repo does not cause a false-positive collision.\n const existing = await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', relId).count()\",\n { rid: repositoryId, 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\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 // Cache entity loads within this layer to avoid redundant DB round-trips when\n // the same entity is connected via multiple relationship types. null = rejected by filter.\n const layerCache = new Map<string, StoredEntity | null>();\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 // Skip entities already visited in a previous BFS layer\n if (visited.has(connectedId)) continue;\n\n // Load entity, using per-layer cache to avoid redundant fetches\n let entity: StoredEntity | null | undefined = layerCache.get(connectedId);\n if (entity === undefined) {\n const loaded = await getEntityLight(conn, repositoryId, connectedId);\n if (loaded && (!options.entityTypes || options.entityTypes.length === 0 || options.entityTypes.includes(loaded.entityType))) {\n entity = loaded;\n } else {\n entity = null;\n }\n layerCache.set(connectedId, entity);\n if (entity) nextFrontier.add(connectedId);\n }\n\n if (!entity) continue;\n\n layer[relType]!.entities.push(entity);\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\n // Promote this layer's entities into visited after the full layer is processed,\n // not mid-loop, so the same entity can appear under multiple relationship types.\n for (const id of nextFrontier) {\n visited.add(id);\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 // The E() lookup is scoped by repositoryId so an edge with the same id in a\n // different repo cannot be matched and silently overwritten.\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('repositoryId', rid).has('id', relId).fold().coalesce(unfold()${propParts.join('')}, ${createEdge})`;\n await conn.submit(query, bindings);\n}\n"],"mappings":"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","names":["import_deep_memory","gremlin","import_deep_memory","dataResult","items","total","import_deep_memory","import_deep_memory","crypto"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../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":["// @utaba/deep-memory-storage-cosmosdb — CosmosDB Gremlin StorageProvider + GraphTraversalProvider\n\nexport { CosmosDbProvider } from './CosmosDbProvider.js';\nexport type { CosmosDbProviderConfig } from './CosmosDbProvider.js';\nexport { CosmosDbConnection } from './CosmosDbConnection.js';\nexport type { CosmosDbConnectionConfig, GremlinResult } from './CosmosDbConnection.js';\n","// 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 UsageSink,\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, InvalidInputError, isValidUuid, projectEntity, createSafeSink } from '@utaba/deep-memory';\nimport { CosmosDbConnection, usageScope } from './CosmosDbConnection.js';\nimport type { UsageAccumulator } 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 * Milliseconds to pause between batches in deleteAllContents/deleteRepository\n * to pace RU consumption. Required on low-RU tiers (e.g. CosmosDB free tier at\n * 1000 RU/s), where a single batch drop query can consume the entire per-second\n * budget and throttle the next batch. Set to 1000+ on constrained tiers.\n * Default: 0 (no pacing — suitable for autoscale and provisioned throughput).\n */\n deleteBatchDelayMs?: number;\n /**\n * Optional usage sink. When provided, the provider emits one\n * {@link OperationUsage} record per public method call with the aggregated\n * CosmosDB request charge (RU). Never exposed to AI agents — the MCP server\n * deliberately does not plumb this sink through.\n */\n reportUsage?: UsageSink;\n}\n\nconst PROVIDER_NAME = 'cosmosdb';\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 private readonly reportUsage: UsageSink | undefined;\n\n constructor(config: CosmosDbProviderConfig) {\n this.config = config;\n this.reportUsage = createSafeSink(config.reportUsage);\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 /**\n * Run the given operation inside an async-local usage scope. While the\n * operation runs, every `conn.submit()` call accumulates its request charge\n * into a shared accumulator. When the operation completes (success or\n * failure), a single {@link OperationUsage} record is emitted to the sink.\n *\n * Nested public-method calls (e.g. `traverse` internally calls\n * `getVocabulary`) are detected: the inner call joins the outer scope\n * instead of starting a new one, so one user-visible operation produces\n * exactly one usage record covering all its internal round-trips.\n *\n * If no sink is configured, this is a zero-overhead pass-through.\n */\n private async track<T>(\n operation: string,\n repositoryId: string | undefined,\n fn: () => Promise<T>,\n ): Promise<T> {\n if (!this.reportUsage) return fn();\n // Already inside a parent scope — join it rather than emitting a\n // separate record. The outermost call owns emission.\n if (usageScope.getStore()) return fn();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n try {\n return await usageScope.run(acc, fn);\n } finally {\n if (acc.calls > 0) {\n this.reportUsage({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n ...(repositoryId ? { repositoryId } : {}),\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n }\n }\n\n /**\n * Reject any repositoryId that is not a valid v4 UUID.\n *\n * Every partition-scoped query filters on repositoryId. Since repositoryId is\n * the CosmosDB partition key, a predicate with a different value would target\n * a different partition. Strict format validation at the provider boundary\n * prevents injection (e.g. strings containing quotes or Gremlin syntax) from\n * ever reaching query construction.\n */\n private assertValidRepositoryId(repositoryId: string): void {\n if (!isValidUuid(repositoryId)) {\n throw new InvalidInputError(\n 'repositoryId',\n `repositoryId must be a valid v4 UUID; got '${repositoryId}'`,\n );\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 return this.track('ensureSchema', undefined, () => this.ensureSchemaImpl());\n }\n\n private async ensureSchemaImpl(): 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 this.assertValidRepositoryId(config.repositoryId);\n return this.track('createRepository', config.repositoryId, () =>\n repoQueries.createRepository(this.conn, config),\n );\n }\n\n async getRepository(repositoryId: string): Promise<StoredRepository | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepository', repositoryId, () =>\n repoQueries.getRepository(this.conn, repositoryId),\n );\n }\n\n async listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>> {\n return this.track('listRepositories', undefined, () =>\n repoQueries.listRepositories(this.conn, filter),\n );\n }\n\n async updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateRepository', repositoryId, () =>\n repoQueries.updateRepository(this.conn, repositoryId, updates),\n );\n }\n\n async deleteRepository(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n const batchDelayMs = this.config.deleteBatchDelayMs ?? 0;\n return this.track('deleteRepository', repositoryId, () =>\n repoQueries.deleteRepository(this.conn, repositoryId, onProgress, { batchDelayMs }),\n );\n }\n\n async deleteAllContents(repositoryId: string, onProgress?: DeleteProgressCallback): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n const batchDelayMs = this.config.deleteBatchDelayMs ?? 0;\n return this.track('deleteAllContents', repositoryId, () =>\n repoQueries.deleteAllContents(this.conn, repositoryId, onProgress, { batchDelayMs }),\n );\n }\n\n async getRepositoryStats(repositoryId: string): Promise<RepositoryStats> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRepositoryStats', repositoryId, () =>\n repoQueries.getRepositoryStats(this.conn, repositoryId),\n );\n }\n\n // ─── Vocabulary ────────────────────────────────────────────────────\n\n async getVocabulary(repositoryId: string): Promise<MemoryVocabulary> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabulary', repositoryId, () =>\n vocabQueries.getVocabulary(this.conn, repositoryId),\n );\n }\n\n async saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('saveVocabulary', repositoryId, () =>\n vocabQueries.saveVocabulary(this.conn, repositoryId, vocabulary),\n );\n }\n\n async getVocabularyChangeLog(repositoryId: string, options?: PaginationOptions): Promise<PaginatedResult<VocabularyChangeRecord>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getVocabularyChangeLog', repositoryId, () =>\n vocabQueries.getVocabularyChangeLog(this.conn, repositoryId, options),\n );\n }\n\n // ─── Entities ──────────────────────────────────────────────────────\n\n async createEntity(repositoryId: string, entity: StoredEntity): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createEntity', repositoryId, () =>\n entityQueries.createEntity(this.conn, repositoryId, entity),\n );\n }\n\n async getEntity(repositoryId: string, entityId: string): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntity', repositoryId, () =>\n entityQueries.getEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async getEntityBySlug(repositoryId: string, slug: string): Promise<StoredEntity | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityBySlug', repositoryId, () =>\n entityQueries.getEntityBySlug(this.conn, repositoryId, slug),\n );\n }\n\n async getEntities(repositoryId: string, entityIds: string[]): Promise<Map<string, StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntities', repositoryId, () =>\n entityQueries.getEntities(this.conn, repositoryId, entityIds),\n );\n }\n\n async updateEntity(repositoryId: string, entityId: string, updates: StoredEntityUpdate): Promise<StoredEntity> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('updateEntity', repositoryId, () =>\n entityQueries.updateEntity(this.conn, repositoryId, entityId, updates),\n );\n }\n\n async deleteEntity(repositoryId: string, entityId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntity', repositoryId, () =>\n entityQueries.deleteEntity(this.conn, repositoryId, entityId),\n );\n }\n\n async deleteEntities(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntities', repositoryId, () => this.deleteEntitiesImpl(repositoryId, ids));\n }\n\n private async deleteEntitiesImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n // Find which vertex IDs actually exist using P.within\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `P.within(${idParams.join(', ')})`;\n const existResult = await this.conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${withinExpr}).has('entityType').values('id')`,\n bindings,\n );\n const found = existResult.items as string[];\n\n if (found.length > 0) {\n // Drop vertices — Gremlin drop() automatically cascades to connected edges\n const dropBindings: Record<string, unknown> = { rid: repositoryId };\n const dropIdParams: string[] = [];\n for (let j = 0; j < found.length; j++) {\n const p = `did${j}`;\n dropBindings[p] = found[j];\n dropIdParams.push(p);\n }\n const dropWithinExpr = `P.within(${dropIdParams.join(', ')})`;\n await this.conn.submit(\n `g.V().has('repositoryId', rid).has('id', ${dropWithinExpr}).has('entityType').drop()`,\n dropBindings,\n );\n deleted.push(...found);\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteEntitiesByType(repositoryId: string, entityType: string): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteEntitiesByType', repositoryId, () =>\n entityQueries.deleteEntitiesByType(this.conn, repositoryId, entityType),\n );\n }\n\n async findEntities(repositoryId: string, query: StorageFindQuery): Promise<PaginatedResult<StoredEntity>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findEntities', repositoryId, () =>\n entityQueries.findEntities(this.conn, repositoryId, query),\n );\n }\n\n // ─── Relationships ─────────────────────────────────────────────────\n\n async createRelationship(repositoryId: string, relationship: StoredRelationship): Promise<StoredRelationship> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('createRelationship', repositoryId, () =>\n relQueries.createRelationship(this.conn, repositoryId, relationship),\n );\n }\n\n async getRelationship(repositoryId: string, relationshipId: string): Promise<StoredRelationship | null> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getRelationship', repositoryId, () =>\n relQueries.getRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async getEntityRelationships(repositoryId: string, entityId: string, options?: RelationshipQueryOptions): Promise<PaginatedResult<StoredRelationship>> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getEntityRelationships', repositoryId, () =>\n relQueries.getEntityRelationships(this.conn, repositoryId, entityId, options),\n );\n }\n\n async deleteRelationship(repositoryId: string, relationshipId: string): Promise<void> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationship', repositoryId, () =>\n relQueries.deleteRelationship(this.conn, repositoryId, relationshipId),\n );\n }\n\n async deleteRelationships(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n if (ids.length === 0) return { deleted: [], notFound: [] };\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationships', repositoryId, () => this.deleteRelationshipsImpl(repositoryId, ids));\n }\n\n private async deleteRelationshipsImpl(repositoryId: string, ids: string[]): Promise<{ deleted: string[]; notFound: string[] }> {\n const deleted: string[] = [];\n const CHUNK = 100;\n\n for (let i = 0; i < ids.length; i += CHUNK) {\n const chunk = ids.slice(i, i + CHUNK);\n\n // Build Gremlin P.within(...) query to find which IDs actually exist\n const bindings: Record<string, unknown> = { rid: repositoryId };\n const idParams: string[] = [];\n for (let j = 0; j < chunk.length; j++) {\n const p = `id${j}`;\n bindings[p] = chunk[j];\n idParams.push(p);\n }\n const withinExpr = `P.within(${idParams.join(', ')})`;\n const existResult = await this.conn.submit(\n `g.E().has('repositoryId', rid).has('id', ${withinExpr}).values('id')`,\n bindings,\n );\n const found = existResult.items as string[];\n\n if (found.length > 0) {\n await cosmosRestBatchDelete(\n this.getRestEndpoint(),\n this.config.key,\n this.config.database,\n this.config.container,\n repositoryId,\n found,\n this.config.rejectUnauthorized ?? true,\n );\n deleted.push(...found);\n }\n }\n\n const deletedSet = new Set(deleted);\n return { deleted, notFound: ids.filter((id) => !deletedSet.has(id)) };\n }\n\n async deleteRelationshipsByType(repositoryId: string, relationshipType: string): Promise<{ deletedRelationships: number }> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('deleteRelationshipsByType', repositoryId, () =>\n relQueries.deleteRelationshipsByType(this.conn, repositoryId, relationshipType),\n );\n }\n\n // ─── Graph Traversal (StorageProvider) ─────────────────────────────\n\n async exploreNeighborhood(repositoryId: string, entityId: string, options: StorageExploreOptions): Promise<StorageNeighborhood> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('exploreNeighborhood', repositoryId, () =>\n traversalQueries.exploreNeighborhood(this.conn, repositoryId, entityId, options),\n );\n }\n\n async findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('findPaths', repositoryId, () =>\n traversalQueries.findPaths(this.conn, repositoryId, sourceId, targetId, options),\n );\n }\n\n // ─── Timeline ──────────────────────────────────────────────────────\n\n async getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('getTimeline', repositoryId, () =>\n timelineQueries.getTimeline(this.conn, repositoryId, entityId, options),\n );\n }\n\n // ─── Bulk Operations ───────────────────────────────────────────────\n\n exportAll(repositoryId: string): AsyncIterable<ExportChunk> {\n this.assertValidRepositoryId(repositoryId);\n // exportAll is a streaming iterator — each chunk consumed drives new\n // submits. Wrapping the entire iteration in a single usage scope would\n // require holding the scope open across consumer awaits, which breaks\n // the AsyncLocalStorage contract. Instead, wrap each submit as its own\n // sub-operation by running the iterator generator inside the scope.\n return this.trackIterable('exportAll', repositoryId, bulkQueries.exportAll(this.conn, repositoryId));\n }\n\n async importBulk(repositoryId: string, data: ImportChunk[], options?: BulkImportOptions): Promise<BulkImportResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('importBulk', repositoryId, () =>\n bulkQueries.importBulk(this.conn, repositoryId, data, options),\n );\n }\n\n /**\n * Wrap an AsyncIterable so every emitted chunk is generated inside the\n * usage scope. On each iteration step, the scope aggregates charges from\n * the next chunk's submits; when the iterator completes (or is closed), a\n * single usage record is emitted for the whole stream.\n */\n private trackIterable<T>(operation: string, repositoryId: string, source: AsyncIterable<T>): AsyncIterable<T> {\n if (!this.reportUsage) return source;\n const sink = this.reportUsage;\n return {\n [Symbol.asyncIterator]: (): AsyncIterator<T> => {\n const iter = source[Symbol.asyncIterator]();\n const acc: UsageAccumulator = { ru: 0, calls: 0, retries: 0 };\n let emitted = false;\n const emit = (): void => {\n if (emitted) return;\n emitted = true;\n if (acc.calls > 0) {\n sink({\n provider: PROVIDER_NAME,\n operation,\n unit: 'RU',\n value: acc.ru,\n repositoryId,\n timestamp: new Date(),\n details: { calls: acc.calls, retries: acc.retries },\n });\n }\n };\n return {\n async next(): Promise<IteratorResult<T>> {\n const step = await usageScope.run(acc, () => iter.next());\n if (step.done) emit();\n return step;\n },\n async return(value?: T): Promise<IteratorResult<T>> {\n emit();\n if (iter.return) return iter.return(value);\n return { done: true, value: value as T };\n },\n async throw(err?: unknown): Promise<IteratorResult<T>> {\n emit();\n if (iter.throw) return iter.throw(err);\n throw err;\n },\n };\n },\n };\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 ): Promise<TraversalResult> {\n this.assertValidRepositoryId(repositoryId);\n return this.track('traverse', repositoryId, () => this.traverseImpl(repositoryId, spec));\n }\n\n private async traverseImpl(\n repositoryId: string,\n spec: TraversalSpec,\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 — the provider owns compilation.\n const compiled = this.compiler.compile(spec, vocabulary);\n\n // Scope the traversal to this repository's partition.\n // repositoryId is the CosmosDB partition key — the predicate both filters\n // and routes the query to a single physical partition. Bind it as a\n // parameter (never concatenated) so it cannot become Gremlin syntax even\n // if the upstream GUID check is ever bypassed.\n const scopedQuery = compiled.query.replace(\n 'g.V()',\n \"g.V().has('repositoryId', pRid)\",\n );\n const scopedParams = { ...compiled.params, pRid: repositoryId };\n\n try {\n const result = await this.conn.submit(scopedQuery, scopedParams);\n const executionTimeMs = Date.now() - startTime;\n\n // Project stored entities to the requested detail level. This strips\n // embeddings and any other internal fields at every level — the\n // projection contract never surfaces embeddings via traversal results.\n const detailLevel = spec.detailLevel ?? 'summary';\n const entities: TraversalResult['entities'] = [];\n const relationships: NonNullable<TraversalResult['relationships']> = [];\n const paths: NonNullable<TraversalResult['paths']> = [];\n\n if (spec.returnMode === 'path') {\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 const stored = entityFromGremlin(props);\n pathEntities.push(projectEntity(stored, detailLevel) as TraversalResult['entities'][number]);\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 for (const item of result.items) {\n const stored = entityFromGremlin(item as Record<string, unknown>);\n entities.push(projectEntity(stored, detailLevel) as TraversalResult['entities'][number]);\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 /**\n * Execute a raw Gremlin query with caller-supplied bindings.\n *\n * ⚠️ ELEVATED PRIVILEGE — SYSTEM-LEVEL OPERATION ⚠️\n *\n * This method is an unscoped pass-through: it does not filter by repository,\n * does not inject the partition key, and performs no validation on the query\n * string. A single call can read or mutate any vertex or edge in the\n * container regardless of which repository (partition) it belongs to.\n *\n * DO NOT expose this method to AI agents, end users, or any untrusted caller.\n * It is intended for:\n * - administrative tooling (migrations, diagnostics, repairs)\n * - internal library operations that need cross-partition reach\n *\n * `repositoryId` is accepted for interface symmetry but is intentionally\n * ignored here — the caller is trusted to scope the query themselves.\n *\n * For agent-facing graph queries use {@link traverse}, which enforces the\n * repositoryId partition predicate.\n */\n async executeNativeQuery(\n _repositoryId: string,\n query: string,\n params?: Record<string, unknown>,\n ): Promise<TraversalResult> {\n // executeNativeQuery is cross-partition by design; no repositoryId is\n // stamped on the usage record because the query isn't scoped to one.\n return this.track('executeNativeQuery', undefined, () => this.executeNativeQueryImpl(query, params));\n }\n\n private async executeNativeQueryImpl(\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 const options: RequestInit = {\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), disable TLS verification process-wide.\n // Caller explicitly opted in via rejectUnauthorized: false.\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\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\n/**\n * Delete multiple CosmosDB documents in a single Transactional Batch request.\n * All documents must share the same partition key value (repositoryId).\n * Max 100 operations per batch — caller is responsible for chunking.\n */\nasync function cosmosRestBatchDelete(\n restBase: string,\n key: string,\n database: string,\n container: string,\n partitionKeyValue: string,\n ids: string[],\n rejectUnauthorized: boolean,\n): Promise<void> {\n const resourceLink = `dbs/${database}/colls/${container}`;\n const date = new Date().toUTCString();\n const token = cosmosAuthToken('post', 'docs', resourceLink, date, key);\n\n if (!rejectUnauthorized) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const ops = ids.map((id) => ({ operationType: 'Delete', id }));\n\n const response = await fetch(`${restBase}/${resourceLink}/docs`, {\n method: 'POST',\n headers: {\n 'Authorization': token,\n 'x-ms-version': '2020-07-15',\n 'x-ms-date': date,\n 'Content-Type': 'application/json',\n 'x-ms-documentdb-partitionkey': JSON.stringify([partitionKeyValue]),\n 'x-ms-cosmos-is-batch-request': 'true',\n 'x-ms-cosmos-batch-atomic': 'true',\n },\n body: JSON.stringify(ops),\n });\n\n // 200 (non-atomic) or 207 (atomic) indicate the batch was processed\n if (response.status !== 200 && response.status !== 207) {\n const text = await response.text();\n throw new ProviderError(`CosmosDB batch delete failed (${response.status}): ${text}`);\n }\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';\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/** Per-operation RU accumulator kept in async-local storage. */\nexport interface UsageAccumulator {\n /** Total request charge (RU) across all submits in the current operation. */\n ru: number;\n /** Number of gremlin submit() calls. */\n calls: number;\n /** Number of transient-retry waits observed. */\n retries: number;\n}\n\n/**\n * Module-level AsyncLocalStorage so any `submit()` executed inside a\n * `usageScope.run(...)` block contributes its RU/retry counts to the active\n * accumulator. Providers wrap each public method in a scope and read the\n * aggregated result when the method returns.\n */\nexport const usageScope = new AsyncLocalStorage<UsageAccumulator>();\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 const acc = usageScope.getStore();\n if (acc) {\n acc.calls++;\n if (typeof requestCharge === 'number') acc.ru += requestCharge;\n }\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 const acc = usageScope.getStore();\n if (acc) acc.retries++;\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/**\n * Extract retry-after from error or use exponential backoff.\n *\n * CosmosDB wraps 429 throttling as Gremlin status 500; the retry hint lives\n * inside ResponseError.statusAttributes (a Map) under `x-ms-retry-after-ms`.\n * The server's hint (e.g. 8ms) targets replication backoff, not RU-budget\n * recovery — blindly following it re-exhausts the budget and loops. We take\n * max(serverHint, exponentialBackoff) so the server can only extend the wait,\n * never shorten it below our safe baseline.\n */\nfunction getRetryAfterMs(err: unknown, attempt: number): number {\n const exponentialMs = Math.min(500 * Math.pow(2, attempt), 10000);\n\n const topLevel = (err as Record<string, unknown>)?.['retryAfterMs'];\n if (typeof topLevel === 'number' && topLevel > 0) {\n return Math.max(topLevel, exponentialMs);\n }\n\n const attrs = (err as { statusAttributes?: unknown })?.statusAttributes;\n let hintVal: unknown;\n if (attrs instanceof Map) {\n hintVal = attrs.get('x-ms-retry-after-ms') ?? attrs.get('x-ms-retry-after');\n } else if (typeof attrs === 'object' && attrs !== null) {\n const record = attrs as Record<string, unknown>;\n hintVal = record['x-ms-retry-after-ms'] ?? record['x-ms-retry-after'];\n }\n const hintMs = Number(hintVal);\n if (Number.isFinite(hintMs) && hintMs > 0) {\n return Math.max(hintMs, exponentialMs);\n }\n\n return exponentialMs;\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\n/** Options for deleteAllContents and deleteRepository query functions. */\nexport interface DeleteBatchOptions {\n /**\n * Milliseconds to pause after each batch drop to pace RU consumption on\n * low-throughput CosmosDB tiers. 0 means no pacing.\n */\n batchDelayMs?: number;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function deleteRepository(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n options?: DeleteBatchOptions,\n): Promise<void> {\n const batchDelayMs = options?.batchDelayMs ?? 0;\n\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 if (batchDelayMs > 0) await sleep(batchDelayMs);\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 if (batchDelayMs > 0) await sleep(batchDelayMs);\n }\n}\n\nexport async function deleteAllContents(\n conn: CosmosDbConnection,\n repositoryId: string,\n onProgress?: DeleteProgressCallback,\n options?: DeleteBatchOptions,\n): Promise<{ deletedEntities: number; deletedRelationships: number }> {\n const batchDelayMs = options?.batchDelayMs ?? 0;\n\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 if (batchDelayMs > 0) await sleep(batchDelayMs);\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 if (batchDelayMs > 0) await sleep(batchDelayMs);\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 // Gremlin has no \"set to null\" — to clear a property we drop it with a\n // sideEffect step. Drops run before sets because `.sideEffect(...)` is\n // appended to `propParts` in traversal order.\n const dropProp = (key: string) => {\n propParts.push(`.sideEffect(properties('${key}').drop())`);\n };\n\n // Note: entityType drives both the Gremlin vertex label (set at addV) and the\n // `entityType` property. The vertex label is immutable in Gremlin, but every\n // entity query in this provider filters by the `entityType` property rather\n // than vertex label, so updating the property is sufficient for functional\n // correctness. The vertex label becomes a stale hint only.\n if (updates.entityType !== undefined) addProp('entityType', updates.entityType);\n if (updates.label !== undefined) addProp('entityLabel', updates.label);\n if (updates.slug !== undefined) addProp('slug', updates.slug);\n if (updates.summary === null) dropProp('summary');\n else if (updates.summary !== undefined) addProp('summary', updates.summary);\n if (updates.properties !== undefined) addProp('properties', JSON.stringify(updates.properties));\n if (updates.data === null) dropProp('data');\n else if (updates.data !== undefined) addProp('data', updates.data);\n if (updates.dataFormat === null) dropProp('dataFormat');\n else 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 // searchTerm and properties can't be filtered server-side: CosmosDB Gremlin\n // silently drops TextP.containing(), and properties are stored as a JSON blob.\n // When either is present, load all type-matched vertices and filter in memory\n // so pagination and total counts reflect the real result set.\n const hasPropertyFilter =\n query.properties != null && Object.keys(query.properties).length > 0;\n const needsClientFilter = Boolean(query.searchTerm) || hasPropertyFilter;\n\n if (needsClientFilter) {\n const dataResult = await conn.submit(\n `g.V()${filterClause}.valueMap(true)`,\n bindings,\n );\n let items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\n\n if (query.searchTerm) {\n const term = query.searchTerm.toLowerCase();\n items = items.filter(\n (e) =>\n e.label.toLowerCase().includes(term) ||\n e.slug.toLowerCase().includes(term) ||\n (e.summary != null && e.summary.toLowerCase().includes(term)),\n );\n }\n\n if (hasPropertyFilter) {\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 const total = items.length;\n const paged = items.slice(query.offset, query.offset + query.limit);\n\n return {\n items: paged,\n total,\n hasMore: query.offset + query.limit < total,\n limit: query.limit,\n offset: query.offset,\n };\n }\n\n // Fast path: server-side pagination when no client-side filters are needed.\n const countResult = await conn.submit(\n `g.V()${filterClause}.count()`,\n bindings,\n );\n const total = Number(countResult.items[0] ?? 0);\n\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 const items = (dataResult.items as Record<string, unknown>[]).map(entityFromGremlin);\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 — scoped by repositoryId so the same relationship id\n // in a different repo does not cause a false-positive collision.\n const existing = await conn.submit(\n \"g.E().has('repositoryId', rid).has('id', relId).count()\",\n { rid: repositoryId, 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\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 // Cache entity loads within this layer to avoid redundant DB round-trips when\n // the same entity is connected via multiple relationship types. null = rejected by filter.\n const layerCache = new Map<string, StoredEntity | null>();\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 // Skip entities already visited in a previous BFS layer\n if (visited.has(connectedId)) continue;\n\n // Load entity, using per-layer cache to avoid redundant fetches\n let entity: StoredEntity | null | undefined = layerCache.get(connectedId);\n if (entity === undefined) {\n const loaded = await getEntityLight(conn, repositoryId, connectedId);\n if (loaded && (!options.entityTypes || options.entityTypes.length === 0 || options.entityTypes.includes(loaded.entityType))) {\n entity = loaded;\n } else {\n entity = null;\n }\n layerCache.set(connectedId, entity);\n if (entity) nextFrontier.add(connectedId);\n }\n\n if (!entity) continue;\n\n layer[relType]!.entities.push(entity);\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\n // Promote this layer's entities into visited after the full layer is processed,\n // not mid-loop, so the same entity can appear under multiple relationship types.\n for (const id of nextFrontier) {\n visited.add(id);\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 // The E() lookup is scoped by repositoryId so an edge with the same id in a\n // different repo cannot be matched and silently overwritten.\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('repositoryId', rid).has('id', relId).fold().coalesce(unfold()${propParts.join('')}, ${createEdge})`;\n await conn.submit(query, bindings);\n}\n"],"mappings":"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","names":["import_deep_memory","gremlin","sleep","import_deep_memory","dataResult","items","total","import_deep_memory","import_deep_memory","crypto"]}
|