{"version":3,"file":"fakes.d.ts","sourceRoot":"","sources":["../src/fakes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtE,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAE7D,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAEhC;IAED,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAGhD;IAED,QAAQ,CAAC,KAAK,EAAE;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACd,GAAG,iBAAiB,CA+BpB;CACD","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { MemoryContract, RetrievalContract } from \"./schemas.js\";\n\nexport class DeterministicMemoryFake {\n\tprivate readonly records = new Map<string, MemoryContract>();\n\n\tput(memory: MemoryContract): void {\n\t\tthis.records.set(memory.memoryId, structuredClone(memory));\n\t}\n\n\tget(memoryId: string): MemoryContract | undefined {\n\t\tconst record = this.records.get(memoryId);\n\t\treturn record ? structuredClone(record) : undefined;\n\t}\n\n\tretrieve(input: {\n\t\trequestId: string;\n\t\townerId: string;\n\t\tprojectId: string;\n\t\tquery: string;\n\t\tlimit: number;\n\t}): RetrievalContract {\n\t\tconst queryTerms = new Set(input.query.toLowerCase().split(/\\s+/).filter(Boolean));\n\t\tconst candidates = [...this.records.values()]\n\t\t\t.filter(\n\t\t\t\t(record) =>\n\t\t\t\t\trecord.ownerId === input.ownerId && record.projectId === input.projectId && !record.tombstonedAt,\n\t\t\t)\n\t\t\t.map((record) => {\n\t\t\t\tconst terms = record.content.toLowerCase().split(/\\s+/).filter(Boolean);\n\t\t\t\tconst matches = terms.filter((term) => queryTerms.has(term)).length;\n\t\t\t\treturn { record, score: terms.length === 0 ? 0 : matches / terms.length };\n\t\t\t})\n\t\t\t.sort((left, right) => right.score - left.score || left.record.memoryId.localeCompare(right.record.memoryId))\n\t\t\t.slice(0, input.limit);\n\t\treturn {\n\t\t\theader: { namespace: \"ai.aletheion.asm\", major: 1, minor: 0 },\n\t\t\trequestId: input.requestId,\n\t\t\townerId: input.ownerId,\n\t\t\tprojectId: input.projectId,\n\t\t\tquery: input.query,\n\t\t\tlimit: input.limit,\n\t\t\talgorithm: \"deterministic-lexical-v1\",\n\t\t\tcandidates: candidates.map(({ record, score }) => ({\n\t\t\t\tmemoryId: record.memoryId,\n\t\t\t\tscore,\n\t\t\t\tselected: score > 0,\n\t\t\t\treasonCodes: score > 0 ? [\"term_overlap\"] : [\"no_overlap\"],\n\t\t\t})),\n\t\t\tstartedAt: deterministicTimestamp(input.requestId),\n\t\t\tlatencyMs: 0,\n\t\t};\n\t}\n}\n\nfunction deterministicTimestamp(seed: string): string {\n\tconst seconds = Number.parseInt(createHash(\"sha256\").update(seed).digest(\"hex\").slice(0, 8), 16);\n\treturn new Date(seconds * 1000).toISOString();\n}\n"]}