@yielded/agent-storage-memory 0.1.0-beta.166 → 0.1.0-beta.168

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.
@@ -1 +1 @@
1
- {"version":3,"file":"MemoryMessageDeliveryStore.mjs","names":[],"sources":["../src/MemoryMessageDeliveryStore.ts"],"sourcesContent":["import { ThreadId } from \"@yielded/agent/identifiers\";\nimport {\n applyMessageDeliveryChange,\n defaultMessageDeliveryStoreLimits,\n MessageDeliveryChange,\n MessageDeliveryError,\n MessageDeliveryFailpoint,\n MessageDeliveryKey,\n MessageDeliveryPageRequest,\n MessageDeliveryRecord,\n MessageDeliveryStore,\n MessageDeliveryStoreLimits,\n messageDeliveryDeadline,\n messageDeliveryKeyString,\n messageDeliveryUsesCapacity,\n isWorkerUpdateDelivery,\n messageDeliveryCapacity,\n sameMessageDeliveryIdentity,\n validateMessageDelivery,\n} from \"@yielded/agent/message-delivery\";\nimport { ScheduleInstant } from \"@yielded/agent/schedule\";\nimport { Effect, Layer, Ref, Schema, Semaphore } from \"effect\";\n\nconst codec = Schema.fromJsonString(MessageDeliveryRecord);\n\nconst decode = (text: string) =>\n Schema.decodeEffect(codec)(text).pipe(\n Effect.mapError(() => MessageDeliveryError.make({ reason: \"corrupt\", operation: \"decode\" })),\n );\n\nconst Scan = Schema.Struct({\n nowMillis: ScheduleInstant,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ownerThreadId: Schema.optionalKey(ThreadId),\n});\n\nexport interface MemoryMessageDeliveryStoreOptions {\n /** UTF-8 bound on the complete stored record, including a processed Settlement. */\n readonly maxStoredValueBytes?: number;\n}\n\n/** Reference adapter. All retained rows are bounded; completed deduplication evidence is never evicted. */\nexport const memoryMessageDeliveryStoreLayer = (\n limits: MessageDeliveryStoreLimits = defaultMessageDeliveryStoreLimits,\n options: MemoryMessageDeliveryStoreOptions = {},\n): Layer.Layer<MessageDeliveryStore, MessageDeliveryError> =>\n Layer.effect(\n MessageDeliveryStore,\n Effect.gen(function* () {\n const config = yield* validateMessageDelivery(MessageDeliveryStoreLimits, limits, \"limits\");\n\n const maxStoredValueBytes = yield* validateMessageDelivery(\n Schema.Int.check(Schema.isGreaterThan(0)),\n options.maxStoredValueBytes ?? 16 * 1_024 * 1_024,\n \"stored-value-limit\",\n );\n\n const state = yield* Ref.make({\n records: new Map<string, string>(),\n pending: new Map<ThreadId, ReadonlySet<MessageDeliveryKey[\"messageId\"]>>(),\n workers: new Map<string, ReadonlySet<MessageDeliveryKey[\"messageId\"]>>(),\n });\n\n const commit = (record: MessageDeliveryRecord, encoded: string) =>\n Ref.update(state, (current) => {\n const key = messageDeliveryKeyString(record.key);\n const keys = new Set(current.pending.get(record.key.ownerThreadId));\n\n if (messageDeliveryUsesCapacity(record)) keys.add(record.key.messageId);\n else keys.delete(record.key.messageId);\n const pending = new Map(current.pending);\n\n if (keys.size === 0) pending.delete(record.key.ownerThreadId);\n else pending.set(record.key.ownerThreadId, keys);\n\n const workers = new Map(current.workers);\n const admission = record.envelope.workerAdmission;\n\n if (admission !== undefined) {\n const worker = admission.origin.worker;\n\n const startKey = JSON.stringify([\n record.key.ownerThreadId,\n worker.delegationId,\n worker.targetAgentId,\n ]);\n\n if (record.key.messageId === admission.origin.firstMessageId)\n workers.set(\n startKey,\n new Set([...(workers.get(startKey) ?? []), record.key.messageId]),\n );\n const pendingKey = JSON.stringify([record.key.ownerThreadId, worker.threadId]);\n const inputs = new Set(workers.get(pendingKey));\n\n if (\n (record.status === \"pending\" || record.status === \"parked\") &&\n record.receipt === null\n )\n inputs.add(record.key.messageId);\n else inputs.delete(record.key.messageId);\n workers.set(pendingKey, inputs);\n }\n\n return { records: new Map(current.records).set(key, encoded), pending, workers };\n });\n\n const lock = yield* Semaphore.make(1);\n const failpoint = yield* MessageDeliveryFailpoint;\n\n const encode = Effect.fn(\"MemoryMessageDeliveryStore.encode\")(function* (\n record: MessageDeliveryRecord,\n ) {\n const text = yield* Schema.encodeEffect(codec)(record).pipe(\n Effect.mapError(() =>\n MessageDeliveryError.make({ reason: \"corrupt\", operation: \"encode\" }),\n ),\n );\n\n if (new TextEncoder().encode(text).byteLength > maxStoredValueBytes) {\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"stored-value-bytes\",\n });\n }\n\n return text;\n });\n\n const all = Effect.fn(\"MemoryMessageDeliveryStore.all\")(function* () {\n return yield* Effect.forEach((yield* Ref.get(state)).records.values(), decode);\n });\n\n const insert: MessageDeliveryStore[\"Service\"][\"insert\"] = Effect.fn(\n \"MemoryMessageDeliveryStore.insert\",\n )(function* (record) {\n const encoded = yield* encode(record);\n const input = yield* decode(encoded);\n\n if (\n input.version !== 1 ||\n input.status !== \"pending\" ||\n input.leaseUntilMillis !== null ||\n input.retry.attempts !== 0 ||\n input.retry.generation !== 0 ||\n input.retry.automaticAttempts !== 0 ||\n input.retry.nextAttemptAtMillis !== input.createdAtMillis ||\n input.retry.lastAttemptAtMillis !== null ||\n input.retry.lastFailure !== null ||\n input.deadlineAtMillis !== input.initialDeadlineAtMillis\n ) {\n return yield* MessageDeliveryError.make({\n reason: \"validation\",\n operation: \"insert-state\",\n });\n }\n if (\n new TextEncoder().encode(JSON.stringify(input.envelope)).byteLength >\n config.maxEnvelopeBytes\n ) {\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"envelope-bytes\",\n });\n }\n yield* failpoint.hit(\"message-delivery:insert:before\");\n\n const inserted = yield* lock.withPermit(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const { records } = yield* Ref.get(state);\n const key = messageDeliveryKeyString(input.key);\n const existingText = records.get(key);\n\n if (existingText !== undefined) {\n const existing = yield* decode(existingText);\n\n if (!sameMessageDeliveryIdentity(existing, input))\n return yield* MessageDeliveryError.make({\n reason: \"conflict\",\n operation: \"insert\",\n });\n\n return existing;\n }\n\n const owned = (yield* all()).filter(\n (record) =>\n record.key.ownerThreadId === input.key.ownerThreadId &&\n isWorkerUpdateDelivery(record) === isWorkerUpdateDelivery(input),\n );\n\n const capacity = messageDeliveryCapacity(config, isWorkerUpdateDelivery(input));\n\n if (\n owned.length >= capacity.retained ||\n owned.filter(messageDeliveryUsesCapacity).length >= capacity.pending\n ) {\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"insert\",\n });\n }\n yield* commit(input, encoded);\n\n return input;\n }),\n ),\n );\n\n yield* failpoint.hit(\"message-delivery:insert:after\");\n\n return yield* decode(yield* encode(inserted));\n });\n\n const get: MessageDeliveryStore[\"Service\"][\"get\"] = Effect.fn(\n \"MemoryMessageDeliveryStore.get\",\n )(function* (key) {\n const input = yield* validateMessageDelivery(MessageDeliveryKey, key, \"get\");\n const text = (yield* Ref.get(state)).records.get(messageDeliveryKeyString(input));\n\n return text === undefined ? null : yield* decode(text);\n });\n\n const change: MessageDeliveryStore[\"Service\"][\"change\"] = Effect.fn(\n \"MemoryMessageDeliveryStore.change\",\n )(function* (key, change) {\n const input = yield* validateMessageDelivery(MessageDeliveryChange, change, \"change\");\n const decodedKey = yield* validateMessageDelivery(MessageDeliveryKey, key, \"change\");\n const point = `message-delivery:${input._tag.toLowerCase()}`;\n\n yield* failpoint.hit(`${point}:before`);\n\n const changed = yield* lock.withPermit(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const existing = yield* get(decodedKey);\n\n if (existing === null)\n return yield* MessageDeliveryError.make({\n reason: \"not-found\",\n operation: \"change\",\n });\n const next = yield* Effect.fromResult(applyMessageDeliveryChange(existing, input));\n const encoded = yield* encode(next);\n\n yield* commit(next, encoded);\n\n return next;\n }),\n ),\n );\n\n yield* failpoint.hit(`${point}:after`);\n\n return yield* decode(yield* encode(changed));\n });\n\n return MessageDeliveryStore.of({\n limits: config,\n maxStoredValueBytes,\n insert,\n get,\n change,\n list: Effect.fn(\"MemoryMessageDeliveryStore.list\")(function* (request) {\n const input = yield* validateMessageDelivery(MessageDeliveryPageRequest, request, \"list\");\n\n const current = yield* Ref.get(state);\n\n const workerKey =\n input.workerStarts !== undefined\n ? JSON.stringify([\n input.ownerThreadId,\n input.workerStarts.delegationId,\n input.workerStarts.targetAgentId,\n ])\n : input.pendingWorker !== undefined\n ? JSON.stringify([input.ownerThreadId, input.pendingWorker])\n : undefined;\n\n const retained =\n workerKey !== undefined || input.pendingOnly\n ? yield* Effect.forEach(\n [\n ...((workerKey === undefined\n ? current.pending.get(input.ownerThreadId)\n : current.workers.get(workerKey)) ?? []),\n ]\n .filter((messageId) => input.after === undefined || messageId > input.after)\n .sort()\n .slice(0, input.limit + 1),\n (messageId) =>\n decode(\n current.records.get(\n messageDeliveryKeyString({ ownerThreadId: input.ownerThreadId, messageId }),\n ) ?? \"\",\n ),\n )\n : yield* all();\n\n const records = retained\n .filter(\n (record) =>\n record.key.ownerThreadId === input.ownerThreadId &&\n (input.after === undefined || record.key.messageId > input.after),\n )\n .sort((left, right) =>\n left.key.messageId < right.key.messageId\n ? -1\n : left.key.messageId > right.key.messageId\n ? 1\n : 0,\n );\n\n const items = records.slice(0, input.limit);\n\n return {\n items,\n next: records.length > input.limit ? (items.at(-1)?.key.messageId ?? null) : null,\n };\n }),\n due: Effect.fn(\"MemoryMessageDeliveryStore.due\")(\n function* (nowMillis, limit, ownerThreadId) {\n const input = yield* validateMessageDelivery(\n Scan,\n { nowMillis, limit, ...(ownerThreadId === undefined ? {} : { ownerThreadId }) },\n \"due\",\n );\n\n return (yield* all())\n .flatMap((record) => {\n const deadline = messageDeliveryDeadline(record);\n\n return deadline !== null &&\n deadline <= input.nowMillis &&\n (input.ownerThreadId === undefined ||\n input.ownerThreadId === record.key.ownerThreadId)\n ? [{ key: record.key, deadline }]\n : [];\n })\n .sort(\n (left, right) =>\n left.deadline - right.deadline ||\n (messageDeliveryKeyString(left.key) < messageDeliveryKeyString(right.key)\n ? -1\n : 1),\n )\n .slice(0, input.limit)\n .map((record) => record.key);\n },\n ),\n nextDeadline: Effect.fn(\"MemoryMessageDeliveryStore.nextDeadline\")(\n function* (ownerThreadId) {\n if (ownerThreadId !== undefined)\n yield* validateMessageDelivery(ThreadId, ownerThreadId, \"nextDeadline\");\n let next: number | null = null;\n\n for (const record of yield* all()) {\n if (ownerThreadId !== undefined && ownerThreadId !== record.key.ownerThreadId)\n continue;\n const deadline = messageDeliveryDeadline(record);\n\n if (deadline !== null && (next === null || deadline < next)) next = deadline;\n }\n\n return next;\n },\n ),\n });\n }),\n );\n\nexport const MemoryMessageDeliveryStoreLive = memoryMessageDeliveryStoreLayer();\n"],"mappings":"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"}
1
+ {"version":3,"file":"MemoryMessageDeliveryStore.mjs","names":[],"sources":["../src/MemoryMessageDeliveryStore.ts"],"sourcesContent":["import { ThreadId } from \"@yielded/agent/identifiers\";\nimport {\n applyMessageDeliveryChange,\n defaultMessageDeliveryStoreLimits,\n MessageDeliveryChange,\n MessageDeliveryError,\n MessageDeliveryFailpoint,\n MessageDeliveryKey,\n MessageDeliveryPageRequest,\n MessageDeliveryRecord,\n MessageDeliveryStore,\n MessageDeliveryStoreLimits,\n messageDeliveryDeadline,\n messageDeliveryKeyString,\n messageDeliveryUsesCapacity,\n isWorkerUpdateDelivery,\n messageDeliveryCapacity,\n sameMessageDeliveryIdentity,\n validateMessageDelivery,\n} from \"@yielded/agent/message-delivery\";\nimport { ScheduleInstant } from \"@yielded/agent/schedule\";\nimport { validateCanonicalSettlement } from \"@yielded/agent/settlement-publisher\";\nimport {\n Settlement,\n settlementFailureFromRecord,\n submissionSettlementRecordId,\n submissionSettlementId,\n} from \"@yielded/agent/submission-ledger\";\nimport { PreparedInput } from \"@yielded/agent/subscription\";\nimport {\n ThreadDeliveryImportReader,\n ThreadImportRejected,\n invalidThreadArchive,\n} from \"@yielded/agent/thread-import\";\nimport { ThreadStoreError, makeTransferFactCheck } from \"@yielded/agent/thread-store\";\nimport { workId, type ThreadWorkEntry } from \"@yielded/agent/thread-work\";\nimport { Effect, Layer, MutableRef, Ref, Schema } from \"effect\";\n\nimport { MemoryThreadStoreKernel } from \"./internal/MemoryThreadStoreKernel.ts\";\nimport { boundedWorkSelection } from \"./internal/WorkSelection.ts\";\n\nconst codec = Schema.fromJsonString(MessageDeliveryRecord);\nconst deliveryFitsTransfer = makeTransferFactCheck(MessageDeliveryRecord);\n\nconst checkTransfer = (record: MessageDeliveryRecord) =>\n deliveryFitsTransfer(record.key.ownerThreadId, { ...record, leaseUntilMillis: null })\n ? Effect.void\n : Effect.fail(\n MessageDeliveryError.make({ reason: \"capacity\", operation: \"transfer-page-bytes\" }),\n );\n\nconst decode = (text: string) =>\n Schema.decodeEffect(codec)(text).pipe(\n Effect.mapError(() => MessageDeliveryError.make({ reason: \"corrupt\", operation: \"decode\" })),\n );\n\nconst Scan = Schema.Struct({\n nowMillis: ScheduleInstant,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ownerThreadId: Schema.optionalKey(ThreadId),\n});\n\nconst position = (keys: ReadonlyArray<string>, key: string) => {\n let low = 0;\n let high = keys.length;\n\n while (low < high) {\n const mid = Math.floor((low + high) / 2);\n\n if (keys[mid] < key) low = mid + 1;\n else high = mid;\n }\n\n return low;\n};\n\nconst retainKey = (keys: Array<string>, key: string) => {\n const at = position(keys, key);\n\n if (keys[at] !== key) keys.splice(at, 0, key);\n};\n\nconst removeKey = (keys: Array<string>, key: string) => {\n const at = position(keys, key);\n\n if (keys[at] === key) keys.splice(at, 1);\n};\n\nconst backend = () => ({\n records: new Map<string, string>(),\n work: new Map<string, ThreadWorkEntry>(),\n ordered: new Map<string, Array<string>>(),\n pending: new Map<ThreadId, Set<MessageDeliveryKey[\"messageId\"]>>(),\n counts: new Map<ThreadId, { retained: number; ordinary: number; update: number; peer: number }>(),\n metadata: new Map<\n string,\n {\n update: boolean;\n pending: boolean;\n peer: boolean;\n deadlineKey?: string;\n importVisit?: \"visiting\" | \"verified\";\n }\n >(),\n deadlines: new Map<string, { readonly key: MessageDeliveryKey; readonly deadline: number }>(),\n deadlineKeys: new Array<string>(),\n ownerDeadlineKeys: new Map<ThreadId, Array<string>>(),\n});\n\nconst ownerKey = (id: ThreadId) => JSON.stringify([id]);\n\nconst keysFor = (current: ReturnType<typeof backend>, key: string) => {\n let keys = current.ordered.get(key);\n\n if (keys === undefined) current.ordered.set(key, (keys = []));\n\n return keys;\n};\n\nexport interface MemoryMessageDeliveryStoreOptions {\n /** UTF-8 bound on the complete stored record, including a processed Settlement. */\n readonly maxStoredValueBytes?: number;\n}\n\n/**\n * Pair with MemoryThreadStoreLive so export/import sees every retained delivery obligation.\n * Each retained value and live partition is bounded; completed deduplication evidence is never evicted.\n */\nexport const memoryMessageDeliveryStoreLayer = (\n limits: MessageDeliveryStoreLimits = defaultMessageDeliveryStoreLimits,\n options: MemoryMessageDeliveryStoreOptions = {},\n): Layer.Layer<MessageDeliveryStore, MessageDeliveryError, MemoryThreadStoreKernel> =>\n Layer.effect(\n MessageDeliveryStore,\n Effect.gen(function* () {\n const journal = yield* MemoryThreadStoreKernel;\n const config = yield* validateMessageDelivery(MessageDeliveryStoreLimits, limits, \"limits\");\n\n const maxStoredValueBytes = yield* validateMessageDelivery(\n Schema.Int.check(Schema.isGreaterThan(0)),\n options.maxStoredValueBytes ?? 16 * 1_024 * 1_024,\n \"stored-value-limit\",\n );\n\n const state = yield* Ref.make(backend());\n\n yield* journal.registerDeliveryLookup((threadId, messageId) =>\n MutableRef.get(state.ref).records.has(\n messageDeliveryKeyString({ ownerThreadId: threadId, messageId }),\n ),\n );\n yield* journal.registerWorkOwner(\"deliveries\", {\n threads: (request) =>\n Ref.get(state).pipe(\n Effect.map((current) => {\n const candidates = boundedWorkSelection<ThreadId>(\n request.limit,\n (id) => id,\n request.afterThreadId,\n );\n\n for (const threadId of current.pending.keys()) candidates.add(threadId);\n const threadIds = candidates.values;\n\n const afterThreadId =\n threadIds.length === request.limit ? threadIds.at(-1) : undefined;\n\n return {\n threadIds,\n ...(afterThreadId === undefined ? {} : { afterThreadId }),\n };\n }),\n ),\n page: (threadId, after, limit) =>\n Effect.gen(function* () {\n const current = yield* Ref.get(state);\n\n const candidates = boundedWorkSelection<MessageDeliveryKey[\"messageId\"]>(\n limit + 1,\n (id) => id,\n after,\n );\n\n for (const id of current.pending.get(threadId) ?? []) candidates.add(id);\n const ids = candidates.values;\n\n const entries: Array<ThreadWorkEntry> = [];\n\n for (const messageId of ids.slice(0, limit)) {\n const key = messageDeliveryKeyString({ ownerThreadId: threadId, messageId });\n const entry = current.work.get(key);\n\n if (entry === undefined || !current.records.has(key))\n return yield* ThreadStoreError.make({\n operation: \"delivery work\",\n message: \"Pending delivery index is incomplete or corrupt\",\n });\n entries.push(entry);\n }\n const next = ids.length > limit ? ids[limit - 1] : undefined;\n\n return { entries, ...(next === undefined ? {} : { after: next }) };\n }),\n });\n\n const commitInto = (\n current: ReturnType<typeof backend>,\n record: MessageDeliveryRecord,\n encoded: string,\n publish: boolean,\n ) => {\n const key = messageDeliveryKeyString(record.key);\n const owner = record.key.ownerThreadId;\n const old = current.metadata.get(key);\n const update = isWorkerUpdateDelivery(record);\n const pending = messageDeliveryUsesCapacity(record);\n\n const peer =\n record.envelope.messageAdmission !== undefined &&\n \"peerName\" in record.envelope.messageAdmission;\n\n let counts = current.counts.get(owner);\n\n if (counts === undefined)\n current.counts.set(owner, (counts = { retained: 0, ordinary: 0, update: 0, peer: 0 }));\n if (old === undefined) counts.retained++;\n if (old?.pending) {\n if (old.update) counts.update--;\n else counts.ordinary--;\n if (old.peer) counts.peer--;\n }\n if (pending) {\n if (update) counts.update++;\n else counts.ordinary++;\n if (peer) counts.peer++;\n }\n let owned = current.pending.get(owner);\n\n if (owned === undefined) current.pending.set(owner, (owned = new Set()));\n if (pending) owned.add(record.key.messageId);\n else owned.delete(record.key.messageId);\n if (owned.size === 0) current.pending.delete(owner);\n retainKey(keysFor(current, ownerKey(owner)), record.key.messageId);\n const admission = record.envelope.workerAdmission;\n\n if (admission !== undefined) {\n const worker = admission.origin.worker;\n\n if (record.key.messageId === admission.origin.firstMessageId)\n retainKey(\n keysFor(current, JSON.stringify([owner, worker.delegationId, worker.targetAgentId])),\n record.key.messageId,\n );\n const inputs = keysFor(current, JSON.stringify([owner, worker.threadId]));\n\n if (\n (record.status === \"pending\" || record.status === \"parked\") &&\n record.receipt === null\n )\n retainKey(inputs, record.key.messageId);\n else removeKey(inputs, record.key.messageId);\n }\n const deadline = messageDeliveryDeadline(record);\n let ownerDeadlines = current.ownerDeadlineKeys.get(owner);\n\n if (ownerDeadlines === undefined)\n current.ownerDeadlineKeys.set(owner, (ownerDeadlines = []));\n if (old?.deadlineKey !== undefined) {\n current.deadlines.delete(old.deadlineKey);\n removeKey(current.deadlineKeys, old.deadlineKey);\n removeKey(ownerDeadlines, old.deadlineKey);\n }\n\n const deadlineKey =\n deadline === null ? undefined : `${String(deadline).padStart(16, \"0\")}:${key}`;\n\n if (deadlineKey !== undefined && deadline !== null) {\n current.deadlines.set(deadlineKey, { key: record.key, deadline });\n retainKey(current.deadlineKeys, deadlineKey);\n retainKey(ownerDeadlines, deadlineKey);\n }\n current.metadata.set(key, {\n update,\n pending,\n peer,\n ...(deadlineKey === undefined ? {} : { deadlineKey }),\n });\n if (pending)\n current.work.set(key, {\n id: workId(\"delivery\", record.key.messageId),\n owner: { _tag: \"Delivery\", messageId: record.key.messageId },\n partition: update ? \"update\" : \"ordinary\",\n stateReference: {\n _tag: \"Delivery\",\n messageId: record.key.messageId,\n version: record.version,\n },\n state: record.status === \"pending\" ? \"ready\" : \"waiting\",\n ...(record.status === \"parked\"\n ? { wait: \"parked\" as const }\n : record.receipt !== null\n ? { wait: \"destination\" as const }\n : {}),\n ...(deadline === null ? {} : { notBeforeMillis: deadline }),\n ...(record.receipt === null\n ? {}\n : {\n receiptId: record.receipt.receiptId,\n queueSequence: record.receipt.queueSequence,\n }),\n });\n else current.work.delete(key);\n current.records.set(key, encoded);\n if (publish) {\n journal.initializeWork(owner);\n journal.retainDelivery(owner, record.key.messageId);\n }\n };\n\n const commit = (record: MessageDeliveryRecord, encoded: string) =>\n Effect.sync(() => commitInto(MutableRef.get(state.ref), record, encoded, true));\n\n const failpoint = yield* MessageDeliveryFailpoint;\n\n const encode = Effect.fnUntraced(function* (record: MessageDeliveryRecord) {\n const text = yield* Schema.encodeEffect(codec)(record).pipe(\n Effect.mapError(() =>\n MessageDeliveryError.make({ reason: \"corrupt\", operation: \"encode\" }),\n ),\n );\n\n if (new TextEncoder().encode(text).byteLength > maxStoredValueBytes) {\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"stored-value-bytes\",\n });\n }\n\n return text;\n });\n\n const insert: MessageDeliveryStore[\"Service\"][\"insert\"] = Effect.fnUntraced(\n function* (record) {\n const encoded = yield* encode(record);\n const input = yield* decode(encoded);\n\n if (\n input.version !== 1 ||\n input.status !== \"pending\" ||\n input.leaseUntilMillis !== null ||\n input.retry.attempts !== 0 ||\n input.retry.generation !== 0 ||\n input.retry.automaticAttempts !== 0 ||\n input.retry.nextAttemptAtMillis !== input.createdAtMillis ||\n input.retry.lastAttemptAtMillis !== null ||\n input.retry.lastFailure !== null ||\n input.deadlineAtMillis !== input.initialDeadlineAtMillis\n ) {\n return yield* MessageDeliveryError.make({\n reason: \"validation\",\n operation: \"insert-state\",\n });\n }\n if (\n new TextEncoder().encode(JSON.stringify(input.envelope)).byteLength >\n config.maxEnvelopeBytes\n ) {\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"envelope-bytes\",\n });\n }\n yield* failpoint.hit(\"message-delivery:insert:before\");\n\n const inserted = yield* journal.withMutation(\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* journal.checkThreadCapacity(input.key.ownerThreadId).pipe(\n Effect.mapError(() =>\n MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"Thread capacity\",\n }),\n ),\n );\n const { records } = yield* Ref.get(state);\n const key = messageDeliveryKeyString(input.key);\n const existingText = records.get(key);\n\n if (existingText !== undefined) {\n const existing = yield* decode(existingText);\n\n if (!sameMessageDeliveryIdentity(existing, input))\n return yield* MessageDeliveryError.make({\n reason: \"conflict\",\n operation: \"insert\",\n });\n\n journal.retainDelivery(existing.key.ownerThreadId, existing.key.messageId);\n\n return existing;\n }\n\n yield* checkTransfer(input);\n const update = isWorkerUpdateDelivery(input);\n const counts = MutableRef.get(state.ref).counts.get(input.key.ownerThreadId);\n const capacity = messageDeliveryCapacity(config, update);\n\n if ((update ? (counts?.update ?? 0) : (counts?.ordinary ?? 0)) >= capacity.pending)\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"insert\",\n });\n yield* commit(input, encoded);\n\n return input;\n }),\n ),\n );\n\n yield* failpoint.hit(\"message-delivery:insert:after\");\n\n return yield* decode(yield* encode(inserted));\n },\n );\n\n const get: MessageDeliveryStore[\"Service\"][\"get\"] = Effect.fnUntraced(function* (key) {\n const input = yield* validateMessageDelivery(MessageDeliveryKey, key, \"get\");\n const text = (yield* Ref.get(state)).records.get(messageDeliveryKeyString(input));\n\n return text === undefined ? null : yield* decode(text);\n });\n\n const change: MessageDeliveryStore[\"Service\"][\"change\"] = Effect.fnUntraced(\n function* (key, change) {\n const input = yield* validateMessageDelivery(MessageDeliveryChange, change, \"change\");\n const decodedKey = yield* validateMessageDelivery(MessageDeliveryKey, key, \"change\");\n const point = `message-delivery:${input._tag.toLowerCase()}`;\n\n yield* failpoint.hit(`${point}:before`);\n\n const changed = yield* journal.withMutation(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const existing = yield* get(decodedKey);\n\n if (existing === null)\n return yield* MessageDeliveryError.make({\n reason: \"not-found\",\n operation: \"change\",\n });\n const next = yield* Effect.fromResult(applyMessageDeliveryChange(existing, input));\n\n if (next === existing) return existing;\n yield* checkTransfer(next);\n const encoded = yield* encode(next);\n\n yield* commit(next, encoded);\n\n return next;\n }),\n ),\n );\n\n yield* failpoint.hit(`${point}:after`);\n\n return yield* decode(yield* encode(changed));\n },\n );\n\n const transferDecode = (text: string) =>\n decode(text).pipe(\n Effect.mapError(() =>\n ThreadStoreError.make({\n operation: \"delivery transfer\",\n message: \"Invalid retained delivery wire\",\n }),\n ),\n );\n\n yield* journal.registerDeliveryTransfer({\n record: (threadId, messageId) => {\n const text = MutableRef.get(state.ref).records.get(\n messageDeliveryKeyString({ ownerThreadId: threadId, messageId }),\n );\n\n return text === undefined ? Effect.succeed(undefined) : transferDecode(text);\n },\n snapshot: (threadId) => {\n const counts = MutableRef.get(state.ref).counts.get(threadId);\n\n return {\n idle: (MutableRef.get(state.ref).pending.get(threadId)?.size ?? 0) === 0,\n deliveries: counts?.retained ?? 0,\n };\n },\n pendingPeerCount: (threadId, limit) =>\n Math.min(MutableRef.get(state.ref).counts.get(threadId)?.peer ?? 0, limit),\n facts: Effect.fnUntraced(function* (threadId, after) {\n const current = MutableRef.get(state.ref);\n const keys = current.ordered.get(ownerKey(threadId)) ?? [];\n\n const at =\n after === undefined\n ? 0\n : position(keys, after) + Number(keys[position(keys, after)] === after);\n\n const messageId = keys[at];\n\n const record =\n messageId === undefined\n ? undefined\n : yield* transferDecode(\n current.records.get(\n messageDeliveryKeyString({\n ownerThreadId: threadId,\n messageId: Schema.decodeSync(MessageDeliveryKey.fields.messageId)(messageId),\n }),\n ) ?? \"\",\n );\n\n return {\n facts: {\n admissions: [],\n commands: { aborts: [], approvals: [], resolutions: [] },\n deliveries:\n record === undefined\n ? []\n : [MessageDeliveryRecord.make({ ...record, leaseUntilMillis: null })],\n },\n after: messageId ?? after ?? \"\",\n };\n }),\n startImport: Effect.fnUntraced(function* (threadId) {\n const current = MutableRef.get(state.ref);\n\n if ((current.counts.get(threadId)?.retained ?? 0) > 0)\n return yield* ThreadImportRejected.make({\n threadId,\n reason: \"target-not-empty\",\n message: \"Destination Thread owns retained deliveries\",\n });\n const staged = backend();\n\n return {\n record: (messageId) => {\n const text = staged.records.get(\n messageDeliveryKeyString({ ownerThreadId: threadId, messageId }),\n );\n\n return text === undefined ? Effect.succeed(undefined) : transferDecode(text);\n },\n has: (messageId) =>\n staged.records.has(messageDeliveryKeyString({ ownerThreadId: threadId, messageId })),\n stage: Effect.fnUntraced(function* (page) {\n for (const record of page.archive.deliveries) {\n const key = messageDeliveryKeyString(record.key);\n\n if (staged.records.has(key) || current.records.has(key))\n return yield* invalidThreadArchive(\"Duplicate retained delivery\", threadId);\n\n const text = yield* encode(record).pipe(\n Effect.mapError(() =>\n ThreadImportRejected.make({\n threadId,\n reason: \"unsupported-capacity\",\n message: \"Delivery wire exceeds destination stored-value bound\",\n }),\n ),\n );\n\n if (\n new TextEncoder().encode(\n JSON.stringify(\n yield* Schema.encodeEffect(PreparedInput)(record.envelope).pipe(\n Effect.mapError(() =>\n invalidThreadArchive(\"Invalid delivery envelope\", threadId),\n ),\n ),\n ),\n ).byteLength > config.maxEnvelopeBytes\n )\n return yield* ThreadImportRejected.make({\n threadId,\n reason: \"unsupported-capacity\",\n message: \"Delivery envelope exceeds destination bound\",\n });\n const counts = staged.counts.get(threadId);\n\n if (\n messageDeliveryUsesCapacity(record) &&\n (isWorkerUpdateDelivery(record)\n ? (counts?.update ?? 0)\n : (counts?.ordinary ?? 0)) >=\n messageDeliveryCapacity(config, isWorkerUpdateDelivery(record)).pending\n )\n return yield* ThreadImportRejected.make({\n threadId,\n reason: \"unsupported-capacity\",\n message: \"Pending delivery capacity exceeded\",\n });\n commitInto(staged, record, text, false);\n }\n }),\n prepareCommit: Effect.fnUntraced(function* () {\n const reader = yield* ThreadDeliveryImportReader;\n\n const read = (messageId: MessageDeliveryKey[\"messageId\"]) => {\n const text = staged.records.get(\n messageDeliveryKeyString({ ownerThreadId: threadId, messageId }),\n );\n\n return text === undefined\n ? Effect.fail(invalidThreadArchive(\"Missing delivery predecessor\", threadId))\n : transferDecode(text);\n };\n\n const visit = (messageId: MessageDeliveryKey[\"messageId\"]) => {\n const metadata = staged.metadata.get(\n messageDeliveryKeyString({ ownerThreadId: threadId, messageId }),\n );\n\n return metadata === undefined\n ? Effect.fail(\n invalidThreadArchive(\"Missing delivery predecessor metadata\", threadId),\n )\n : Effect.succeed(metadata);\n };\n\n const verifyPredecessors = Effect.fnUntraced(function* (\n start: MessageDeliveryKey[\"messageId\"],\n ) {\n let cursor: MessageDeliveryKey[\"messageId\"] | undefined = start;\n\n while (cursor !== undefined) {\n const metadata = yield* visit(cursor);\n\n if (metadata.importVisit === \"verified\") break;\n if (metadata.importVisit === \"visiting\")\n return yield* invalidThreadArchive(\"Delivery predecessor cycle\", threadId);\n metadata.importVisit = \"visiting\";\n const record: MessageDeliveryRecord = yield* read(cursor);\n\n if (\n record.predecessor !== undefined &&\n (yield* read(record.predecessor)).createdAtMillis > record.createdAtMillis\n )\n return yield* invalidThreadArchive(\n \"Delivery predecessor has a later boundary\",\n threadId,\n );\n cursor = record.predecessor;\n }\n cursor = start;\n while (cursor !== undefined) {\n const metadata = yield* visit(cursor);\n\n if (metadata.importVisit === \"verified\") break;\n metadata.importVisit = \"verified\";\n cursor = (yield* read(cursor)).predecessor;\n }\n });\n\n for (const text of staged.records.values()) {\n const d = yield* transferDecode(text);\n\n yield* verifyPredecessors(d.key.messageId);\n if (d.receipt !== null) {\n if (\n d.settlement !== null &&\n d.settlement.settlementId !== submissionSettlementId(d.receipt.submissionId)\n )\n return yield* invalidThreadArchive(\n \"Delivery settlement identity is not canonical\",\n threadId,\n );\n const foreign = d.receipt.threadId !== threadId;\n\n if (foreign && d.status !== \"processed\")\n return yield* ThreadImportRejected.make({\n threadId,\n reason: \"unsupported-obligations\",\n message: \"Live foreign delivery receipt cannot be restored\",\n });\n\n const destination = yield* reader.admission(\n d.receipt.threadId,\n d.receipt.submissionId,\n );\n\n // A closed foreign delivery retains frozen evidence, not the receiver's execution authority.\n if (destination === undefined) {\n if (foreign && d.status === \"processed\") continue;\n\n return yield* invalidThreadArchive(\n \"Destination delivery receipt evidence is missing\",\n threadId,\n );\n }\n\n const expected = PreparedInput.make({\n schemaVersion: 1,\n authorization: d.envelope.authorization,\n threadId: destination.threadId,\n deliveryPrincipal: destination.principal,\n admissionKey: destination.idempotencyKey,\n agentId: destination.agentId,\n definitions: destination.agentDigests,\n input: destination.inputPayload,\n inputDigest: destination.inputDigest,\n ...(destination.admissionGroup === undefined\n ? {}\n : { admissionGroup: destination.admissionGroup }),\n ...(destination.admissionFence === undefined\n ? {}\n : { admissionFence: destination.admissionFence }),\n ...(destination.workerAdmission === undefined\n ? {}\n : { workerAdmission: destination.workerAdmission }),\n ...(destination.messageAdmission === undefined\n ? {}\n : { messageAdmission: destination.messageAdmission }),\n });\n\n if (\n d.receipt.receiptId !== destination.receiptId ||\n d.receipt.queueSequence !== destination.queueSequence ||\n !Schema.toEquivalence(PreparedInput)(d.envelope, expected)\n )\n return yield* invalidThreadArchive(\n \"Delivery envelope differs from destination admission\",\n threadId,\n );\n if (d.settlement !== null) {\n const record = yield* reader.record(\n destination.threadId,\n submissionSettlementRecordId(destination.submissionId),\n );\n\n if (record === undefined) {\n if (foreign) continue;\n\n return yield* invalidThreadArchive(\n \"Processed delivery has no destination settlement\",\n threadId,\n );\n }\n\n const settled = yield* validateCanonicalSettlement(record, destination).pipe(\n Effect.mapError(() =>\n invalidThreadArchive(\"Invalid destination settlement\", threadId),\n ),\n );\n\n const failure = settlementFailureFromRecord(record);\n\n const expected = Settlement.make({\n submissionId: settled.submissionId,\n receiptId: settled.receiptId,\n settlementId: settled.settlementId,\n outcome: settled.outcome,\n settledAt: d.settlement.settledAt,\n ...(failure === undefined ? {} : { failure }),\n ...(d.settlement.runDisposition === undefined ||\n settled.runDisposition === undefined\n ? {}\n : { runDisposition: settled.runDisposition }),\n ...(d.settlement.usageSummary === undefined ||\n settled.usageSummary === undefined\n ? {}\n : { usageSummary: settled.usageSummary }),\n });\n\n if (!Schema.toEquivalence(Settlement)(d.settlement, expected))\n return yield* invalidThreadArchive(\n \"Delivery settlement differs from destination evidence\",\n threadId,\n );\n }\n }\n }\n\n return () => {\n for (const text of staged.records.values())\n commitInto(current, Schema.decodeSync(codec)(text), text, true);\n };\n }),\n };\n }),\n });\n\n return MessageDeliveryStore.of({\n limits: config,\n maxStoredValueBytes,\n insert,\n get,\n change,\n list: Effect.fnUntraced(function* (request) {\n const input = yield* validateMessageDelivery(MessageDeliveryPageRequest, request, \"list\");\n\n const current = yield* Ref.get(state);\n\n const workerKey =\n input.workerStarts !== undefined\n ? JSON.stringify([\n input.ownerThreadId,\n input.workerStarts.delegationId,\n input.workerStarts.targetAgentId,\n ])\n : input.pendingWorker !== undefined\n ? JSON.stringify([input.ownerThreadId, input.pendingWorker])\n : undefined;\n\n const keys =\n workerKey === undefined\n ? input.pendingOnly\n ? Array.from(current.pending.get(input.ownerThreadId) ?? []).sort()\n : (current.ordered.get(ownerKey(input.ownerThreadId)) ?? [])\n : (current.ordered.get(workerKey) ?? []);\n\n const start =\n input.after === undefined\n ? 0\n : position(keys, input.after) +\n Number(keys[position(keys, input.after)] === input.after);\n\n const items: Array<MessageDeliveryRecord> = [];\n let bytes = 0;\n let at = start;\n\n while (at < keys.length && items.length < input.limit) {\n const text = current.records.get(\n messageDeliveryKeyString({\n ownerThreadId: input.ownerThreadId,\n messageId: Schema.decodeSync(MessageDeliveryKey.fields.messageId)(keys[at]),\n }),\n );\n\n if (text === undefined)\n return yield* MessageDeliveryError.make({\n reason: \"corrupt\",\n operation: \"list locator\",\n });\n const size = new TextEncoder().encode(text).byteLength;\n\n if (size > 32 * 1024 * 1024)\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"list byte bound\",\n });\n if (bytes + size > 32 * 1024 * 1024) break;\n items.push(yield* decode(text));\n bytes += size;\n at++;\n }\n\n return {\n items,\n next: at < keys.length ? (items.at(-1)?.key.messageId ?? null) : null,\n };\n }),\n due: Effect.fnUntraced(function* (nowMillis, limit, ownerThreadId) {\n const input = yield* validateMessageDelivery(\n Scan,\n { nowMillis, limit, ...(ownerThreadId === undefined ? {} : { ownerThreadId }) },\n \"due\",\n );\n\n const current = MutableRef.get(state.ref);\n\n const keys =\n input.ownerThreadId === undefined\n ? current.deadlineKeys\n : (current.ownerDeadlineKeys.get(input.ownerThreadId) ?? []);\n\n const selected: Array<MessageDeliveryKey> = [];\n\n for (const key of keys) {\n const row = current.deadlines.get(key);\n\n if (row === undefined)\n return yield* MessageDeliveryError.make({\n reason: \"corrupt\",\n operation: \"deadline index\",\n });\n if (row.deadline > input.nowMillis || selected.length === input.limit) break;\n selected.push(row.key);\n }\n\n return selected;\n }),\n nextDeadline: Effect.fnUntraced(function* (ownerThreadId) {\n if (ownerThreadId !== undefined)\n yield* validateMessageDelivery(ThreadId, ownerThreadId, \"nextDeadline\");\n const current = MutableRef.get(state.ref);\n\n const first = (\n ownerThreadId === undefined\n ? current.deadlineKeys\n : current.ownerDeadlineKeys.get(ownerThreadId)\n )?.[0];\n\n return first === undefined ? null : (current.deadlines.get(first)?.deadline ?? null);\n }),\n });\n }),\n );\n\nexport const MemoryMessageDeliveryStoreLive = memoryMessageDeliveryStoreLayer();\n"],"mappings":"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"}
@@ -27,7 +27,7 @@ const sameOwner = (record, owner) => scheduleOwnerKey(record.owner) === schedule
27
27
  const makeScheduleStore = Effect.gen(function* () {
28
28
  const state = yield* Ref.make({ records: /* @__PURE__ */ new Map() });
29
29
  const failpoint = yield* ScheduleFailpoint;
30
- const insert = Effect.fn("MemoryScheduleStore.insert")((record, ownerLimit) => Effect.gen(function* () {
30
+ const insert = Effect.fnUntraced(function* (record, ownerLimit) {
31
31
  const encoded = yield* encodeRecord("insert", record);
32
32
  yield* failpoint.hit("schedule:insert:before");
33
33
  const decision = yield* Effect.uninterruptible(Ref.modify(state, (current) => {
@@ -63,13 +63,13 @@ const makeScheduleStore = Effect.gen(function* () {
63
63
  const inserted = yield* Effect.fromResult(decision);
64
64
  yield* failpoint.hit("schedule:insert:after");
65
65
  return yield* decodeRecord("insert", yield* encodeRecord("insert", inserted));
66
- }));
67
- const get = Effect.fn("MemoryScheduleStore.get")(function* (key) {
66
+ });
67
+ const get = Effect.fnUntraced(function* (key) {
68
68
  const decodedKey = yield* decodeInput("get", ScheduleKey, key);
69
69
  const text = (yield* Ref.get(state)).records.get(scheduleKeyString(decodedKey));
70
70
  return text === void 0 ? null : yield* decodeRecord("get", text);
71
71
  });
72
- const list = Effect.fn("MemoryScheduleStore.list")(function* (request) {
72
+ const list = Effect.fnUntraced(function* (request) {
73
73
  const decodedRequest = yield* decodeInput("list", SchedulePageRequest, request);
74
74
  const records = [];
75
75
  for (const text of (yield* Ref.get(state)).records.values()) {
@@ -84,7 +84,7 @@ const makeScheduleStore = Effect.gen(function* () {
84
84
  next: hasNext ? items.at(-1)?.scheduleId ?? null : null
85
85
  };
86
86
  });
87
- const change = Effect.fn("MemoryScheduleStore.change")((key, command, ownerLimit = defaultSchedulingLimits.maxSchedulesPerOwner) => Effect.gen(function* () {
87
+ const change = Effect.fnUntraced(function* (key, command, ownerLimit = defaultSchedulingLimits.maxSchedulesPerOwner) {
88
88
  const decodedKey = yield* decodeInput("change", ScheduleKey, key);
89
89
  const decodedCommand = yield* decodeInput("change", ScheduleChange, command);
90
90
  yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:before`);
@@ -122,8 +122,8 @@ const makeScheduleStore = Effect.gen(function* () {
122
122
  const changed = yield* Effect.fromResult(decision);
123
123
  yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:after`);
124
124
  return yield* decodeRecord("change", yield* encodeRecord("change", changed));
125
- }));
126
- const due = Effect.fn("MemoryScheduleStore.due")(function* (nowMillis, limit, owner, after) {
125
+ });
126
+ const due = Effect.fnUntraced(function* (nowMillis, limit, owner, after) {
127
127
  const decodedOwner = owner === void 0 ? void 0 : yield* decodeInput("due", ScheduleOwner, owner);
128
128
  const cursor = after === void 0 ? void 0 : yield* decodeInput("due", ScheduleDueCursor, after);
129
129
  const records = [];
@@ -141,7 +141,7 @@ const makeScheduleStore = Effect.gen(function* () {
141
141
  });
142
142
  return records.slice(0, limit);
143
143
  });
144
- const nextDeadline = Effect.fn("MemoryScheduleStore.nextDeadline")(function* (owner) {
144
+ const nextDeadline = Effect.fnUntraced(function* (owner) {
145
145
  const decodedOwner = owner === void 0 ? void 0 : yield* decodeInput("nextDeadline", ScheduleOwner, owner);
146
146
  let earliest = null;
147
147
  for (const text of (yield* Ref.get(state)).records.values()) {
@@ -1 +1 @@
1
- {"version":3,"file":"MemoryScheduleStore.mjs","names":[],"sources":["../src/MemoryScheduleStore.ts"],"sourcesContent":["import {\n ScheduleCapacityError,\n ScheduleDueCursor,\n defaultSchedulingLimits,\n ScheduleChange,\n ScheduleConflict,\n ScheduleFailpoint,\n ScheduleKey,\n ScheduleNotFound,\n ScheduleOwner,\n SchedulePageRequest,\n ScheduleRecord,\n ScheduleStorageError,\n ScheduleStore,\n} from \"@yielded/agent/schedule\";\nimport {\n scheduleUsesCapacity,\n applyScheduleChange,\n compareScheduleKeys,\n compareScheduleNames,\n scheduleDeadline,\n scheduleKeyString,\n scheduleKeyOf,\n scheduleOwnerKey,\n} from \"@yielded/agent/schedule-transition\";\nimport { Effect, Layer, Ref, Result, Schema } from \"effect\";\n\ninterface MemoryScheduleState {\n readonly records: ReadonlyMap<string, string>;\n}\n\nconst storageError = (operation: string, reason: \"unavailable\" | \"corrupt\") =>\n ScheduleStorageError.make({ operation, reason });\n\nconst encodeRecord = (operation: string, record: ScheduleRecord) =>\n Effect.try({\n try: () => Schema.encodeSync(Schema.fromJsonString(ScheduleRecord))(record),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst decodeRecord = (operation: string, encoded: string) =>\n Effect.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(encoded),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst decodeInput = <A, I>(operation: string, schema: Schema.Codec<A, I>, value: unknown) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst sameOwner = (record: ScheduleRecord, owner: ScheduleOwner): boolean =>\n scheduleOwnerKey(record.owner) === scheduleOwnerKey(owner);\n\nconst makeScheduleStore = Effect.gen(function* () {\n const state = yield* Ref.make<MemoryScheduleState>({ records: new Map() });\n const failpoint = yield* ScheduleFailpoint;\n\n const insert: ScheduleStore[\"Service\"][\"insert\"] = Effect.fn(\"MemoryScheduleStore.insert\")(\n (record, ownerLimit) =>\n Effect.gen(function* () {\n const encoded = yield* encodeRecord(\"insert\", record);\n\n yield* failpoint.hit(\"schedule:insert:before\");\n\n const decision = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<\n ScheduleRecord,\n ScheduleConflict | ScheduleCapacityError | ScheduleStorageError\n >,\n MemoryScheduleState,\n ] => {\n const key = scheduleKeyString(record);\n const existingText = current.records.get(key);\n\n if (existingText !== undefined) {\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(existingText),\n catch: () => storageError(\"insert\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n if (decoded.success.creationFingerprint === record.creationFingerprint) {\n return [Result.succeed(decoded.success), current];\n }\n\n return [\n Result.fail(\n ScheduleConflict.make({ reason: \"creation\", key: scheduleKeyOf(record) }),\n ),\n current,\n ];\n }\n\n let ownerCount = 0;\n\n for (const text of current.records.values()) {\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(text),\n catch: () => storageError(\"insert\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n if (\n sameOwner(decoded.success, record.owner) &&\n scheduleUsesCapacity(decoded.success)\n )\n ownerCount += 1;\n }\n if (ownerCount >= ownerLimit) {\n return [Result.fail(ScheduleCapacityError.make({ limit: ownerLimit })), current];\n }\n const records = new Map(current.records);\n\n records.set(key, encoded);\n const next = { records };\n\n return [Result.succeed(record), next];\n },\n ),\n );\n\n const inserted = yield* Effect.fromResult(decision);\n\n yield* failpoint.hit(\"schedule:insert:after\");\n\n return yield* decodeRecord(\"insert\", yield* encodeRecord(\"insert\", inserted));\n }),\n );\n\n const get: ScheduleStore[\"Service\"][\"get\"] = Effect.fn(\"MemoryScheduleStore.get\")(\n function* (key) {\n const decodedKey = yield* decodeInput(\"get\", ScheduleKey, key);\n const text = (yield* Ref.get(state)).records.get(scheduleKeyString(decodedKey));\n\n return text === undefined ? null : yield* decodeRecord(\"get\", text);\n },\n );\n\n const list: ScheduleStore[\"Service\"][\"list\"] = Effect.fn(\"MemoryScheduleStore.list\")(\n function* (request) {\n const decodedRequest = yield* decodeInput(\"list\", SchedulePageRequest, request);\n const records: Array<ScheduleRecord> = [];\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"list\", text);\n\n if (\n sameOwner(record, decodedRequest.owner) &&\n (decodedRequest.after === undefined ||\n compareScheduleNames(record.scheduleId, decodedRequest.after) > 0)\n ) {\n records.push(record);\n }\n }\n records.sort((left, right) => compareScheduleNames(left.scheduleId, right.scheduleId));\n const hasNext = records.length > decodedRequest.limit;\n const items = records.slice(0, decodedRequest.limit);\n\n return {\n items,\n next: hasNext ? (items.at(-1)?.scheduleId ?? null) : null,\n };\n },\n );\n\n const change: ScheduleStore[\"Service\"][\"change\"] = Effect.fn(\"MemoryScheduleStore.change\")(\n (key, command, ownerLimit = defaultSchedulingLimits.maxSchedulesPerOwner) =>\n Effect.gen(function* () {\n const decodedKey = yield* decodeInput(\"change\", ScheduleKey, key);\n const decodedCommand = yield* decodeInput(\"change\", ScheduleChange, command);\n\n yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:before`);\n\n const decision = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<\n ScheduleRecord,\n ScheduleConflict | ScheduleStorageError | ScheduleNotFound | ScheduleCapacityError\n >,\n MemoryScheduleState,\n ] => {\n const storageKey = scheduleKeyString(decodedKey);\n const text = current.records.get(storageKey);\n\n if (text === undefined) {\n return [Result.fail(ScheduleNotFound.make({ key: decodedKey })), current];\n }\n\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(text),\n catch: () => storageError(\"change\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n const applied = applyScheduleChange(decoded.success, decodedCommand);\n\n if (Result.isFailure(applied)) {\n return [Result.fail(applied.failure), current];\n }\n if (applied.success === decoded.success) {\n return [Result.succeed(decoded.success), current];\n }\n if (!scheduleUsesCapacity(decoded.success) && scheduleUsesCapacity(applied.success)) {\n let count = 0;\n\n for (const text of current.records.values()) {\n const candidate = Schema.decodeResult(Schema.fromJsonString(ScheduleRecord))(\n text,\n );\n\n if (Result.isFailure(candidate))\n return [Result.fail(storageError(\"change\", \"corrupt\")), current];\n if (\n sameOwner(candidate.success, decodedKey.owner) &&\n scheduleUsesCapacity(candidate.success)\n )\n count += 1;\n }\n if (count >= ownerLimit)\n return [Result.fail(ScheduleCapacityError.make({ limit: ownerLimit })), current];\n }\n\n const encoded = Result.try({\n try: () =>\n Schema.encodeSync(Schema.fromJsonString(ScheduleRecord))(applied.success),\n catch: () => storageError(\"change\", \"corrupt\"),\n });\n\n if (Result.isFailure(encoded)) {\n return [Result.fail(encoded.failure), current];\n }\n const records = new Map(current.records);\n\n records.set(storageKey, encoded.success);\n const next = { records };\n\n return [Result.succeed(applied.success), next];\n },\n ),\n );\n\n const changed = yield* Effect.fromResult(decision);\n\n yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:after`);\n\n return yield* decodeRecord(\"change\", yield* encodeRecord(\"change\", changed));\n }),\n );\n\n const due: ScheduleStore[\"Service\"][\"due\"] = Effect.fn(\"MemoryScheduleStore.due\")(\n function* (nowMillis, limit, owner, after) {\n const decodedOwner =\n owner === undefined ? undefined : yield* decodeInput(\"due\", ScheduleOwner, owner);\n\n const cursor =\n after === undefined ? undefined : yield* decodeInput(\"due\", ScheduleDueCursor, after);\n\n const records: Array<ScheduleDueCursor> = [];\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"due\", text);\n const deadline = scheduleDeadline(record);\n\n if (\n deadline !== null &&\n deadline <= nowMillis &&\n (decodedOwner === undefined || sameOwner(record, decodedOwner)) &&\n (cursor === undefined ||\n deadline > cursor.deadlineAtMillis ||\n (deadline === cursor.deadlineAtMillis && compareScheduleKeys(record, cursor) > 0))\n ) {\n records.push({ ...scheduleKeyOf(record), deadlineAtMillis: deadline });\n }\n }\n records.sort((left, right) => {\n const byDeadline = left.deadlineAtMillis - right.deadlineAtMillis;\n\n return byDeadline !== 0 ? byDeadline : compareScheduleKeys(left, right);\n });\n\n return records.slice(0, limit);\n },\n );\n\n const nextDeadline: ScheduleStore[\"Service\"][\"nextDeadline\"] = Effect.fn(\n \"MemoryScheduleStore.nextDeadline\",\n )(function* (owner) {\n const decodedOwner =\n owner === undefined ? undefined : yield* decodeInput(\"nextDeadline\", ScheduleOwner, owner);\n\n let earliest: number | null = null;\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"nextDeadline\", text);\n\n if (decodedOwner !== undefined && !sameOwner(record, decodedOwner)) continue;\n const deadline = scheduleDeadline(record);\n\n if (deadline !== null && (earliest === null || deadline < earliest)) earliest = deadline;\n }\n\n return earliest;\n });\n\n return ScheduleStore.of({ insert, get, list, change, due, nextDeadline });\n});\n\nexport const memoryScheduleStoreLayer = (): Layer.Layer<ScheduleStore> =>\n Layer.effect(ScheduleStore, makeScheduleStore);\n\nexport const MemoryScheduleStoreLive: Layer.Layer<ScheduleStore> = memoryScheduleStoreLayer();\n"],"mappings":"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"}
1
+ {"version":3,"file":"MemoryScheduleStore.mjs","names":[],"sources":["../src/MemoryScheduleStore.ts"],"sourcesContent":["import {\n ScheduleCapacityError,\n ScheduleDueCursor,\n defaultSchedulingLimits,\n ScheduleChange,\n ScheduleConflict,\n ScheduleFailpoint,\n ScheduleKey,\n ScheduleNotFound,\n ScheduleOwner,\n SchedulePageRequest,\n ScheduleRecord,\n ScheduleStorageError,\n ScheduleStore,\n} from \"@yielded/agent/schedule\";\nimport {\n scheduleUsesCapacity,\n applyScheduleChange,\n compareScheduleKeys,\n compareScheduleNames,\n scheduleDeadline,\n scheduleKeyString,\n scheduleKeyOf,\n scheduleOwnerKey,\n} from \"@yielded/agent/schedule-transition\";\nimport { Effect, Layer, Ref, Result, Schema } from \"effect\";\n\ninterface MemoryScheduleState {\n readonly records: ReadonlyMap<string, string>;\n}\n\nconst storageError = (operation: string, reason: \"unavailable\" | \"corrupt\") =>\n ScheduleStorageError.make({ operation, reason });\n\nconst encodeRecord = (operation: string, record: ScheduleRecord) =>\n Effect.try({\n try: () => Schema.encodeSync(Schema.fromJsonString(ScheduleRecord))(record),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst decodeRecord = (operation: string, encoded: string) =>\n Effect.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(encoded),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst decodeInput = <A, I>(operation: string, schema: Schema.Codec<A, I>, value: unknown) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value),\n catch: () => storageError(operation, \"corrupt\"),\n });\n\nconst sameOwner = (record: ScheduleRecord, owner: ScheduleOwner): boolean =>\n scheduleOwnerKey(record.owner) === scheduleOwnerKey(owner);\n\nconst makeScheduleStore = Effect.gen(function* () {\n const state = yield* Ref.make<MemoryScheduleState>({ records: new Map() });\n const failpoint = yield* ScheduleFailpoint;\n\n const insert: ScheduleStore[\"Service\"][\"insert\"] = Effect.fnUntraced(\n function* (record, ownerLimit) {\n const encoded = yield* encodeRecord(\"insert\", record);\n\n yield* failpoint.hit(\"schedule:insert:before\");\n\n const decision = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<\n ScheduleRecord,\n ScheduleConflict | ScheduleCapacityError | ScheduleStorageError\n >,\n MemoryScheduleState,\n ] => {\n const key = scheduleKeyString(record);\n const existingText = current.records.get(key);\n\n if (existingText !== undefined) {\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(existingText),\n catch: () => storageError(\"insert\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n if (decoded.success.creationFingerprint === record.creationFingerprint) {\n return [Result.succeed(decoded.success), current];\n }\n\n return [\n Result.fail(\n ScheduleConflict.make({ reason: \"creation\", key: scheduleKeyOf(record) }),\n ),\n current,\n ];\n }\n\n let ownerCount = 0;\n\n for (const text of current.records.values()) {\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(text),\n catch: () => storageError(\"insert\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n if (sameOwner(decoded.success, record.owner) && scheduleUsesCapacity(decoded.success))\n ownerCount += 1;\n }\n if (ownerCount >= ownerLimit) {\n return [Result.fail(ScheduleCapacityError.make({ limit: ownerLimit })), current];\n }\n const records = new Map(current.records);\n\n records.set(key, encoded);\n const next = { records };\n\n return [Result.succeed(record), next];\n },\n ),\n );\n\n const inserted = yield* Effect.fromResult(decision);\n\n yield* failpoint.hit(\"schedule:insert:after\");\n\n return yield* decodeRecord(\"insert\", yield* encodeRecord(\"insert\", inserted));\n },\n );\n\n const get: ScheduleStore[\"Service\"][\"get\"] = Effect.fnUntraced(function* (key) {\n const decodedKey = yield* decodeInput(\"get\", ScheduleKey, key);\n const text = (yield* Ref.get(state)).records.get(scheduleKeyString(decodedKey));\n\n return text === undefined ? null : yield* decodeRecord(\"get\", text);\n });\n\n const list: ScheduleStore[\"Service\"][\"list\"] = Effect.fnUntraced(function* (request) {\n const decodedRequest = yield* decodeInput(\"list\", SchedulePageRequest, request);\n const records: Array<ScheduleRecord> = [];\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"list\", text);\n\n if (\n sameOwner(record, decodedRequest.owner) &&\n (decodedRequest.after === undefined ||\n compareScheduleNames(record.scheduleId, decodedRequest.after) > 0)\n ) {\n records.push(record);\n }\n }\n records.sort((left, right) => compareScheduleNames(left.scheduleId, right.scheduleId));\n const hasNext = records.length > decodedRequest.limit;\n const items = records.slice(0, decodedRequest.limit);\n\n return {\n items,\n next: hasNext ? (items.at(-1)?.scheduleId ?? null) : null,\n };\n });\n\n const change: ScheduleStore[\"Service\"][\"change\"] = Effect.fnUntraced(function* (\n key,\n command,\n ownerLimit = defaultSchedulingLimits.maxSchedulesPerOwner,\n ) {\n const decodedKey = yield* decodeInput(\"change\", ScheduleKey, key);\n const decodedCommand = yield* decodeInput(\"change\", ScheduleChange, command);\n\n yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:before`);\n\n const decision = yield* Effect.uninterruptible(\n Ref.modify(\n state,\n (\n current,\n ): readonly [\n Result.Result<\n ScheduleRecord,\n ScheduleConflict | ScheduleStorageError | ScheduleNotFound | ScheduleCapacityError\n >,\n MemoryScheduleState,\n ] => {\n const storageKey = scheduleKeyString(decodedKey);\n const text = current.records.get(storageKey);\n\n if (text === undefined) {\n return [Result.fail(ScheduleNotFound.make({ key: decodedKey })), current];\n }\n\n const decoded = Result.try({\n try: () => Schema.decodeSync(Schema.fromJsonString(ScheduleRecord))(text),\n catch: () => storageError(\"change\", \"corrupt\"),\n });\n\n if (Result.isFailure(decoded)) {\n return [Result.fail(decoded.failure), current];\n }\n const applied = applyScheduleChange(decoded.success, decodedCommand);\n\n if (Result.isFailure(applied)) {\n return [Result.fail(applied.failure), current];\n }\n if (applied.success === decoded.success) {\n return [Result.succeed(decoded.success), current];\n }\n if (!scheduleUsesCapacity(decoded.success) && scheduleUsesCapacity(applied.success)) {\n let count = 0;\n\n for (const text of current.records.values()) {\n const candidate = Schema.decodeResult(Schema.fromJsonString(ScheduleRecord))(text);\n\n if (Result.isFailure(candidate))\n return [Result.fail(storageError(\"change\", \"corrupt\")), current];\n if (\n sameOwner(candidate.success, decodedKey.owner) &&\n scheduleUsesCapacity(candidate.success)\n )\n count += 1;\n }\n if (count >= ownerLimit)\n return [Result.fail(ScheduleCapacityError.make({ limit: ownerLimit })), current];\n }\n\n const encoded = Result.try({\n try: () => Schema.encodeSync(Schema.fromJsonString(ScheduleRecord))(applied.success),\n catch: () => storageError(\"change\", \"corrupt\"),\n });\n\n if (Result.isFailure(encoded)) {\n return [Result.fail(encoded.failure), current];\n }\n const records = new Map(current.records);\n\n records.set(storageKey, encoded.success);\n const next = { records };\n\n return [Result.succeed(applied.success), next];\n },\n ),\n );\n\n const changed = yield* Effect.fromResult(decision);\n\n yield* failpoint.hit(`schedule:${decodedCommand._tag.toLowerCase()}:after`);\n\n return yield* decodeRecord(\"change\", yield* encodeRecord(\"change\", changed));\n });\n\n const due: ScheduleStore[\"Service\"][\"due\"] = Effect.fnUntraced(\n function* (nowMillis, limit, owner, after) {\n const decodedOwner =\n owner === undefined ? undefined : yield* decodeInput(\"due\", ScheduleOwner, owner);\n\n const cursor =\n after === undefined ? undefined : yield* decodeInput(\"due\", ScheduleDueCursor, after);\n\n const records: Array<ScheduleDueCursor> = [];\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"due\", text);\n const deadline = scheduleDeadline(record);\n\n if (\n deadline !== null &&\n deadline <= nowMillis &&\n (decodedOwner === undefined || sameOwner(record, decodedOwner)) &&\n (cursor === undefined ||\n deadline > cursor.deadlineAtMillis ||\n (deadline === cursor.deadlineAtMillis && compareScheduleKeys(record, cursor) > 0))\n ) {\n records.push({ ...scheduleKeyOf(record), deadlineAtMillis: deadline });\n }\n }\n records.sort((left, right) => {\n const byDeadline = left.deadlineAtMillis - right.deadlineAtMillis;\n\n return byDeadline !== 0 ? byDeadline : compareScheduleKeys(left, right);\n });\n\n return records.slice(0, limit);\n },\n );\n\n const nextDeadline: ScheduleStore[\"Service\"][\"nextDeadline\"] = Effect.fnUntraced(\n function* (owner) {\n const decodedOwner =\n owner === undefined ? undefined : yield* decodeInput(\"nextDeadline\", ScheduleOwner, owner);\n\n let earliest: number | null = null;\n\n for (const text of (yield* Ref.get(state)).records.values()) {\n const record = yield* decodeRecord(\"nextDeadline\", text);\n\n if (decodedOwner !== undefined && !sameOwner(record, decodedOwner)) continue;\n const deadline = scheduleDeadline(record);\n\n if (deadline !== null && (earliest === null || deadline < earliest)) earliest = deadline;\n }\n\n return earliest;\n },\n );\n\n return ScheduleStore.of({ insert, get, list, change, due, nextDeadline });\n});\n\nexport const memoryScheduleStoreLayer = (): Layer.Layer<ScheduleStore> =>\n Layer.effect(ScheduleStore, makeScheduleStore);\n\nexport const MemoryScheduleStoreLive: Layer.Layer<ScheduleStore> = memoryScheduleStoreLayer();\n"],"mappings":"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"}
@@ -34,9 +34,7 @@ const error = (operation, reason) => MemoryIndexError.make({
34
34
  });
35
35
  const keyString = (key) => JSON.stringify([key.namespace.address, key.id]);
36
36
  const sourceIdentityBytes = (source) => Hex.encode(JSON.stringify(source)).length / 2;
37
- const decodeBoundary = Effect.fn("InMemorySemanticIndex.decodeBoundary")(function* (schema, value, operation) {
38
- return yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.flatMap((decoded) => Schema.encodeEffect(schema)(decoded).pipe(Effect.as(decoded))), Effect.mapError(() => error(operation, "invalid-input")));
39
- });
37
+ const decodeBoundary = (schema, value, operation) => Schema.decodeUnknownEffect(schema)(value).pipe(Effect.flatMap((decoded) => Schema.encodeEffect(schema)(decoded).pipe(Effect.as(decoded))), Effect.mapError(() => error(operation, "invalid-input")));
40
38
  const freezeSource = (source) => Object.freeze(MemoryIndexSource.make({
41
39
  key: Object.freeze(MemoryKey.make({
42
40
  ...source.key,
@@ -59,7 +57,7 @@ const squaredNorm = (vector) => {
59
57
  return sum > 0 ? sum : null;
60
58
  };
61
59
  const validVector = (vector, profile) => vector.length === profile.dimensions && squaredNorm(vector) !== null;
62
- const validateChunks = Effect.fn("InMemorySemanticIndex.validateChunks")(function* (chunks, profile, operation) {
60
+ const validateChunks = Effect.fnUntraced(function* (chunks, profile, operation) {
63
61
  let nextByte = 0;
64
62
  const passageIds = /* @__PURE__ */ new Set();
65
63
  for (let index = 0; index < chunks.length; index++) {
@@ -79,7 +77,7 @@ const cosine = (left, right) => {
79
77
  return bounded === 0 ? 0 : bounded;
80
78
  };
81
79
  const compareText = (left, right) => left < right ? -1 : left > right ? 1 : 0;
82
- const makeIndex = Effect.fn("InMemorySemanticIndex.make")(function* (rawProfile, rawCapacity) {
80
+ const makeIndex = Effect.fnUntraced(function* (rawProfile, rawCapacity) {
83
81
  const profile = Object.freeze(SemanticMemoryProfile.make({ ...yield* decodeBoundary(SemanticMemoryProfile, rawProfile, "configure semantic memory index") }));
84
82
  const capacity = yield* decodeBoundary(InMemorySemanticIndexCapacity, rawCapacity, "configure semantic memory index");
85
83
  if (capacity.maxChunks * profile.dimensions > MaxStoredVectorComponents) return yield* error("configure semantic memory index", "invalid-input");
@@ -94,10 +92,10 @@ const makeIndex = Effect.fn("InMemorySemanticIndex.make")(function* (rawProfile,
94
92
  entries: /* @__PURE__ */ new Map(),
95
93
  sourceBytes: 0
96
94
  }));
97
- const ensureOpen = Effect.fn("InMemorySemanticIndex.ensureOpen")(function* (operation) {
95
+ const ensureOpen = Effect.fnUntraced(function* (operation) {
98
96
  if ((yield* Ref.get(data)).closed) return yield* error(operation, "unavailable");
99
97
  });
100
- const replace = Effect.fn("InMemorySemanticIndex.replace")(function* (rawRequest) {
98
+ const replace = Effect.fnUntraced(function* (rawRequest) {
101
99
  const operation = "replace semantic memory source";
102
100
  yield* ensureOpen(operation);
103
101
  const request = yield* decodeBoundary(MemoryIndexReplacement.Wire, rawRequest, operation);
@@ -135,7 +133,7 @@ const makeIndex = Effect.fn("InMemorySemanticIndex.make")(function* (rawProfile,
135
133
  });
136
134
  if (failure !== void 0) return yield* failure;
137
135
  });
138
- const withdraw = Effect.fn("InMemorySemanticIndex.withdraw")(function* (rawSource) {
136
+ const withdraw = Effect.fnUntraced(function* (rawSource) {
139
137
  const operation = "withdraw semantic memory source";
140
138
  yield* ensureOpen(operation);
141
139
  const source = freezeSource(yield* decodeBoundary(MemoryIndexSource.Wire, rawSource, operation));
@@ -165,7 +163,7 @@ const makeIndex = Effect.fn("InMemorySemanticIndex.make")(function* (rawProfile,
165
163
  });
166
164
  if (failure !== void 0) return yield* failure;
167
165
  });
168
- const search = Effect.fn("InMemorySemanticIndex.search")(function* (rawQuery) {
166
+ const search = Effect.fnUntraced(function* (rawQuery) {
169
167
  const operation = "search semantic memory index";
170
168
  yield* ensureOpen(operation);
171
169
  const query = yield* decodeBoundary(MemoryIndexQuery.Wire, rawQuery, operation);
@@ -1 +1 @@
1
- {"version":3,"file":"MemorySemanticIndex.mjs","names":[],"sources":["../src/MemorySemanticIndex.ts"],"sourcesContent":["import { MemoryKey } from \"@yielded/agent/memory-store\";\nimport {\n MemoryIndexCandidate,\n MemoryIndexError,\n MemoryIndexQuery,\n MemoryIndexReplacement,\n MemoryIndexSearch,\n MemoryIndexSource,\n SemanticMemoryChunk,\n SemanticMemoryIndex,\n SemanticMemoryProfile,\n} from \"@yielded/agent/semantic-memory-index\";\nimport { Clock, Effect, Layer, Ref, Schema } from \"effect\";\nimport { Hex } from \"effect/encoding\";\n\nconst PositiveCapacity = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65_536 }));\nconst MaxStoredVectorComponents = 16_777_216;\n\n/**\n * Hard per-Layer bounds for disposable semantic index state. maxChunks times profile dimensions\n * must not exceed 16,777,216 vector components. maxSourceBytes bounds the aggregate UTF-8 JSON\n * of retained source identities and defaults to 16 MiB; it is not a general heap limit.\n */\nexport class InMemorySemanticIndexCapacity extends Schema.Class<InMemorySemanticIndexCapacity>(\n \"@effect-agent/storage-memory/InMemorySemanticIndexCapacity\",\n)({\n maxSources: PositiveCapacity,\n maxChunks: PositiveCapacity,\n maxSourceBytes: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 67_108_864 })),\n ),\n}) {}\n\ntype StoredEntry = {\n readonly source: MemoryIndexSource;\n readonly sourceBytes: number;\n} & (\n | {\n readonly _tag: \"Indexed\";\n readonly chunks: ReadonlyArray<SemanticMemoryChunk>;\n readonly indexedAt: number;\n }\n | { readonly _tag: \"Withdrawn\" }\n);\n\ninterface IndexData {\n readonly closed: boolean;\n readonly entries: ReadonlyMap<string, StoredEntry>;\n readonly sourceBytes: number;\n}\n\nconst sameProfile = Schema.toEquivalence(SemanticMemoryProfile);\nconst sameSource = Schema.toEquivalence(MemoryIndexSource.Wire);\n\nconst error = (operation: string, reason: MemoryIndexError[\"reason\"]): MemoryIndexError =>\n MemoryIndexError.make({ operation, reason });\n\nconst keyString = (key: MemoryKey): string => JSON.stringify([key.namespace.address, key.id]);\n\nconst sourceIdentityBytes = (source: MemoryIndexSource): number =>\n Hex.encode(JSON.stringify(source)).length / 2;\n\nconst decodeBoundary = Effect.fn(\"InMemorySemanticIndex.decodeBoundary\")(function* <A, I>(\n schema: Schema.Codec<A, I, never>,\n value: unknown,\n operation: string,\n): Effect.fn.Return<A, MemoryIndexError> {\n return yield* Schema.decodeUnknownEffect(schema)(value).pipe(\n Effect.flatMap((decoded) => Schema.encodeEffect(schema)(decoded).pipe(Effect.as(decoded))),\n Effect.mapError(() => error(operation, \"invalid-input\")),\n );\n});\n\nconst freezeSource = (source: MemoryIndexSource): MemoryIndexSource =>\n Object.freeze(\n MemoryIndexSource.make({\n key: Object.freeze(\n MemoryKey.make({\n ...source.key,\n namespace: Object.freeze({ address: source.key.namespace.address }),\n }),\n ),\n source: Object.freeze({ ...source.source }),\n sourceGeneration: source.sourceGeneration,\n }),\n );\n\nconst freezeChunk = (chunk: SemanticMemoryChunk): SemanticMemoryChunk =>\n Object.freeze(SemanticMemoryChunk.make({ ...chunk, vector: Object.freeze([...chunk.vector]) }));\n\nconst sourceIsFenced = (source: MemoryIndexSource, existing: StoredEntry): boolean =>\n source.sourceGeneration < existing.source.sourceGeneration ||\n (source.sourceGeneration === existing.source.sourceGeneration &&\n !sameSource(source, existing.source));\n\nconst squaredNorm = (vector: ReadonlyArray<number>): number | null => {\n let sum = 0;\n\n for (const value of vector) {\n sum += value * value;\n if (!Number.isFinite(sum)) return null;\n }\n\n return sum > 0 ? sum : null;\n};\n\nconst validVector = (vector: ReadonlyArray<number>, profile: SemanticMemoryProfile): boolean =>\n vector.length === profile.dimensions && squaredNorm(vector) !== null;\n\nconst validateChunks = Effect.fn(\"InMemorySemanticIndex.validateChunks\")(function* (\n chunks: ReadonlyArray<SemanticMemoryChunk>,\n profile: SemanticMemoryProfile,\n operation: string,\n): Effect.fn.Return<void, MemoryIndexError> {\n let nextByte = 0;\n const passageIds = new Set<string>();\n\n for (let index = 0; index < chunks.length; index++) {\n const chunk = chunks[index];\n const byteLength = Hex.encode(chunk.text).length / 2;\n\n if (\n chunk.ordinal !== index ||\n chunk.startByte !== nextByte ||\n chunk.endByte <= chunk.startByte ||\n chunk.endByte - chunk.startByte !== byteLength ||\n byteLength > profile.maxChunkBytes ||\n passageIds.has(chunk.passageId) ||\n !validVector(chunk.vector, profile)\n ) {\n return yield* error(operation, \"invalid-input\");\n }\n passageIds.add(chunk.passageId);\n nextByte = chunk.endByte;\n }\n});\n\nconst cosine = (left: ReadonlyArray<number>, right: ReadonlyArray<number>): number => {\n const leftNorm = Math.sqrt(squaredNorm(left) ?? 1);\n const rightNorm = Math.sqrt(squaredNorm(right) ?? 1);\n let score = 0;\n\n for (let index = 0; index < left.length; index++) {\n score += (left[index] / leftNorm) * (right[index] / rightNorm);\n }\n const bounded = Math.max(-1, Math.min(1, score));\n\n return bounded === 0 ? 0 : bounded;\n};\n\nconst compareText = (left: string, right: string): number =>\n left < right ? -1 : left > right ? 1 : 0;\n\nconst makeIndex = Effect.fn(\"InMemorySemanticIndex.make\")(function* (\n rawProfile: SemanticMemoryProfile,\n rawCapacity: InMemorySemanticIndexCapacity,\n) {\n const profile = Object.freeze(\n SemanticMemoryProfile.make({\n ...(yield* decodeBoundary(\n SemanticMemoryProfile,\n rawProfile,\n \"configure semantic memory index\",\n )),\n }),\n );\n\n const capacity = yield* decodeBoundary(\n InMemorySemanticIndexCapacity,\n rawCapacity,\n \"configure semantic memory index\",\n );\n\n if (capacity.maxChunks * profile.dimensions > MaxStoredVectorComponents) {\n return yield* error(\"configure semantic memory index\", \"invalid-input\");\n }\n const maxSourceBytes = capacity.maxSourceBytes ?? 16_777_216;\n const data = yield* Ref.make<IndexData>({ closed: false, entries: new Map(), sourceBytes: 0 });\n\n yield* Effect.addFinalizer(() =>\n Ref.set(data, { closed: true, entries: new Map(), sourceBytes: 0 }),\n );\n\n const ensureOpen = Effect.fn(\"InMemorySemanticIndex.ensureOpen\")(function* (operation: string) {\n if ((yield* Ref.get(data)).closed) return yield* error(operation, \"unavailable\");\n });\n\n const replace: SemanticMemoryIndex[\"Service\"][\"replace\"] = Effect.fn(\n \"InMemorySemanticIndex.replace\",\n )(function* (rawRequest) {\n const operation = \"replace semantic memory source\";\n\n yield* ensureOpen(operation);\n const request = yield* decodeBoundary(MemoryIndexReplacement.Wire, rawRequest, operation);\n const source = freezeSource(request.source);\n const sourceBytes = sourceIdentityBytes(source);\n const chunks = Object.freeze(request.chunks.map(freezeChunk));\n\n if (source.source.id !== source.key.id) return yield* error(operation, \"invalid-input\");\n if (!sameProfile(request.profile, profile)) return yield* error(operation, \"incompatible\");\n yield* validateChunks(chunks, profile, operation);\n const indexedAt = yield* Clock.currentTimeMillis;\n\n const failure = yield* Ref.modify(\n data,\n (current): readonly [MemoryIndexError | undefined, IndexData] => {\n if (current.closed) return [error(operation, \"unavailable\"), current];\n const id = keyString(source.key);\n const existing = current.entries.get(id);\n\n if (\n existing !== undefined &&\n (existing._tag === \"Withdrawn\" || sourceIsFenced(source, existing))\n ) {\n return [error(operation, \"fenced\"), current];\n }\n if (existing === undefined && current.entries.size >= capacity.maxSources) {\n return [error(operation, \"budget\"), current];\n }\n const nextSourceBytes = current.sourceBytes - (existing?.sourceBytes ?? 0) + sourceBytes;\n\n if (nextSourceBytes > maxSourceBytes) return [error(operation, \"budget\"), current];\n let count = chunks.length;\n\n for (const [entryId, entry] of current.entries) {\n if (entryId !== id && entry._tag === \"Indexed\") count += entry.chunks.length;\n }\n if (count > capacity.maxChunks) return [error(operation, \"budget\"), current];\n const entries = new Map(current.entries);\n\n entries.set(id, { _tag: \"Indexed\", source, sourceBytes, chunks, indexedAt });\n\n return [undefined, { ...current, entries, sourceBytes: nextSourceBytes }];\n },\n );\n\n if (failure !== undefined) return yield* failure;\n });\n\n const withdraw: SemanticMemoryIndex[\"Service\"][\"withdraw\"] = Effect.fn(\n \"InMemorySemanticIndex.withdraw\",\n )(function* (rawSource) {\n const operation = \"withdraw semantic memory source\";\n\n yield* ensureOpen(operation);\n\n const source = freezeSource(\n yield* decodeBoundary(MemoryIndexSource.Wire, rawSource, operation),\n );\n\n const sourceBytes = sourceIdentityBytes(source);\n\n if (source.source.id !== source.key.id) return yield* error(operation, \"invalid-input\");\n\n const failure = yield* Ref.modify(\n data,\n (current): readonly [MemoryIndexError | undefined, IndexData] => {\n if (current.closed) return [error(operation, \"unavailable\"), current];\n const id = keyString(source.key);\n const existing = current.entries.get(id);\n\n if (existing !== undefined) {\n if (existing._tag === \"Withdrawn\") {\n return [\n sameSource(source, existing.source) ? undefined : error(operation, \"fenced\"),\n current,\n ];\n }\n if (sourceIsFenced(source, existing)) return [error(operation, \"fenced\"), current];\n } else if (current.entries.size >= capacity.maxSources) {\n return [error(operation, \"budget\"), current];\n }\n const nextSourceBytes = current.sourceBytes - (existing?.sourceBytes ?? 0) + sourceBytes;\n\n if (nextSourceBytes > maxSourceBytes) return [error(operation, \"budget\"), current];\n const entries = new Map(current.entries);\n\n entries.set(id, { _tag: \"Withdrawn\", source, sourceBytes });\n\n return [undefined, { ...current, entries, sourceBytes: nextSourceBytes }];\n },\n );\n\n if (failure !== undefined) return yield* failure;\n });\n\n const search = Effect.fn(\"InMemorySemanticIndex.search\")(function* (rawQuery: MemoryIndexQuery) {\n const operation = \"search semantic memory index\";\n\n yield* ensureOpen(operation);\n const query = yield* decodeBoundary(MemoryIndexQuery.Wire, rawQuery, operation);\n const vector = Object.freeze([...query.vector]);\n\n if (!validVector(vector, profile)) return yield* error(operation, \"invalid-input\");\n const current = yield* Ref.get(data);\n\n if (current.closed) return yield* error(operation, \"unavailable\");\n let scannedChunks = 0;\n let inspectedSources = 0;\n const candidates: Array<MemoryIndexCandidate> = [];\n\n for (const entry of current.entries.values()) {\n inspectedSources += 1;\n if (inspectedSources % 128 === 0) yield* Effect.yieldNow;\n if (\n entry.source.key.namespace.address !== query.namespace.address ||\n entry._tag !== \"Indexed\"\n )\n continue;\n scannedChunks += entry.chunks.length;\n if (scannedChunks > query.maxScannedChunks) return yield* error(operation, \"budget\");\n }\n for (const entry of current.entries.values()) {\n if (\n entry.source.key.namespace.address !== query.namespace.address ||\n entry._tag !== \"Indexed\"\n )\n continue;\n yield* Effect.yieldNow;\n for (const chunk of entry.chunks) {\n const score = cosine(vector, chunk.vector);\n\n if (score < query.minScore) continue;\n candidates.push(\n MemoryIndexCandidate.make({\n ...entry.source,\n passageId: chunk.passageId,\n ordinal: chunk.ordinal,\n startByte: chunk.startByte,\n endByte: chunk.endByte,\n text: chunk.text,\n score,\n indexedAt: entry.indexedAt,\n }),\n );\n }\n }\n candidates.sort(\n (left, right) =>\n right.score - left.score ||\n compareText(left.key.id, right.key.id) ||\n compareText(left.source.revision, right.source.revision) ||\n left.ordinal - right.ordinal,\n );\n yield* ensureOpen(operation);\n\n return MemoryIndexSearch.make({ candidates: candidates.slice(0, query.limit), scannedChunks });\n });\n\n return SemanticMemoryIndex.fromAdapter({ profile, replace, withdraw, search });\n});\n\n/** Scoped disposable semantic index. No persistent build or recovery state is retained. */\nexport const inMemorySemanticIndexLayer = (\n profile: SemanticMemoryProfile,\n capacity: InMemorySemanticIndexCapacity,\n): Layer.Layer<SemanticMemoryIndex, MemoryIndexError> =>\n Layer.effect(SemanticMemoryIndex, makeIndex(profile, capacity));\n"],"mappings":"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"}
1
+ {"version":3,"file":"MemorySemanticIndex.mjs","names":[],"sources":["../src/MemorySemanticIndex.ts"],"sourcesContent":["import { MemoryKey } from \"@yielded/agent/memory-store\";\nimport {\n MemoryIndexCandidate,\n MemoryIndexError,\n MemoryIndexQuery,\n MemoryIndexReplacement,\n MemoryIndexSearch,\n MemoryIndexSource,\n SemanticMemoryChunk,\n SemanticMemoryIndex,\n SemanticMemoryProfile,\n} from \"@yielded/agent/semantic-memory-index\";\nimport { Clock, Effect, Layer, Ref, Schema } from \"effect\";\nimport { Hex } from \"effect/encoding\";\n\nconst PositiveCapacity = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 65_536 }));\nconst MaxStoredVectorComponents = 16_777_216;\n\n/**\n * Hard per-Layer bounds for disposable semantic index state. maxChunks times profile dimensions\n * must not exceed 16,777,216 vector components. maxSourceBytes bounds the aggregate UTF-8 JSON\n * of retained source identities and defaults to 16 MiB; it is not a general heap limit.\n */\nexport class InMemorySemanticIndexCapacity extends Schema.Class<InMemorySemanticIndexCapacity>(\n \"@effect-agent/storage-memory/InMemorySemanticIndexCapacity\",\n)({\n maxSources: PositiveCapacity,\n maxChunks: PositiveCapacity,\n maxSourceBytes: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 67_108_864 })),\n ),\n}) {}\n\ntype StoredEntry = {\n readonly source: MemoryIndexSource;\n readonly sourceBytes: number;\n} & (\n | {\n readonly _tag: \"Indexed\";\n readonly chunks: ReadonlyArray<SemanticMemoryChunk>;\n readonly indexedAt: number;\n }\n | { readonly _tag: \"Withdrawn\" }\n);\n\ninterface IndexData {\n readonly closed: boolean;\n readonly entries: ReadonlyMap<string, StoredEntry>;\n readonly sourceBytes: number;\n}\n\nconst sameProfile = Schema.toEquivalence(SemanticMemoryProfile);\nconst sameSource = Schema.toEquivalence(MemoryIndexSource.Wire);\n\nconst error = (operation: string, reason: MemoryIndexError[\"reason\"]): MemoryIndexError =>\n MemoryIndexError.make({ operation, reason });\n\nconst keyString = (key: MemoryKey): string => JSON.stringify([key.namespace.address, key.id]);\n\nconst sourceIdentityBytes = (source: MemoryIndexSource): number =>\n Hex.encode(JSON.stringify(source)).length / 2;\n\nconst decodeBoundary = <A, I>(\n schema: Schema.Codec<A, I, never>,\n value: unknown,\n operation: string,\n): Effect.Effect<A, MemoryIndexError> =>\n Schema.decodeUnknownEffect(schema)(value).pipe(\n Effect.flatMap((decoded) => Schema.encodeEffect(schema)(decoded).pipe(Effect.as(decoded))),\n Effect.mapError(() => error(operation, \"invalid-input\")),\n );\n\nconst freezeSource = (source: MemoryIndexSource): MemoryIndexSource =>\n Object.freeze(\n MemoryIndexSource.make({\n key: Object.freeze(\n MemoryKey.make({\n ...source.key,\n namespace: Object.freeze({ address: source.key.namespace.address }),\n }),\n ),\n source: Object.freeze({ ...source.source }),\n sourceGeneration: source.sourceGeneration,\n }),\n );\n\nconst freezeChunk = (chunk: SemanticMemoryChunk): SemanticMemoryChunk =>\n Object.freeze(SemanticMemoryChunk.make({ ...chunk, vector: Object.freeze([...chunk.vector]) }));\n\nconst sourceIsFenced = (source: MemoryIndexSource, existing: StoredEntry): boolean =>\n source.sourceGeneration < existing.source.sourceGeneration ||\n (source.sourceGeneration === existing.source.sourceGeneration &&\n !sameSource(source, existing.source));\n\nconst squaredNorm = (vector: ReadonlyArray<number>): number | null => {\n let sum = 0;\n\n for (const value of vector) {\n sum += value * value;\n if (!Number.isFinite(sum)) return null;\n }\n\n return sum > 0 ? sum : null;\n};\n\nconst validVector = (vector: ReadonlyArray<number>, profile: SemanticMemoryProfile): boolean =>\n vector.length === profile.dimensions && squaredNorm(vector) !== null;\n\nconst validateChunks = Effect.fnUntraced(function* (\n chunks: ReadonlyArray<SemanticMemoryChunk>,\n profile: SemanticMemoryProfile,\n operation: string,\n): Effect.fn.Return<void, MemoryIndexError> {\n let nextByte = 0;\n const passageIds = new Set<string>();\n\n for (let index = 0; index < chunks.length; index++) {\n const chunk = chunks[index];\n const byteLength = Hex.encode(chunk.text).length / 2;\n\n if (\n chunk.ordinal !== index ||\n chunk.startByte !== nextByte ||\n chunk.endByte <= chunk.startByte ||\n chunk.endByte - chunk.startByte !== byteLength ||\n byteLength > profile.maxChunkBytes ||\n passageIds.has(chunk.passageId) ||\n !validVector(chunk.vector, profile)\n ) {\n return yield* error(operation, \"invalid-input\");\n }\n passageIds.add(chunk.passageId);\n nextByte = chunk.endByte;\n }\n});\n\nconst cosine = (left: ReadonlyArray<number>, right: ReadonlyArray<number>): number => {\n const leftNorm = Math.sqrt(squaredNorm(left) ?? 1);\n const rightNorm = Math.sqrt(squaredNorm(right) ?? 1);\n let score = 0;\n\n for (let index = 0; index < left.length; index++) {\n score += (left[index] / leftNorm) * (right[index] / rightNorm);\n }\n const bounded = Math.max(-1, Math.min(1, score));\n\n return bounded === 0 ? 0 : bounded;\n};\n\nconst compareText = (left: string, right: string): number =>\n left < right ? -1 : left > right ? 1 : 0;\n\nconst makeIndex = Effect.fnUntraced(function* (\n rawProfile: SemanticMemoryProfile,\n rawCapacity: InMemorySemanticIndexCapacity,\n) {\n const profile = Object.freeze(\n SemanticMemoryProfile.make({\n ...(yield* decodeBoundary(\n SemanticMemoryProfile,\n rawProfile,\n \"configure semantic memory index\",\n )),\n }),\n );\n\n const capacity = yield* decodeBoundary(\n InMemorySemanticIndexCapacity,\n rawCapacity,\n \"configure semantic memory index\",\n );\n\n if (capacity.maxChunks * profile.dimensions > MaxStoredVectorComponents) {\n return yield* error(\"configure semantic memory index\", \"invalid-input\");\n }\n const maxSourceBytes = capacity.maxSourceBytes ?? 16_777_216;\n const data = yield* Ref.make<IndexData>({ closed: false, entries: new Map(), sourceBytes: 0 });\n\n yield* Effect.addFinalizer(() =>\n Ref.set(data, { closed: true, entries: new Map(), sourceBytes: 0 }),\n );\n\n const ensureOpen = Effect.fnUntraced(function* (operation: string) {\n if ((yield* Ref.get(data)).closed) return yield* error(operation, \"unavailable\");\n });\n\n const replace: SemanticMemoryIndex[\"Service\"][\"replace\"] = Effect.fnUntraced(\n function* (rawRequest) {\n const operation = \"replace semantic memory source\";\n\n yield* ensureOpen(operation);\n const request = yield* decodeBoundary(MemoryIndexReplacement.Wire, rawRequest, operation);\n const source = freezeSource(request.source);\n const sourceBytes = sourceIdentityBytes(source);\n const chunks = Object.freeze(request.chunks.map(freezeChunk));\n\n if (source.source.id !== source.key.id) return yield* error(operation, \"invalid-input\");\n if (!sameProfile(request.profile, profile)) return yield* error(operation, \"incompatible\");\n yield* validateChunks(chunks, profile, operation);\n const indexedAt = yield* Clock.currentTimeMillis;\n\n const failure = yield* Ref.modify(\n data,\n (current): readonly [MemoryIndexError | undefined, IndexData] => {\n if (current.closed) return [error(operation, \"unavailable\"), current];\n const id = keyString(source.key);\n const existing = current.entries.get(id);\n\n if (\n existing !== undefined &&\n (existing._tag === \"Withdrawn\" || sourceIsFenced(source, existing))\n ) {\n return [error(operation, \"fenced\"), current];\n }\n if (existing === undefined && current.entries.size >= capacity.maxSources) {\n return [error(operation, \"budget\"), current];\n }\n const nextSourceBytes = current.sourceBytes - (existing?.sourceBytes ?? 0) + sourceBytes;\n\n if (nextSourceBytes > maxSourceBytes) return [error(operation, \"budget\"), current];\n let count = chunks.length;\n\n for (const [entryId, entry] of current.entries) {\n if (entryId !== id && entry._tag === \"Indexed\") count += entry.chunks.length;\n }\n if (count > capacity.maxChunks) return [error(operation, \"budget\"), current];\n const entries = new Map(current.entries);\n\n entries.set(id, { _tag: \"Indexed\", source, sourceBytes, chunks, indexedAt });\n\n return [undefined, { ...current, entries, sourceBytes: nextSourceBytes }];\n },\n );\n\n if (failure !== undefined) return yield* failure;\n },\n );\n\n const withdraw: SemanticMemoryIndex[\"Service\"][\"withdraw\"] = Effect.fnUntraced(\n function* (rawSource) {\n const operation = \"withdraw semantic memory source\";\n\n yield* ensureOpen(operation);\n\n const source = freezeSource(\n yield* decodeBoundary(MemoryIndexSource.Wire, rawSource, operation),\n );\n\n const sourceBytes = sourceIdentityBytes(source);\n\n if (source.source.id !== source.key.id) return yield* error(operation, \"invalid-input\");\n\n const failure = yield* Ref.modify(\n data,\n (current): readonly [MemoryIndexError | undefined, IndexData] => {\n if (current.closed) return [error(operation, \"unavailable\"), current];\n const id = keyString(source.key);\n const existing = current.entries.get(id);\n\n if (existing !== undefined) {\n if (existing._tag === \"Withdrawn\") {\n return [\n sameSource(source, existing.source) ? undefined : error(operation, \"fenced\"),\n current,\n ];\n }\n if (sourceIsFenced(source, existing)) return [error(operation, \"fenced\"), current];\n } else if (current.entries.size >= capacity.maxSources) {\n return [error(operation, \"budget\"), current];\n }\n const nextSourceBytes = current.sourceBytes - (existing?.sourceBytes ?? 0) + sourceBytes;\n\n if (nextSourceBytes > maxSourceBytes) return [error(operation, \"budget\"), current];\n const entries = new Map(current.entries);\n\n entries.set(id, { _tag: \"Withdrawn\", source, sourceBytes });\n\n return [undefined, { ...current, entries, sourceBytes: nextSourceBytes }];\n },\n );\n\n if (failure !== undefined) return yield* failure;\n },\n );\n\n const search = Effect.fnUntraced(function* (rawQuery: MemoryIndexQuery) {\n const operation = \"search semantic memory index\";\n\n yield* ensureOpen(operation);\n const query = yield* decodeBoundary(MemoryIndexQuery.Wire, rawQuery, operation);\n const vector = Object.freeze([...query.vector]);\n\n if (!validVector(vector, profile)) return yield* error(operation, \"invalid-input\");\n const current = yield* Ref.get(data);\n\n if (current.closed) return yield* error(operation, \"unavailable\");\n let scannedChunks = 0;\n let inspectedSources = 0;\n const candidates: Array<MemoryIndexCandidate> = [];\n\n for (const entry of current.entries.values()) {\n inspectedSources += 1;\n if (inspectedSources % 128 === 0) yield* Effect.yieldNow;\n if (\n entry.source.key.namespace.address !== query.namespace.address ||\n entry._tag !== \"Indexed\"\n )\n continue;\n scannedChunks += entry.chunks.length;\n if (scannedChunks > query.maxScannedChunks) return yield* error(operation, \"budget\");\n }\n for (const entry of current.entries.values()) {\n if (\n entry.source.key.namespace.address !== query.namespace.address ||\n entry._tag !== \"Indexed\"\n )\n continue;\n yield* Effect.yieldNow;\n for (const chunk of entry.chunks) {\n const score = cosine(vector, chunk.vector);\n\n if (score < query.minScore) continue;\n candidates.push(\n MemoryIndexCandidate.make({\n ...entry.source,\n passageId: chunk.passageId,\n ordinal: chunk.ordinal,\n startByte: chunk.startByte,\n endByte: chunk.endByte,\n text: chunk.text,\n score,\n indexedAt: entry.indexedAt,\n }),\n );\n }\n }\n candidates.sort(\n (left, right) =>\n right.score - left.score ||\n compareText(left.key.id, right.key.id) ||\n compareText(left.source.revision, right.source.revision) ||\n left.ordinal - right.ordinal,\n );\n yield* ensureOpen(operation);\n\n return MemoryIndexSearch.make({ candidates: candidates.slice(0, query.limit), scannedChunks });\n });\n\n return SemanticMemoryIndex.fromAdapter({ profile, replace, withdraw, search });\n});\n\n/** Scoped disposable semantic index. No persistent build or recovery state is retained. */\nexport const inMemorySemanticIndexLayer = (\n profile: SemanticMemoryProfile,\n capacity: InMemorySemanticIndexCapacity,\n): Layer.Layer<SemanticMemoryIndex, MemoryIndexError> =>\n Layer.effect(SemanticMemoryIndex, makeIndex(profile, capacity));\n"],"mappings":";;;;;;;;;;AAeA,MAAM,mBAAmB,OAAO,IAAI,MAAM,OAAO,UAAU;CAAE,SAAS;CAAG,SAAS;AAAO,CAAC,CAAC;AAC3F,MAAM,4BAA4B;;;;;;AAOlC,IAAa,gCAAb,cAAmD,OAAO,MACxD,4DACF,CAAC,CAAC;CACA,YAAY;CACZ,WAAW;CACX,gBAAgB,OAAO,YACrB,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS;CAAW,CAAC,CAAC,CACxE;AACF,CAAC,CAAC,CAAC,CAAC;AAoBJ,MAAM,cAAc,OAAO,cAAc,qBAAqB;AAC9D,MAAM,aAAa,OAAO,cAAc,kBAAkB,IAAI;AAE9D,MAAM,SAAS,WAAmB,WAChC,iBAAiB,KAAK;CAAE;CAAW;AAAO,CAAC;AAE7C,MAAM,aAAa,QAA2B,KAAK,UAAU,CAAC,IAAI,UAAU,SAAS,IAAI,EAAE,CAAC;AAE5F,MAAM,uBAAuB,WAC3B,IAAI,OAAO,KAAK,UAAU,MAAM,CAAC,CAAC,CAAC,SAAS;AAE9C,MAAM,kBACJ,QACA,OACA,cAEA,OAAO,oBAAoB,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KACxC,OAAO,SAAS,YAAY,OAAO,aAAa,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,CAAC,GACzF,OAAO,eAAe,MAAM,WAAW,eAAe,CAAC,CACzD;AAEF,MAAM,gBAAgB,WACpB,OAAO,OACL,kBAAkB,KAAK;CACrB,KAAK,OAAO,OACV,UAAU,KAAK;EACb,GAAG,OAAO;EACV,WAAW,OAAO,OAAO,EAAE,SAAS,OAAO,IAAI,UAAU,QAAQ,CAAC;CACpE,CAAC,CACH;CACA,QAAQ,OAAO,OAAO,EAAE,GAAG,OAAO,OAAO,CAAC;CAC1C,kBAAkB,OAAO;AAC3B,CAAC,CACH;AAEF,MAAM,eAAe,UACnB,OAAO,OAAO,oBAAoB,KAAK;CAAE,GAAG;CAAO,QAAQ,OAAO,OAAO,CAAC,GAAG,MAAM,MAAM,CAAC;AAAE,CAAC,CAAC;AAEhG,MAAM,kBAAkB,QAA2B,aACjD,OAAO,mBAAmB,SAAS,OAAO,oBACzC,OAAO,qBAAqB,SAAS,OAAO,oBAC3C,CAAC,WAAW,QAAQ,SAAS,MAAM;AAEvC,MAAM,eAAe,WAAiD;CACpE,IAAI,MAAM;CAEV,KAAK,MAAM,SAAS,QAAQ;EAC1B,OAAO,QAAQ;EACf,IAAI,CAAC,OAAO,SAAS,GAAG,GAAG,OAAO;CACpC;CAEA,OAAO,MAAM,IAAI,MAAM;AACzB;AAEA,MAAM,eAAe,QAA+B,YAClD,OAAO,WAAW,QAAQ,cAAc,YAAY,MAAM,MAAM;AAElE,MAAM,iBAAiB,OAAO,WAAW,WACvC,QACA,SACA,WAC0C;CAC1C,IAAI,WAAW;CACf,MAAM,6BAAa,IAAI,IAAY;CAEnC,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;EAClD,MAAM,QAAQ,OAAO;EACrB,MAAM,aAAa,IAAI,OAAO,MAAM,IAAI,CAAC,CAAC,SAAS;EAEnD,IACE,MAAM,YAAY,SAClB,MAAM,cAAc,YACpB,MAAM,WAAW,MAAM,aACvB,MAAM,UAAU,MAAM,cAAc,cACpC,aAAa,QAAQ,iBACrB,WAAW,IAAI,MAAM,SAAS,KAC9B,CAAC,YAAY,MAAM,QAAQ,OAAO,GAElC,OAAO,OAAO,MAAM,WAAW,eAAe;EAEhD,WAAW,IAAI,MAAM,SAAS;EAC9B,WAAW,MAAM;CACnB;AACF,CAAC;AAED,MAAM,UAAU,MAA6B,UAAyC;CACpF,MAAM,WAAW,KAAK,KAAK,YAAY,IAAI,KAAK,CAAC;CACjD,MAAM,YAAY,KAAK,KAAK,YAAY,KAAK,KAAK,CAAC;CACnD,IAAI,QAAQ;CAEZ,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SACvC,SAAU,KAAK,SAAS,YAAa,MAAM,SAAS;CAEtD,MAAM,UAAU,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,CAAC;CAE/C,OAAO,YAAY,IAAI,IAAI;AAC7B;AAEA,MAAM,eAAe,MAAc,UACjC,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAEzC,MAAM,YAAY,OAAO,WAAW,WAClC,YACA,aACA;CACA,MAAM,UAAU,OAAO,OACrB,sBAAsB,KAAK,EACzB,GAAI,OAAO,eACT,uBACA,YACA,iCACF,EACF,CAAC,CACH;CAEA,MAAM,WAAW,OAAO,eACtB,+BACA,aACA,iCACF;CAEA,IAAI,SAAS,YAAY,QAAQ,aAAa,2BAC5C,OAAO,OAAO,MAAM,mCAAmC,eAAe;CAExE,MAAM,iBAAiB,SAAS,kBAAkB;CAClD,MAAM,OAAO,OAAO,IAAI,KAAgB;EAAE,QAAQ;EAAO,yBAAS,IAAI,IAAI;EAAG,aAAa;CAAE,CAAC;CAE7F,OAAO,OAAO,mBACZ,IAAI,IAAI,MAAM;EAAE,QAAQ;EAAM,yBAAS,IAAI,IAAI;EAAG,aAAa;CAAE,CAAC,CACpE;CAEA,MAAM,aAAa,OAAO,WAAW,WAAW,WAAmB;EACjE,KAAK,OAAO,IAAI,IAAI,IAAI,EAAA,CAAG,QAAQ,OAAO,OAAO,MAAM,WAAW,aAAa;CACjF,CAAC;CAED,MAAM,UAAqD,OAAO,WAChE,WAAW,YAAY;EACrB,MAAM,YAAY;EAElB,OAAO,WAAW,SAAS;EAC3B,MAAM,UAAU,OAAO,eAAe,uBAAuB,MAAM,YAAY,SAAS;EACxF,MAAM,SAAS,aAAa,QAAQ,MAAM;EAC1C,MAAM,cAAc,oBAAoB,MAAM;EAC9C,MAAM,SAAS,OAAO,OAAO,QAAQ,OAAO,IAAI,WAAW,CAAC;EAE5D,IAAI,OAAO,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,OAAO,MAAM,WAAW,eAAe;EACtF,IAAI,CAAC,YAAY,QAAQ,SAAS,OAAO,GAAG,OAAO,OAAO,MAAM,WAAW,cAAc;EACzF,OAAO,eAAe,QAAQ,SAAS,SAAS;EAChD,MAAM,YAAY,OAAO,MAAM;EAE/B,MAAM,UAAU,OAAO,IAAI,OACzB,OACC,YAAgE;GAC/D,IAAI,QAAQ,QAAQ,OAAO,CAAC,MAAM,WAAW,aAAa,GAAG,OAAO;GACpE,MAAM,KAAK,UAAU,OAAO,GAAG;GAC/B,MAAM,WAAW,QAAQ,QAAQ,IAAI,EAAE;GAEvC,IACE,aAAa,KAAA,MACZ,SAAS,SAAS,eAAe,eAAe,QAAQ,QAAQ,IAEjE,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GAE7C,IAAI,aAAa,KAAA,KAAa,QAAQ,QAAQ,QAAQ,SAAS,YAC7D,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GAE7C,MAAM,kBAAkB,QAAQ,eAAe,UAAU,eAAe,KAAK;GAE7E,IAAI,kBAAkB,gBAAgB,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GACjF,IAAI,QAAQ,OAAO;GAEnB,KAAK,MAAM,CAAC,SAAS,UAAU,QAAQ,SACrC,IAAI,YAAY,MAAM,MAAM,SAAS,WAAW,SAAS,MAAM,OAAO;GAExE,IAAI,QAAQ,SAAS,WAAW,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GAC3E,MAAM,UAAU,IAAI,IAAI,QAAQ,OAAO;GAEvC,QAAQ,IAAI,IAAI;IAAE,MAAM;IAAW;IAAQ;IAAa;IAAQ;GAAU,CAAC;GAE3E,OAAO,CAAC,KAAA,GAAW;IAAE,GAAG;IAAS;IAAS,aAAa;GAAgB,CAAC;EAC1E,CACF;EAEA,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO;CAC3C,CACF;CAEA,MAAM,WAAuD,OAAO,WAClE,WAAW,WAAW;EACpB,MAAM,YAAY;EAElB,OAAO,WAAW,SAAS;EAE3B,MAAM,SAAS,aACb,OAAO,eAAe,kBAAkB,MAAM,WAAW,SAAS,CACpE;EAEA,MAAM,cAAc,oBAAoB,MAAM;EAE9C,IAAI,OAAO,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,OAAO,MAAM,WAAW,eAAe;EAEtF,MAAM,UAAU,OAAO,IAAI,OACzB,OACC,YAAgE;GAC/D,IAAI,QAAQ,QAAQ,OAAO,CAAC,MAAM,WAAW,aAAa,GAAG,OAAO;GACpE,MAAM,KAAK,UAAU,OAAO,GAAG;GAC/B,MAAM,WAAW,QAAQ,QAAQ,IAAI,EAAE;GAEvC,IAAI,aAAa,KAAA,GAAW;IAC1B,IAAI,SAAS,SAAS,aACpB,OAAO,CACL,WAAW,QAAQ,SAAS,MAAM,IAAI,KAAA,IAAY,MAAM,WAAW,QAAQ,GAC3E,OACF;IAEF,IAAI,eAAe,QAAQ,QAAQ,GAAG,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GACnF,OAAO,IAAI,QAAQ,QAAQ,QAAQ,SAAS,YAC1C,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GAE7C,MAAM,kBAAkB,QAAQ,eAAe,UAAU,eAAe,KAAK;GAE7E,IAAI,kBAAkB,gBAAgB,OAAO,CAAC,MAAM,WAAW,QAAQ,GAAG,OAAO;GACjF,MAAM,UAAU,IAAI,IAAI,QAAQ,OAAO;GAEvC,QAAQ,IAAI,IAAI;IAAE,MAAM;IAAa;IAAQ;GAAY,CAAC;GAE1D,OAAO,CAAC,KAAA,GAAW;IAAE,GAAG;IAAS;IAAS,aAAa;GAAgB,CAAC;EAC1E,CACF;EAEA,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO;CAC3C,CACF;CAEA,MAAM,SAAS,OAAO,WAAW,WAAW,UAA4B;EACtE,MAAM,YAAY;EAElB,OAAO,WAAW,SAAS;EAC3B,MAAM,QAAQ,OAAO,eAAe,iBAAiB,MAAM,UAAU,SAAS;EAC9E,MAAM,SAAS,OAAO,OAAO,CAAC,GAAG,MAAM,MAAM,CAAC;EAE9C,IAAI,CAAC,YAAY,QAAQ,OAAO,GAAG,OAAO,OAAO,MAAM,WAAW,eAAe;EACjF,MAAM,UAAU,OAAO,IAAI,IAAI,IAAI;EAEnC,IAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,WAAW,aAAa;EAChE,IAAI,gBAAgB;EACpB,IAAI,mBAAmB;EACvB,MAAM,aAA0C,CAAC;EAEjD,KAAK,MAAM,SAAS,QAAQ,QAAQ,OAAO,GAAG;GAC5C,oBAAoB;GACpB,IAAI,mBAAmB,QAAQ,GAAG,OAAO,OAAO;GAChD,IACE,MAAM,OAAO,IAAI,UAAU,YAAY,MAAM,UAAU,WACvD,MAAM,SAAS,WAEf;GACF,iBAAiB,MAAM,OAAO;GAC9B,IAAI,gBAAgB,MAAM,kBAAkB,OAAO,OAAO,MAAM,WAAW,QAAQ;EACrF;EACA,KAAK,MAAM,SAAS,QAAQ,QAAQ,OAAO,GAAG;GAC5C,IACE,MAAM,OAAO,IAAI,UAAU,YAAY,MAAM,UAAU,WACvD,MAAM,SAAS,WAEf;GACF,OAAO,OAAO;GACd,KAAK,MAAM,SAAS,MAAM,QAAQ;IAChC,MAAM,QAAQ,OAAO,QAAQ,MAAM,MAAM;IAEzC,IAAI,QAAQ,MAAM,UAAU;IAC5B,WAAW,KACT,qBAAqB,KAAK;KACxB,GAAG,MAAM;KACT,WAAW,MAAM;KACjB,SAAS,MAAM;KACf,WAAW,MAAM;KACjB,SAAS,MAAM;KACf,MAAM,MAAM;KACZ;KACA,WAAW,MAAM;IACnB,CAAC,CACH;GACF;EACF;EACA,WAAW,MACR,MAAM,UACL,MAAM,QAAQ,KAAK,SACnB,YAAY,KAAK,IAAI,IAAI,MAAM,IAAI,EAAE,KACrC,YAAY,KAAK,OAAO,UAAU,MAAM,OAAO,QAAQ,KACvD,KAAK,UAAU,MAAM,OACzB;EACA,OAAO,WAAW,SAAS;EAE3B,OAAO,kBAAkB,KAAK;GAAE,YAAY,WAAW,MAAM,GAAG,MAAM,KAAK;GAAG;EAAc,CAAC;CAC/F,CAAC;CAED,OAAO,oBAAoB,YAAY;EAAE;EAAS;EAAS;EAAU;CAAO,CAAC;AAC/E,CAAC;;AAGD,MAAa,8BACX,SACA,aAEA,MAAM,OAAO,qBAAqB,UAAU,SAAS,QAAQ,CAAC"}
@@ -1,4 +1,6 @@
1
- import { Effect, Layer, Option } from "effect";
1
+ import { t as MemoryThreadStoreKernel } from "./MemoryThreadStoreKernel-DYNDjlhO.mjs";
2
+ import { Crypto, Effect, Layer, Option } from "effect";
3
+ import { SettlementPublisher } from "@yielded/agent/settlement-publisher";
2
4
  import { SubmissionLedger } from "@yielded/agent/submission-ledger";
3
5
  declare namespace MemorySubmissionLedger_d_exports {
4
6
  export { MemorySubmissionLedgerLive, MemorySubmissionLedgerOptions, memorySubmissionLedgerLayer };
@@ -15,10 +17,11 @@ export interface MemorySubmissionLedgerOptions {
15
17
  }
16
18
  /**
17
19
  * In-memory reference SubmissionLedger Layer (durability `non-durable`). All state lives in one
18
- * `Ref` owned by the Layer's Scope; no daemon fibers are spawned and no wall clock is consulted.
20
+ * `Ref` owned by the Layer's Scope. Fresh identities use the supplied `Crypto` service;
21
+ * imported identities remain unchanged. No daemon fibers are spawned and no wall clock is consulted.
19
22
  */
20
- export declare const memorySubmissionLedgerLayer: (options?: MemorySubmissionLedgerOptions) => Layer.Layer<SubmissionLedger>;
21
- export declare const MemorySubmissionLedgerLive: Layer.Layer<SubmissionLedger>;
23
+ export declare const memorySubmissionLedgerLayer: (options?: MemorySubmissionLedgerOptions) => Layer.Layer<SubmissionLedger | SettlementPublisher, never, MemoryThreadStoreKernel | Crypto.Crypto>;
24
+ export declare const MemorySubmissionLedgerLive: Layer.Layer<SubmissionLedger | SettlementPublisher, never, MemoryThreadStoreKernel | Crypto.Crypto>;
22
25
  //#endregion
23
26
  export { MemorySubmissionLedger_d_exports as t };
24
27
  //# sourceMappingURL=MemorySubmissionLedger.d.mts.map