{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/components/capabilities/memory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAEX,oBAAoB,EAGpB,MAAM,cAAc,CAAC;AAgItB,wBAAgB,8BAA8B,CAC7C,SAAS,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAC,CAsD1D","sourcesContent":["import { isDigest } from \"../../bundle/schema.ts\";\nimport type { EvoMemoryNamespace } from \"../memory/store.ts\";\nimport { parseEvoMemoryFragmentInput } from \"../memory/store.ts\";\nimport type { EvoCapabilityName } from \"./protocol.ts\";\nimport type {\n\tEvoCapabilityExecutionResult,\n\tEvoCapabilityService,\n\tEvoCapabilityServiceContext,\n\tEvoPreparedCapabilityRequest,\n} from \"./service.ts\";\n\nconst MEMORY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst MAX_RETRIEVE_LIMIT = 100;\n\ntype MemoryReadRequest = { operation: \"list\" } | { operation: \"get\"; id: string };\ntype MemoryWriteRequest =\n\t| {\n\t\t\toperation: \"append\";\n\t\t\tfragment: ReturnType<typeof parseEvoMemoryFragmentInput>;\n\t\t\texpectedStateDigest?: string;\n\t  }\n\t| {\n\t\t\toperation: \"update\";\n\t\t\tfragment: ReturnType<typeof parseEvoMemoryFragmentInput>;\n\t\t\texpectedStateDigest?: string;\n\t  }\n\t| { operation: \"forget\"; id: string; expectedStateDigest?: string };\ninterface RetrieveRequest {\n\tquery: string;\n\tlimit: number;\n}\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be an object`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction rejectUnknownKeys(record: Record<string, unknown>, allowed: readonly string[], label: string): void {\n\tconst allowedKeys = new Set(allowed);\n\tfor (const key of Object.keys(record)) {\n\t\tif (!allowedKeys.has(key)) throw new Error(`${label} has unknown key: ${key}`);\n\t}\n}\n\nfunction memoryId(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || !MEMORY_ID_PATTERN.test(value)) throw new Error(`${label} is invalid`);\n\treturn value;\n}\n\nfunction optionalStateDigest(value: unknown, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\" || !isDigest(value)) throw new Error(`${label} must be a sha256 digest`);\n\treturn value;\n}\n\nfunction parseMemoryReadRequest(value: unknown): MemoryReadRequest {\n\tconst request = asRecord(value, \"memory-read request\");\n\tif (request.operation === \"list\") {\n\t\trejectUnknownKeys(request, [\"operation\"], \"memory-read list request\");\n\t\treturn { operation: \"list\" };\n\t}\n\tif (request.operation === \"get\") {\n\t\trejectUnknownKeys(request, [\"operation\", \"id\"], \"memory-read get request\");\n\t\treturn { operation: \"get\", id: memoryId(request.id, \"memory-read get request.id\") };\n\t}\n\tthrow new Error(\"memory-read request.operation must be 'list' or 'get'\");\n}\n\nfunction parseMemoryWriteRequest(value: unknown): MemoryWriteRequest {\n\tconst request = asRecord(value, \"memory-write request\");\n\tif (request.operation === \"append\") {\n\t\trejectUnknownKeys(request, [\"operation\", \"fragment\", \"expectedStateDigest\"], \"memory-write append request\");\n\t\tconst expectedStateDigest = optionalStateDigest(\n\t\t\trequest.expectedStateDigest,\n\t\t\t\"memory-write append request.expectedStateDigest\",\n\t\t);\n\t\treturn {\n\t\t\toperation: \"append\",\n\t\t\tfragment: parseEvoMemoryFragmentInput(request.fragment, \"memory-write append request.fragment\"),\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t};\n\t}\n\tif (request.operation === \"update\") {\n\t\trejectUnknownKeys(request, [\"operation\", \"fragment\", \"expectedStateDigest\"], \"memory-write update request\");\n\t\tconst expectedStateDigest = optionalStateDigest(\n\t\t\trequest.expectedStateDigest,\n\t\t\t\"memory-write update request.expectedStateDigest\",\n\t\t);\n\t\treturn {\n\t\t\toperation: \"update\",\n\t\t\tfragment: parseEvoMemoryFragmentInput(request.fragment, \"memory-write update request.fragment\"),\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t};\n\t}\n\tif (request.operation === \"forget\") {\n\t\trejectUnknownKeys(request, [\"operation\", \"id\", \"expectedStateDigest\"], \"memory-write forget request\");\n\t\tconst expectedStateDigest = optionalStateDigest(\n\t\t\trequest.expectedStateDigest,\n\t\t\t\"memory-write forget request.expectedStateDigest\",\n\t\t);\n\t\treturn {\n\t\t\toperation: \"forget\",\n\t\t\tid: memoryId(request.id, \"memory-write forget request.id\"),\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t};\n\t}\n\tthrow new Error(\"memory-write request.operation must be 'append', 'update', or 'forget'\");\n}\n\nfunction parseRetrieveRequest(value: unknown): RetrieveRequest {\n\tconst request = asRecord(value, \"retrieve request\");\n\trejectUnknownKeys(request, [\"query\", \"limit\"], \"retrieve request\");\n\tif (\n\t\ttypeof request.query !== \"string\" ||\n\t\t!request.query.trim() ||\n\t\trequest.query !== request.query.trim() ||\n\t\trequest.query.length > 8_000\n\t) {\n\t\tthrow new Error(\"retrieve request.query must be a trimmed non-empty string of at most 8000 characters\");\n\t}\n\tconst limit = request.limit ?? 10;\n\tif (!Number.isSafeInteger(limit) || (limit as number) <= 0 || (limit as number) > MAX_RETRIEVE_LIMIT) {\n\t\tthrow new Error(`retrieve request.limit must be an integer from 1 to ${MAX_RETRIEVE_LIMIT}`);\n\t}\n\treturn { query: request.query, limit: limit as number };\n}\n\nfunction prepared(request: unknown): EvoPreparedCapabilityRequest {\n\treturn { request };\n}\n\nfunction assertNamespaceComponent(namespace: EvoMemoryNamespace, context: EvoCapabilityServiceContext): void {\n\tnamespace.assertComponent(context.component);\n}\n\nexport function createMemoryCapabilityServices(\n\tnamespace: EvoMemoryNamespace,\n): Partial<Record<EvoCapabilityName, EvoCapabilityService>> {\n\treturn {\n\t\t\"memory-read\": {\n\t\t\tprepare(value, context) {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\treturn prepared(parseMemoryReadRequest(value));\n\t\t\t},\n\t\t\tasync execute(value, context): Promise<EvoCapabilityExecutionResult> {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\tconst request = parseMemoryReadRequest(value);\n\t\t\t\tconst state = await namespace.read();\n\t\t\t\tif (request.operation === \"list\") return { result: state };\n\t\t\t\treturn {\n\t\t\t\t\tresult: {\n\t\t\t\t\t\tstateDigest: state.stateDigest,\n\t\t\t\t\t\tfragment: state.fragments.find((fragment) => fragment.id === request.id) ?? null,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t\t\"memory-write\": {\n\t\t\tprepare(value, context) {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\treturn prepared(parseMemoryWriteRequest(value));\n\t\t\t},\n\t\t\tasync execute(value, context): Promise<EvoCapabilityExecutionResult> {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\tconst request = parseMemoryWriteRequest(value);\n\t\t\t\tif (request.operation === \"append\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tresult: await namespace.append(request.fragment, request.expectedStateDigest),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (request.operation === \"update\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tresult: await namespace.update(request.fragment, request.expectedStateDigest),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst mutation = await namespace.forget(request.id, request.expectedStateDigest);\n\t\t\t\treturn { result: { stateDigest: mutation.stateDigest, forgottenId: request.id } };\n\t\t\t},\n\t\t},\n\t\tretrieve: {\n\t\t\tprepare(value, context) {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\treturn prepared(parseRetrieveRequest(value));\n\t\t\t},\n\t\t\tasync execute(value, context): Promise<EvoCapabilityExecutionResult> {\n\t\t\t\tassertNamespaceComponent(namespace, context);\n\t\t\t\tconst request = parseRetrieveRequest(value);\n\t\t\t\treturn { result: await namespace.retrieve(request.query, request.limit) };\n\t\t\t},\n\t\t},\n\t};\n}\n"]}