@atomicmemory/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/LICENSE +201 -0
- package/README.md +314 -0
- package/dist/app/bind-ephemeral.d.ts +18 -0
- package/dist/app/bind-ephemeral.js +22 -0
- package/dist/app/cors-headers.d.ts +12 -0
- package/dist/app/cors-headers.js +18 -0
- package/dist/app/create-app.d.ts +25 -0
- package/dist/app/create-app.js +156 -0
- package/dist/app/runtime-config-route-snapshot.d.ts +27 -0
- package/dist/app/runtime-config-route-snapshot.js +27 -0
- package/dist/app/runtime-container.d.ts +281 -0
- package/dist/app/runtime-container.js +297 -0
- package/dist/app/startup-checks.d.ts +28 -0
- package/dist/app/startup-checks.js +45 -0
- package/dist/bin.d.ts +17 -0
- package/dist/bin.js +128 -0
- package/dist/config.d.ts +680 -0
- package/dist/config.js +808 -0
- package/dist/db/agent-trust-repository.d.ts +49 -0
- package/dist/db/agent-trust-repository.js +66 -0
- package/dist/db/belief-edges-repository.d.ts +68 -0
- package/dist/db/belief-edges-repository.js +124 -0
- package/dist/db/claim-repository.d.ts +6 -0
- package/dist/db/claim-repository.js +4 -0
- package/dist/db/contradictions-repository.d.ts +56 -0
- package/dist/db/contradictions-repository.js +88 -0
- package/dist/db/document-chunk-repository.d.ts +48 -0
- package/dist/db/document-chunk-repository.js +145 -0
- package/dist/db/document-chunk-types.d.ts +35 -0
- package/dist/db/document-chunk-types.js +9 -0
- package/dist/db/document-list-cursor.d.ts +45 -0
- package/dist/db/document-list-cursor.js +111 -0
- package/dist/db/document-list-repository.d.ts +103 -0
- package/dist/db/document-list-repository.js +204 -0
- package/dist/db/entity-cards-repository.d.ts +37 -0
- package/dist/db/entity-cards-repository.js +46 -0
- package/dist/db/entity-values-repository.d.ts +26 -0
- package/dist/db/entity-values-repository.js +57 -0
- package/dist/db/link-repository.d.ts +30 -0
- package/dist/db/link-repository.js +54 -0
- package/dist/db/memory-repository.d.ts +163 -0
- package/dist/db/memory-repository.js +232 -0
- package/dist/db/migrate.d.ts +6 -0
- package/dist/db/migrate.js +36 -0
- package/dist/db/mmr.d.ts +14 -0
- package/dist/db/mmr.js +57 -0
- package/dist/db/passport-feed-repository.d.ts +91 -0
- package/dist/db/passport-feed-repository.js +198 -0
- package/dist/db/pg-episode-store.d.ts +19 -0
- package/dist/db/pg-episode-store.js +17 -0
- package/dist/db/pg-link-store.d.ts +17 -0
- package/dist/db/pg-link-store.js +14 -0
- package/dist/db/pg-memory-store.d.ts +68 -0
- package/dist/db/pg-memory-store.js +53 -0
- package/dist/db/pg-recap-store.d.ts +13 -0
- package/dist/db/pg-recap-store.js +19 -0
- package/dist/db/pg-representation-store.d.ts +17 -0
- package/dist/db/pg-representation-store.js +17 -0
- package/dist/db/pg-search-store.d.ts +29 -0
- package/dist/db/pg-search-store.js +47 -0
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +21 -0
- package/dist/db/ppr.d.ts +56 -0
- package/dist/db/ppr.js +178 -0
- package/dist/db/query-helpers.d.ts +44 -0
- package/dist/db/query-helpers.js +60 -0
- package/dist/db/raw-doc-artifact-sync.d.ts +128 -0
- package/dist/db/raw-doc-artifact-sync.js +259 -0
- package/dist/db/raw-document-blob-repository.d.ts +148 -0
- package/dist/db/raw-document-blob-repository.js +300 -0
- package/dist/db/raw-document-repository.d.ts +104 -0
- package/dist/db/raw-document-repository.js +410 -0
- package/dist/db/raw-document-status-repository.d.ts +122 -0
- package/dist/db/raw-document-status-repository.js +183 -0
- package/dist/db/raw-document-types.d.ts +236 -0
- package/dist/db/raw-document-types.js +10 -0
- package/dist/db/raw-storage-reconciliation-repository.d.ts +110 -0
- package/dist/db/raw-storage-reconciliation-repository.js +200 -0
- package/dist/db/reflection-jobs-repository.d.ts +33 -0
- package/dist/db/reflection-jobs-repository.js +48 -0
- package/dist/db/reflections-repository.d.ts +41 -0
- package/dist/db/reflections-repository.js +83 -0
- package/dist/db/repository-claims.d.ts +141 -0
- package/dist/db/repository-claims.js +376 -0
- package/dist/db/repository-deferred-audn.d.ts +33 -0
- package/dist/db/repository-deferred-audn.js +69 -0
- package/dist/db/repository-document-delete.d.ts +53 -0
- package/dist/db/repository-document-delete.js +156 -0
- package/dist/db/repository-entities.d.ts +114 -0
- package/dist/db/repository-entities.js +317 -0
- package/dist/db/repository-entity-attributes.d.ts +41 -0
- package/dist/db/repository-entity-attributes.js +65 -0
- package/dist/db/repository-entity-graph.d.ts +32 -0
- package/dist/db/repository-entity-graph.js +87 -0
- package/dist/db/repository-first-mentions.d.ts +41 -0
- package/dist/db/repository-first-mentions.js +79 -0
- package/dist/db/repository-lessons.d.ts +51 -0
- package/dist/db/repository-lessons.js +90 -0
- package/dist/db/repository-links.d.ts +26 -0
- package/dist/db/repository-links.js +105 -0
- package/dist/db/repository-observation.d.ts +26 -0
- package/dist/db/repository-observation.js +51 -0
- package/dist/db/repository-read.d.ts +56 -0
- package/dist/db/repository-read.js +271 -0
- package/dist/db/repository-recaps.d.ts +59 -0
- package/dist/db/repository-recaps.js +158 -0
- package/dist/db/repository-representations.d.ts +48 -0
- package/dist/db/repository-representations.js +162 -0
- package/dist/db/repository-temporal-state.d.ts +35 -0
- package/dist/db/repository-temporal-state.js +46 -0
- package/dist/db/repository-tll.d.ts +88 -0
- package/dist/db/repository-tll.js +179 -0
- package/dist/db/repository-types.d.ts +313 -0
- package/dist/db/repository-types.js +142 -0
- package/dist/db/repository-user-profiles.d.ts +17 -0
- package/dist/db/repository-user-profiles.js +28 -0
- package/dist/db/repository-vector-search.d.ts +33 -0
- package/dist/db/repository-vector-search.js +373 -0
- package/dist/db/repository-wipe.d.ts +34 -0
- package/dist/db/repository-wipe.js +94 -0
- package/dist/db/repository-write.d.ts +61 -0
- package/dist/db/repository-write.js +279 -0
- package/dist/db/schema.sql +1355 -0
- package/dist/db/storage-artifact-delete-tx.d.ts +56 -0
- package/dist/db/storage-artifact-delete-tx.js +123 -0
- package/dist/db/storage-artifact-providers.d.ts +21 -0
- package/dist/db/storage-artifact-providers.js +21 -0
- package/dist/db/storage-artifact-recovery-repository.d.ts +66 -0
- package/dist/db/storage-artifact-recovery-repository.js +58 -0
- package/dist/db/storage-artifact-repository.d.ts +329 -0
- package/dist/db/storage-artifact-repository.js +497 -0
- package/dist/db/stores.d.ts +220 -0
- package/dist/db/stores.js +12 -0
- package/dist/db/summaries-repository.d.ts +74 -0
- package/dist/db/summaries-repository.js +125 -0
- package/dist/eval/beam-10m-loader.d.ts +98 -0
- package/dist/eval/beam-10m-loader.js +128 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +17 -0
- package/dist/middleware/require-bearer.d.ts +27 -0
- package/dist/middleware/require-bearer.js +60 -0
- package/dist/middleware/validate-response.d.ts +33 -0
- package/dist/middleware/validate-response.js +55 -0
- package/dist/middleware/validate.d.ts +43 -0
- package/dist/middleware/validate.js +85 -0
- package/dist/routes/agents.d.ts +13 -0
- package/dist/routes/agents.js +89 -0
- package/dist/routes/document-response-formatters.d.ts +98 -0
- package/dist/routes/document-response-formatters.js +243 -0
- package/dist/routes/documents.d.ts +74 -0
- package/dist/routes/documents.js +425 -0
- package/dist/routes/memories.d.ts +29 -0
- package/dist/routes/memories.js +725 -0
- package/dist/routes/memory-response-formatters.d.ts +179 -0
- package/dist/routes/memory-response-formatters.js +210 -0
- package/dist/routes/public-raw-storage-metadata.d.ts +54 -0
- package/dist/routes/public-raw-storage-metadata.js +56 -0
- package/dist/routes/reflect.d.ts +14 -0
- package/dist/routes/reflect.js +19 -0
- package/dist/routes/response-schema-map.d.ts +14 -0
- package/dist/routes/response-schema-map.js +69 -0
- package/dist/routes/route-errors.d.ts +12 -0
- package/dist/routes/route-errors.js +30 -0
- package/dist/routes/storage-error-handlers.d.ts +34 -0
- package/dist/routes/storage-error-handlers.js +185 -0
- package/dist/routes/storage-response-formatters.d.ts +44 -0
- package/dist/routes/storage-response-formatters.js +155 -0
- package/dist/routes/storage.d.ts +38 -0
- package/dist/routes/storage.js +369 -0
- package/dist/routes/upstream-provider-errors.d.ts +19 -0
- package/dist/routes/upstream-provider-errors.js +95 -0
- package/dist/schemas/agents.d.ts +79 -0
- package/dist/schemas/agents.js +126 -0
- package/dist/schemas/common.d.ts +110 -0
- package/dist/schemas/common.js +190 -0
- package/dist/schemas/document-list-responses.d.ts +102 -0
- package/dist/schemas/document-list-responses.js +87 -0
- package/dist/schemas/document-list-schemas.d.ts +123 -0
- package/dist/schemas/document-list-schemas.js +174 -0
- package/dist/schemas/document-response-schemas.d.ts +610 -0
- package/dist/schemas/document-response-schemas.js +264 -0
- package/dist/schemas/document-status-envelope.d.ts +48 -0
- package/dist/schemas/document-status-envelope.js +54 -0
- package/dist/schemas/documents.d.ts +292 -0
- package/dist/schemas/documents.js +449 -0
- package/dist/schemas/errors.d.ts +75 -0
- package/dist/schemas/errors.js +105 -0
- package/dist/schemas/memories.d.ts +378 -0
- package/dist/schemas/memories.js +542 -0
- package/dist/schemas/openapi.d.ts +24 -0
- package/dist/schemas/openapi.js +1038 -0
- package/dist/schemas/response-scalars.d.ts +10 -0
- package/dist/schemas/response-scalars.js +10 -0
- package/dist/schemas/responses.d.ts +536 -0
- package/dist/schemas/responses.js +350 -0
- package/dist/schemas/search-response-parts.d.ts +97 -0
- package/dist/schemas/search-response-parts.js +103 -0
- package/dist/schemas/storage-schemas.d.ts +175 -0
- package/dist/schemas/storage-schemas.js +277 -0
- package/dist/schemas/zod-setup.d.ts +15 -0
- package/dist/schemas/zod-setup.js +17 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +57 -0
- package/dist/services/abstract-query-policy.d.ts +13 -0
- package/dist/services/abstract-query-policy.js +50 -0
- package/dist/services/affinity-clustering.d.ts +66 -0
- package/dist/services/affinity-clustering.js +125 -0
- package/dist/services/agentic-retrieval.d.ts +38 -0
- package/dist/services/agentic-retrieval.js +126 -0
- package/dist/services/answer-format.d.ts +56 -0
- package/dist/services/answer-format.js +118 -0
- package/dist/services/answer-rescue.d.ts +72 -0
- package/dist/services/answer-rescue.js +177 -0
- package/dist/services/answer-verifier.d.ts +24 -0
- package/dist/services/answer-verifier.js +73 -0
- package/dist/services/api-retry.d.ts +6 -0
- package/dist/services/api-retry.js +41 -0
- package/dist/services/assistant-turn-filter.d.ts +20 -0
- package/dist/services/assistant-turn-filter.js +69 -0
- package/dist/services/atomicmem-uri.d.ts +33 -0
- package/dist/services/atomicmem-uri.js +86 -0
- package/dist/services/audit-events.d.ts +54 -0
- package/dist/services/audit-events.js +56 -0
- package/dist/services/chunked-extraction.d.ts +21 -0
- package/dist/services/chunked-extraction.js +108 -0
- package/dist/services/claim-slotting.d.ts +27 -0
- package/dist/services/claim-slotting.js +38 -0
- package/dist/services/claude-code-llm.d.ts +19 -0
- package/dist/services/claude-code-llm.js +96 -0
- package/dist/services/composite-dedup.d.ts +50 -0
- package/dist/services/composite-dedup.js +153 -0
- package/dist/services/composite-grouping.d.ts +41 -0
- package/dist/services/composite-grouping.js +111 -0
- package/dist/services/composite-staleness.d.ts +20 -0
- package/dist/services/composite-staleness.js +50 -0
- package/dist/services/conciseness-preference.d.ts +14 -0
- package/dist/services/conciseness-preference.js +42 -0
- package/dist/services/conflict-policy.d.ts +20 -0
- package/dist/services/conflict-policy.js +335 -0
- package/dist/services/consensus-extraction.d.ts +39 -0
- package/dist/services/consensus-extraction.js +147 -0
- package/dist/services/consensus-validation.d.ts +52 -0
- package/dist/services/consensus-validation.js +206 -0
- package/dist/services/consolidation-service.d.ts +60 -0
- package/dist/services/consolidation-service.js +171 -0
- package/dist/services/content-detection.d.ts +18 -0
- package/dist/services/content-detection.js +25 -0
- package/dist/services/contradiction-surfacing.d.ts +62 -0
- package/dist/services/contradiction-surfacing.js +111 -0
- package/dist/services/cost-telemetry.d.ts +39 -0
- package/dist/services/cost-telemetry.js +58 -0
- package/dist/services/counter-evidence.d.ts +34 -0
- package/dist/services/counter-evidence.js +92 -0
- package/dist/services/current-state-ranking.d.ts +21 -0
- package/dist/services/current-state-ranking.js +152 -0
- package/dist/services/deferred-audn.d.ts +47 -0
- package/dist/services/deferred-audn.js +162 -0
- package/dist/services/document-chunker.d.ts +50 -0
- package/dist/services/document-chunker.js +153 -0
- package/dist/services/document-failure-markers.d.ts +91 -0
- package/dist/services/document-failure-markers.js +305 -0
- package/dist/services/document-indexer.d.ts +122 -0
- package/dist/services/document-indexer.js +405 -0
- package/dist/services/document-service.d.ts +245 -0
- package/dist/services/document-service.js +325 -0
- package/dist/services/document-upload-artifact-sync.d.ts +80 -0
- package/dist/services/document-upload-artifact-sync.js +162 -0
- package/dist/services/document-upload-beta2-recovery.d.ts +72 -0
- package/dist/services/document-upload-beta2-recovery.js +94 -0
- package/dist/services/document-upload.d.ts +44 -0
- package/dist/services/document-upload.js +353 -0
- package/dist/services/embedding.d.ts +57 -0
- package/dist/services/embedding.js +416 -0
- package/dist/services/entity-attribute-extractor.d.ts +34 -0
- package/dist/services/entity-attribute-extractor.js +117 -0
- package/dist/services/entity-card-synthesis.d.ts +54 -0
- package/dist/services/entity-card-synthesis.js +92 -0
- package/dist/services/entity-dedup.d.ts +9 -0
- package/dist/services/entity-dedup.js +14 -0
- package/dist/services/entity-graph.d.ts +17 -0
- package/dist/services/entity-graph.js +135 -0
- package/dist/services/entropy-gate.d.ts +52 -0
- package/dist/services/entropy-gate.js +56 -0
- package/dist/services/episode-fetcher.d.ts +47 -0
- package/dist/services/episode-fetcher.js +128 -0
- package/dist/services/event-anchor-facts.d.ts +8 -0
- package/dist/services/event-anchor-facts.js +205 -0
- package/dist/services/event-chain-detector.d.ts +52 -0
- package/dist/services/event-chain-detector.js +83 -0
- package/dist/services/extraction-cache.d.ts +9 -0
- package/dist/services/extraction-cache.js +54 -0
- package/dist/services/extraction-enrichment.d.ts +9 -0
- package/dist/services/extraction-enrichment.js +223 -0
- package/dist/services/extraction.d.ts +69 -0
- package/dist/services/extraction.js +596 -0
- package/dist/services/fact-normalization.d.ts +12 -0
- package/dist/services/fact-normalization.js +248 -0
- package/dist/services/filecoin-observability.d.ts +127 -0
- package/dist/services/filecoin-observability.js +200 -0
- package/dist/services/first-mention-service.d.ts +76 -0
- package/dist/services/first-mention-service.js +186 -0
- package/dist/services/hierarchical-retrieval.d.ts +49 -0
- package/dist/services/hierarchical-retrieval.js +50 -0
- package/dist/services/ingest-fact-pipeline.d.ts +32 -0
- package/dist/services/ingest-fact-pipeline.js +212 -0
- package/dist/services/ingest-post-write.d.ts +50 -0
- package/dist/services/ingest-post-write.js +117 -0
- package/dist/services/ingest-trace.d.ts +32 -0
- package/dist/services/ingest-trace.js +60 -0
- package/dist/services/input-sanitizer.d.ts +41 -0
- package/dist/services/input-sanitizer.js +135 -0
- package/dist/services/iterative-retrieval.d.ts +26 -0
- package/dist/services/iterative-retrieval.js +139 -0
- package/dist/services/keyword-expansion.d.ts +10 -0
- package/dist/services/keyword-expansion.js +26 -0
- package/dist/services/lesson-service.d.ts +68 -0
- package/dist/services/lesson-service.js +178 -0
- package/dist/services/literal-extractor.d.ts +16 -0
- package/dist/services/literal-extractor.js +74 -0
- package/dist/services/literal-list-protection.d.ts +17 -0
- package/dist/services/literal-list-protection.js +134 -0
- package/dist/services/literal-query-expansion.d.ts +20 -0
- package/dist/services/literal-query-expansion.js +181 -0
- package/dist/services/llm.d.ts +61 -0
- package/dist/services/llm.js +265 -0
- package/dist/services/memcell-projection.d.ts +17 -0
- package/dist/services/memcell-projection.js +41 -0
- package/dist/services/memory-audn.d.ts +43 -0
- package/dist/services/memory-audn.js +419 -0
- package/dist/services/memory-crud.d.ts +93 -0
- package/dist/services/memory-crud.js +255 -0
- package/dist/services/memory-ingest.d.ts +21 -0
- package/dist/services/memory-ingest.js +249 -0
- package/dist/services/memory-lifecycle.d.ts +75 -0
- package/dist/services/memory-lifecycle.js +108 -0
- package/dist/services/memory-lineage.d.ts +181 -0
- package/dist/services/memory-lineage.js +232 -0
- package/dist/services/memory-network.d.ts +40 -0
- package/dist/services/memory-network.js +75 -0
- package/dist/services/memory-search-types.d.ts +25 -0
- package/dist/services/memory-search-types.js +10 -0
- package/dist/services/memory-search.d.ts +48 -0
- package/dist/services/memory-search.js +505 -0
- package/dist/services/memory-service-types.d.ts +371 -0
- package/dist/services/memory-service-types.js +8 -0
- package/dist/services/memory-service.d.ts +152 -0
- package/dist/services/memory-service.js +225 -0
- package/dist/services/memory-storage.d.ts +33 -0
- package/dist/services/memory-storage.js +328 -0
- package/dist/services/msr-aggregator.d.ts +38 -0
- package/dist/services/msr-aggregator.js +97 -0
- package/dist/services/msr-detector.d.ts +35 -0
- package/dist/services/msr-detector.js +65 -0
- package/dist/services/namespace-retrieval.d.ts +60 -0
- package/dist/services/namespace-retrieval.js +180 -0
- package/dist/services/observation-date-extraction.d.ts +12 -0
- package/dist/services/observation-date-extraction.js +50 -0
- package/dist/services/observation-service.d.ts +27 -0
- package/dist/services/observation-service.js +84 -0
- package/dist/services/packaging-observability.d.ts +29 -0
- package/dist/services/packaging-observability.js +146 -0
- package/dist/services/query-expansion.d.ts +83 -0
- package/dist/services/query-expansion.js +242 -0
- package/dist/services/query-keyword-matches.d.ts +6 -0
- package/dist/services/query-keyword-matches.js +56 -0
- package/dist/services/query-term-visibility.d.ts +28 -0
- package/dist/services/query-term-visibility.js +100 -0
- package/dist/services/quick-extraction.d.ts +25 -0
- package/dist/services/quick-extraction.js +431 -0
- package/dist/services/quoted-entity-extraction.d.ts +10 -0
- package/dist/services/quoted-entity-extraction.js +161 -0
- package/dist/services/raw-storage-reconciler-backoff.d.ts +8 -0
- package/dist/services/raw-storage-reconciler-backoff.js +14 -0
- package/dist/services/raw-storage-reconciler-scheduler.d.ts +29 -0
- package/dist/services/raw-storage-reconciler-scheduler.js +43 -0
- package/dist/services/raw-storage-reconciler.d.ts +71 -0
- package/dist/services/raw-storage-reconciler.js +278 -0
- package/dist/services/recap-builder.d.ts +49 -0
- package/dist/services/recap-builder.js +157 -0
- package/dist/services/reflect-jobs.d.ts +23 -0
- package/dist/services/reflect-jobs.js +36 -0
- package/dist/services/reflect-prompts.d.ts +71 -0
- package/dist/services/reflect-prompts.js +99 -0
- package/dist/services/reflect-retrieval.d.ts +33 -0
- package/dist/services/reflect-retrieval.js +30 -0
- package/dist/services/reflect.d.ts +49 -0
- package/dist/services/reflect.js +84 -0
- package/dist/services/relative-temporal.d.ts +14 -0
- package/dist/services/relative-temporal.js +163 -0
- package/dist/services/relevance-policy.d.ts +37 -0
- package/dist/services/relevance-policy.js +109 -0
- package/dist/services/rerank.d.ts +32 -0
- package/dist/services/rerank.js +118 -0
- package/dist/services/reranker.d.ts +20 -0
- package/dist/services/reranker.js +99 -0
- package/dist/services/retrieval-channel-rules.d.ts +34 -0
- package/dist/services/retrieval-channel-rules.js +41 -0
- package/dist/services/retrieval-config-overlay.d.ts +36 -0
- package/dist/services/retrieval-config-overlay.js +44 -0
- package/dist/services/retrieval-format.d.ts +119 -0
- package/dist/services/retrieval-format.js +559 -0
- package/dist/services/retrieval-policy.d.ts +69 -0
- package/dist/services/retrieval-policy.js +275 -0
- package/dist/services/retrieval-profiles.d.ts +37 -0
- package/dist/services/retrieval-profiles.js +90 -0
- package/dist/services/retrieval-side-effects.d.ts +14 -0
- package/dist/services/retrieval-side-effects.js +26 -0
- package/dist/services/retrieval-trace.d.ts +108 -0
- package/dist/services/retrieval-trace.js +147 -0
- package/dist/services/rrf-fusion.d.ts +18 -0
- package/dist/services/rrf-fusion.js +34 -0
- package/dist/services/search-pipeline.d.ts +71 -0
- package/dist/services/search-pipeline.js +788 -0
- package/dist/services/session-date.d.ts +20 -0
- package/dist/services/session-date.js +61 -0
- package/dist/services/session-packaging.d.ts +53 -0
- package/dist/services/session-packaging.js +182 -0
- package/dist/services/session-summary-generator.d.ts +53 -0
- package/dist/services/session-summary-generator.js +134 -0
- package/dist/services/specialists/cr-specialist.d.ts +52 -0
- package/dist/services/specialists/cr-specialist.js +121 -0
- package/dist/services/specialists/dispatch.d.ts +53 -0
- package/dist/services/specialists/dispatch.js +102 -0
- package/dist/services/specialists/ie-ku-specialist.d.ts +37 -0
- package/dist/services/specialists/ie-ku-specialist.js +63 -0
- package/dist/services/specialists/msr-specialist.d.ts +61 -0
- package/dist/services/specialists/msr-specialist.js +162 -0
- package/dist/services/specialists/tr-specialist.d.ts +37 -0
- package/dist/services/specialists/tr-specialist.js +146 -0
- package/dist/services/storage-key-prefix.d.ts +42 -0
- package/dist/services/storage-key-prefix.js +45 -0
- package/dist/services/storage-put-recovery.d.ts +71 -0
- package/dist/services/storage-put-recovery.js +269 -0
- package/dist/services/storage-service-errors.d.ts +124 -0
- package/dist/services/storage-service-errors.js +189 -0
- package/dist/services/storage-service.d.ts +176 -0
- package/dist/services/storage-service.js +423 -0
- package/dist/services/subject-aware-ranking.d.ts +19 -0
- package/dist/services/subject-aware-ranking.js +161 -0
- package/dist/services/supplemental-extraction.d.ts +7 -0
- package/dist/services/supplemental-extraction.js +116 -0
- package/dist/services/tbc-execution.d.ts +49 -0
- package/dist/services/tbc-execution.js +284 -0
- package/dist/services/temporal-classifier.d.ts +56 -0
- package/dist/services/temporal-classifier.js +94 -0
- package/dist/services/temporal-endpoint-evidence.d.ts +12 -0
- package/dist/services/temporal-endpoint-evidence.js +313 -0
- package/dist/services/temporal-fingerprint.d.ts +6 -0
- package/dist/services/temporal-fingerprint.js +12 -0
- package/dist/services/temporal-format.d.ts +9 -0
- package/dist/services/temporal-format.js +21 -0
- package/dist/services/temporal-intent.d.ts +39 -0
- package/dist/services/temporal-intent.js +78 -0
- package/dist/services/temporal-query-constraints.d.ts +16 -0
- package/dist/services/temporal-query-constraints.js +107 -0
- package/dist/services/temporal-query-expansion.d.ts +14 -0
- package/dist/services/temporal-query-expansion.js +131 -0
- package/dist/services/temporal-rerank.d.ts +22 -0
- package/dist/services/temporal-rerank.js +47 -0
- package/dist/services/temporal-result-protection.d.ts +7 -0
- package/dist/services/temporal-result-protection.js +60 -0
- package/dist/services/temporal-state-write.d.ts +57 -0
- package/dist/services/temporal-state-write.js +45 -0
- package/dist/services/tiered-context.d.ts +87 -0
- package/dist/services/tiered-context.js +214 -0
- package/dist/services/tiered-loading.d.ts +88 -0
- package/dist/services/tiered-loading.js +263 -0
- package/dist/services/timeline-pack.d.ts +36 -0
- package/dist/services/timeline-pack.js +50 -0
- package/dist/services/timing.d.ts +13 -0
- package/dist/services/timing.js +72 -0
- package/dist/services/tll-augmentation.d.ts +20 -0
- package/dist/services/tll-augmentation.js +125 -0
- package/dist/services/tll-retrieval.d.ts +55 -0
- package/dist/services/tll-retrieval.js +101 -0
- package/dist/services/topic-abstraction.d.ts +36 -0
- package/dist/services/topic-abstraction.js +105 -0
- package/dist/services/trust-scoring.d.ts +43 -0
- package/dist/services/trust-scoring.js +89 -0
- package/dist/services/typed-belief-calculus.d.ts +126 -0
- package/dist/services/typed-belief-calculus.js +204 -0
- package/dist/services/upload-config.d.ts +34 -0
- package/dist/services/upload-config.js +23 -0
- package/dist/services/upload-decision.d.ts +65 -0
- package/dist/services/upload-decision.js +98 -0
- package/dist/services/upload-helpers.d.ts +107 -0
- package/dist/services/upload-helpers.js +148 -0
- package/dist/services/user-profile-builder.d.ts +22 -0
- package/dist/services/user-profile-builder.js +109 -0
- package/dist/services/voyage-embedding.d.ts +22 -0
- package/dist/services/voyage-embedding.js +77 -0
- package/dist/services/write-security.d.ts +31 -0
- package/dist/services/write-security.js +64 -0
- package/dist/storage/artifact-public-redaction.d.ts +34 -0
- package/dist/storage/artifact-public-redaction.js +83 -0
- package/dist/storage/cleanup.d.ts +103 -0
- package/dist/storage/cleanup.js +138 -0
- package/dist/storage/codec-factory.d.ts +17 -0
- package/dist/storage/codec-factory.js +33 -0
- package/dist/storage/codecs/aes-gcm-codec.d.ts +44 -0
- package/dist/storage/codecs/aes-gcm-codec.js +108 -0
- package/dist/storage/codecs/noop-codec.d.ts +16 -0
- package/dist/storage/codecs/noop-codec.js +23 -0
- package/dist/storage/factory.d.ts +44 -0
- package/dist/storage/factory.js +99 -0
- package/dist/storage/filecoin-cid-validation.d.ts +82 -0
- package/dist/storage/filecoin-cid-validation.js +122 -0
- package/dist/storage/filecoin-public-metadata.d.ts +73 -0
- package/dist/storage/filecoin-public-metadata.js +110 -0
- package/dist/storage/local-fs-store.d.ts +39 -0
- package/dist/storage/local-fs-store.js +145 -0
- package/dist/storage/pointer-uri-allowlist.d.ts +38 -0
- package/dist/storage/pointer-uri-allowlist.js +70 -0
- package/dist/storage/provider-metadata-projection.d.ts +27 -0
- package/dist/storage/provider-metadata-projection.js +68 -0
- package/dist/storage/providers/filecoin/backend.d.ts +42 -0
- package/dist/storage/providers/filecoin/backend.js +250 -0
- package/dist/storage/providers/filecoin/config.d.ts +70 -0
- package/dist/storage/providers/filecoin/config.js +275 -0
- package/dist/storage/providers/filecoin/errors.d.ts +45 -0
- package/dist/storage/providers/filecoin/errors.js +56 -0
- package/dist/storage/providers/filecoin/filecoin-pin-car.d.ts +78 -0
- package/dist/storage/providers/filecoin/filecoin-pin-car.js +155 -0
- package/dist/storage/providers/filecoin/filecoin-pin-client.d.ts +92 -0
- package/dist/storage/providers/filecoin/filecoin-pin-client.js +199 -0
- package/dist/storage/providers/filecoin/filecoin-pin-mapping.d.ts +58 -0
- package/dist/storage/providers/filecoin/filecoin-pin-mapping.js +103 -0
- package/dist/storage/providers/filecoin/filecoin-pin-timeout.d.ts +30 -0
- package/dist/storage/providers/filecoin/filecoin-pin-timeout.js +53 -0
- package/dist/storage/providers/filecoin/filecoin-pin-vendor.d.ts +111 -0
- package/dist/storage/providers/filecoin/filecoin-pin-vendor.js +87 -0
- package/dist/storage/providers/filecoin/hints.d.ts +71 -0
- package/dist/storage/providers/filecoin/hints.js +123 -0
- package/dist/storage/providers/filecoin/index.d.ts +51 -0
- package/dist/storage/providers/filecoin/index.js +103 -0
- package/dist/storage/providers/filecoin/ipfs-cid.d.ts +50 -0
- package/dist/storage/providers/filecoin/ipfs-cid.js +64 -0
- package/dist/storage/providers/filecoin/metadata.d.ts +72 -0
- package/dist/storage/providers/filecoin/metadata.js +137 -0
- package/dist/storage/providers/filecoin/piece-cid.d.ts +48 -0
- package/dist/storage/providers/filecoin/piece-cid.js +57 -0
- package/dist/storage/providers/filecoin/provider-client.d.ts +234 -0
- package/dist/storage/providers/filecoin/provider-client.js +27 -0
- package/dist/storage/providers/filecoin/readiness.d.ts +62 -0
- package/dist/storage/providers/filecoin/readiness.js +85 -0
- package/dist/storage/providers/filecoin/retriever.d.ts +82 -0
- package/dist/storage/providers/filecoin/retriever.js +63 -0
- package/dist/storage/providers/filecoin/skeleton-client.d.ts +36 -0
- package/dist/storage/providers/filecoin/skeleton-client.js +55 -0
- package/dist/storage/providers/filecoin/synapse-client.d.ts +169 -0
- package/dist/storage/providers/filecoin/synapse-client.js +343 -0
- package/dist/storage/providers/filecoin/synapse-construction.d.ts +26 -0
- package/dist/storage/providers/filecoin/synapse-construction.js +47 -0
- package/dist/storage/providers/filecoin/synapse-error-mapping.d.ts +23 -0
- package/dist/storage/providers/filecoin/synapse-error-mapping.js +49 -0
- package/dist/storage/providers/filecoin/synapse-readiness.d.ts +37 -0
- package/dist/storage/providers/filecoin/synapse-readiness.js +231 -0
- package/dist/storage/providers/filecoin/uri.d.ts +49 -0
- package/dist/storage/providers/filecoin/uri.js +84 -0
- package/dist/storage/providers/filecoin/verified-fetch-lifecycle.d.ts +77 -0
- package/dist/storage/providers/filecoin/verified-fetch-lifecycle.js +196 -0
- package/dist/storage/providers/filecoin/verified-fetch-retriever.d.ts +54 -0
- package/dist/storage/providers/filecoin/verified-fetch-retriever.js +81 -0
- package/dist/storage/providers/filecoin/verified-fetch-vendor.d.ts +71 -0
- package/dist/storage/providers/filecoin/verified-fetch-vendor.js +94 -0
- package/dist/storage/raw-content-codec.d.ts +89 -0
- package/dist/storage/raw-content-codec.js +47 -0
- package/dist/storage/raw-content-store-backend-adapter.d.ts +28 -0
- package/dist/storage/raw-content-store-backend-adapter.js +67 -0
- package/dist/storage/raw-content-store.d.ts +228 -0
- package/dist/storage/raw-content-store.js +27 -0
- package/dist/storage/s3-store.d.ts +42 -0
- package/dist/storage/s3-store.js +181 -0
- package/dist/storage/storage-backend-registry.d.ts +58 -0
- package/dist/storage/storage-backend-registry.js +56 -0
- package/dist/storage/storage-backend.d.ts +82 -0
- package/dist/storage/storage-backend.js +14 -0
- package/dist/storage/storage-capabilities.d.ts +56 -0
- package/dist/storage/storage-capabilities.js +170 -0
- package/dist/storage/store-registry.d.ts +67 -0
- package/dist/storage/store-registry.js +77 -0
- package/dist/vector-math.d.ts +15 -0
- package/dist/vector-math.js +31 -0
- package/dist/xml-escape.d.ts +5 -0
- package/dist/xml-escape.js +7 -0
- package/openapi.json +15395 -0
- package/openapi.yaml +10794 -0
- package/package.json +119 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic query expansion for temporal-order questions.
|
|
3
|
+
* Pulls exact keyword candidates and nearby session memories when the query
|
|
4
|
+
* asks about sequence, relative timing, or duration.
|
|
5
|
+
*/
|
|
6
|
+
import { buildTemporalFingerprint } from './temporal-fingerprint.js';
|
|
7
|
+
const TEMPORAL_MARKERS = [
|
|
8
|
+
'before',
|
|
9
|
+
'after',
|
|
10
|
+
'when',
|
|
11
|
+
'timeline',
|
|
12
|
+
'order',
|
|
13
|
+
'sequence',
|
|
14
|
+
'relative',
|
|
15
|
+
'how long',
|
|
16
|
+
'first',
|
|
17
|
+
'second',
|
|
18
|
+
];
|
|
19
|
+
const STOP_WORDS = new Set([
|
|
20
|
+
'what', 'when', 'where', 'which', 'who', 'whom', 'whose', 'why', 'how',
|
|
21
|
+
'did', 'does', 'do', 'was', 'were', 'is', 'are', 'the', 'a', 'an', 'and',
|
|
22
|
+
'or', 'to', 'of', 'in', 'for', 'on', 'with', 'between', 'these', 'those',
|
|
23
|
+
'this', 'that', 'their', 'they', 'them', 'therefore', 'developer', 'student',
|
|
24
|
+
'order', 'changes', 'made', 'project', 'relative', 'timeline', 'receive', 'from',
|
|
25
|
+
]);
|
|
26
|
+
const HIGH_SIGNAL_PATTERNS = [
|
|
27
|
+
/\bDr\.?\s+[A-Z][a-z]+\b/g,
|
|
28
|
+
/\b[A-Z]{2,}\s+\d{4}\b/g,
|
|
29
|
+
/\b(?:career advice|application timeline|application deadlines|first paper|second submission|finance tracker)\b/gi,
|
|
30
|
+
/\bdotctl\b/gi,
|
|
31
|
+
];
|
|
32
|
+
const MAX_TEMPORAL_ANCHORS = 4;
|
|
33
|
+
export function isTemporalOrderingQuery(query) {
|
|
34
|
+
const lower = query.toLowerCase();
|
|
35
|
+
return TEMPORAL_MARKERS.some((marker) => lower.includes(marker));
|
|
36
|
+
}
|
|
37
|
+
export function extractTemporalQueryKeywords(query) {
|
|
38
|
+
if (!isTemporalOrderingQuery(query)) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const phrases = collectPatternMatches(query);
|
|
42
|
+
const tokens = tokenizeQuery(query);
|
|
43
|
+
const keywords = [...phrases, ...tokens];
|
|
44
|
+
return [...new Set(keywords.map((keyword) => keyword.trim()).filter(Boolean))].slice(0, 10);
|
|
45
|
+
}
|
|
46
|
+
export async function expandTemporalQuery(repo, userId, query, queryEmbedding, excludeIds, limit, referenceTime) {
|
|
47
|
+
const keywords = extractTemporalQueryKeywords(query);
|
|
48
|
+
if (keywords.length === 0) {
|
|
49
|
+
return { memories: [], keywords, anchorIds: [] };
|
|
50
|
+
}
|
|
51
|
+
const keywordHits = await repo.findKeywordCandidates(userId, keywords, limit);
|
|
52
|
+
const keywordIds = keywordHits.map((memory) => memory.id);
|
|
53
|
+
const initialAnchorIds = selectAnchorIds(keywordHits, new Set(keywordIds.filter((id) => excludeIds.has(id))), limit);
|
|
54
|
+
const anchorIds = initialAnchorIds.length >= Math.min(MAX_TEMPORAL_ANCHORS, limit)
|
|
55
|
+
? initialAnchorIds
|
|
56
|
+
: [
|
|
57
|
+
...initialAnchorIds,
|
|
58
|
+
...selectAnchorIds(keywordHits, new Set(keywordIds.filter((id) => !excludeIds.has(id))), Math.min(MAX_TEMPORAL_ANCHORS, limit) - initialAnchorIds.length),
|
|
59
|
+
];
|
|
60
|
+
const expansionIds = keywordIds.filter((id) => !excludeIds.has(id));
|
|
61
|
+
if (anchorIds.length === 0) {
|
|
62
|
+
return { memories: [], keywords, anchorIds: [] };
|
|
63
|
+
}
|
|
64
|
+
const anchorMemories = await repo.fetchMemoriesByIds(userId, anchorIds, queryEmbedding, referenceTime);
|
|
65
|
+
const expansionSet = new Set(expansionIds);
|
|
66
|
+
const keywordMemories = anchorMemories.filter((memory) => expansionSet.has(memory.id));
|
|
67
|
+
const temporalNeighbors = await repo.findTemporalNeighbors(userId, anchorMemories.map((memory) => memory.created_at), queryEmbedding, 30, new Set([...excludeIds, ...anchorIds]), limit, referenceTime);
|
|
68
|
+
return {
|
|
69
|
+
memories: [...keywordMemories, ...temporalNeighbors],
|
|
70
|
+
keywords,
|
|
71
|
+
anchorIds,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function collectPatternMatches(query) {
|
|
75
|
+
const matches = [];
|
|
76
|
+
for (const pattern of HIGH_SIGNAL_PATTERNS) {
|
|
77
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
78
|
+
let match;
|
|
79
|
+
while ((match = regex.exec(query)) !== null) {
|
|
80
|
+
matches.push(match[0]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return matches;
|
|
84
|
+
}
|
|
85
|
+
function tokenizeQuery(query) {
|
|
86
|
+
const words = query.match(/[A-Za-z0-9.]+/g) ?? [];
|
|
87
|
+
const filtered = words.filter((word) => isUsefulKeyword(word));
|
|
88
|
+
const bigrams = buildBigrams(filtered);
|
|
89
|
+
return [...filtered, ...bigrams];
|
|
90
|
+
}
|
|
91
|
+
function selectAnchorIds(keywordHits, keywordMemoryIds, limit) {
|
|
92
|
+
const seenFingerprints = new Set();
|
|
93
|
+
const anchorIds = [];
|
|
94
|
+
for (const hit of keywordHits) {
|
|
95
|
+
if (!keywordMemoryIds.has(hit.id)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const fingerprint = buildTemporalFingerprint(hit.content);
|
|
99
|
+
if (seenFingerprints.has(fingerprint)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
seenFingerprints.add(fingerprint);
|
|
103
|
+
anchorIds.push(hit.id);
|
|
104
|
+
if (anchorIds.length >= Math.min(MAX_TEMPORAL_ANCHORS, limit)) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return anchorIds;
|
|
109
|
+
}
|
|
110
|
+
function isUsefulKeyword(word) {
|
|
111
|
+
const lower = word.toLowerCase();
|
|
112
|
+
if (STOP_WORDS.has(lower))
|
|
113
|
+
return false;
|
|
114
|
+
if (isCompactHighSignalToken(word))
|
|
115
|
+
return true;
|
|
116
|
+
if (lower.length < 4)
|
|
117
|
+
return false;
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
function buildBigrams(words) {
|
|
121
|
+
const bigrams = [];
|
|
122
|
+
for (let i = 0; i < words.length - 1; i++) {
|
|
123
|
+
if (bigrams.length >= 4)
|
|
124
|
+
break;
|
|
125
|
+
bigrams.push(`${words[i]} ${words[i + 1]}`);
|
|
126
|
+
}
|
|
127
|
+
return bigrams;
|
|
128
|
+
}
|
|
129
|
+
function isCompactHighSignalToken(word) {
|
|
130
|
+
return /^[A-Z]{3,}$/.test(word) || /[A-Z]/.test(word.slice(1));
|
|
131
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEAM v38: read-time temporal-state reranker.
|
|
3
|
+
*
|
|
4
|
+
* Adds a small additive boost to candidates with an active state
|
|
5
|
+
* (`event_end IS NULL`) and a small deboost to candidates whose state
|
|
6
|
+
* has been superseded (`event_end IS NOT NULL`). Pure reranking — the
|
|
7
|
+
* candidate set is unchanged, never filtered. This mirrors Mem0's
|
|
8
|
+
* "rerank, never filter" temporal-reasoning design principle.
|
|
9
|
+
*
|
|
10
|
+
* Only runs when:
|
|
11
|
+
* - `temporalStateEnabled` is true at the call site, and
|
|
12
|
+
* - the query intent is `CURRENT_STATE`.
|
|
13
|
+
*
|
|
14
|
+
* Memories without a `state_key` (most of the corpus, especially while
|
|
15
|
+
* the layer is being adopted) are untouched.
|
|
16
|
+
*/
|
|
17
|
+
import type { SearchResult } from '../db/repository-types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Apply the additive state rerank in place. Returns a new array, sorted
|
|
20
|
+
* by the post-boost score (descending), so callers can drop straight in.
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyTemporalStateRerank(results: SearchResult[]): SearchResult[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEAM v38: read-time temporal-state reranker.
|
|
3
|
+
*
|
|
4
|
+
* Adds a small additive boost to candidates with an active state
|
|
5
|
+
* (`event_end IS NULL`) and a small deboost to candidates whose state
|
|
6
|
+
* has been superseded (`event_end IS NOT NULL`). Pure reranking — the
|
|
7
|
+
* candidate set is unchanged, never filtered. This mirrors Mem0's
|
|
8
|
+
* "rerank, never filter" temporal-reasoning design principle.
|
|
9
|
+
*
|
|
10
|
+
* Only runs when:
|
|
11
|
+
* - `temporalStateEnabled` is true at the call site, and
|
|
12
|
+
* - the query intent is `CURRENT_STATE`.
|
|
13
|
+
*
|
|
14
|
+
* Memories without a `state_key` (most of the corpus, especially while
|
|
15
|
+
* the layer is being adopted) are untouched.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Boost added to active state memories. Small enough that strong semantic
|
|
19
|
+
* matches still win, large enough to flip ties between active and
|
|
20
|
+
* superseded versions of the same fact.
|
|
21
|
+
*/
|
|
22
|
+
const ACTIVE_STATE_BOOST = 0.1;
|
|
23
|
+
/** Symmetric deboost for superseded state memories. */
|
|
24
|
+
const SUPERSEDED_STATE_DEBOOST = 0.1;
|
|
25
|
+
/**
|
|
26
|
+
* Apply the additive state rerank in place. Returns a new array, sorted
|
|
27
|
+
* by the post-boost score (descending), so callers can drop straight in.
|
|
28
|
+
*/
|
|
29
|
+
export function applyTemporalStateRerank(results) {
|
|
30
|
+
if (results.length === 0)
|
|
31
|
+
return results;
|
|
32
|
+
const reranked = results.map((row) => {
|
|
33
|
+
const boost = computeStateBoost(row);
|
|
34
|
+
if (boost === 0)
|
|
35
|
+
return row;
|
|
36
|
+
return { ...row, score: row.score + boost };
|
|
37
|
+
});
|
|
38
|
+
return reranked.sort((a, b) => b.score - a.score);
|
|
39
|
+
}
|
|
40
|
+
function computeStateBoost(row) {
|
|
41
|
+
if (!row.state_key)
|
|
42
|
+
return 0;
|
|
43
|
+
if (row.event_end === null || row.event_end === undefined) {
|
|
44
|
+
return ACTIVE_STATE_BOOST;
|
|
45
|
+
}
|
|
46
|
+
return -SUPERSEDED_STATE_DEBOOST;
|
|
47
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protect exact temporal keyword hits from being dropped by late-stage
|
|
3
|
+
* reranking or MMR. Temporal comparison questions often need one or two
|
|
4
|
+
* specific event memories to survive alongside broader context.
|
|
5
|
+
*/
|
|
6
|
+
import type { SearchResult } from '../db/memory-repository.js';
|
|
7
|
+
export declare function preserveProtectedResults(selected: SearchResult[], candidates: SearchResult[], protectedFingerprints: string[], limit: number): SearchResult[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protect exact temporal keyword hits from being dropped by late-stage
|
|
3
|
+
* reranking or MMR. Temporal comparison questions often need one or two
|
|
4
|
+
* specific event memories to survive alongside broader context.
|
|
5
|
+
*/
|
|
6
|
+
import { buildTemporalFingerprint } from './temporal-fingerprint.js';
|
|
7
|
+
export function preserveProtectedResults(selected, candidates, protectedFingerprints, limit) {
|
|
8
|
+
if (protectedFingerprints.length === 0 || selected.length === 0) {
|
|
9
|
+
return selected.slice(0, limit);
|
|
10
|
+
}
|
|
11
|
+
const selectedFingerprints = new Set(selected.map((result) => buildTemporalFingerprint(result.content)));
|
|
12
|
+
const protectedSet = new Set(protectedFingerprints);
|
|
13
|
+
const protectedResults = candidates.filter((result) => protectedSet.has(buildTemporalFingerprint(result.content)));
|
|
14
|
+
if (protectedResults.length === 0) {
|
|
15
|
+
return selected.slice(0, limit);
|
|
16
|
+
}
|
|
17
|
+
const dedupedProtectedResults = dedupeByFingerprint(protectedResults);
|
|
18
|
+
const finalResults = [...selected];
|
|
19
|
+
for (const protectedResult of dedupedProtectedResults) {
|
|
20
|
+
const fingerprint = buildTemporalFingerprint(protectedResult.content);
|
|
21
|
+
if (selectedFingerprints.has(fingerprint)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const replacementIndex = findReplacementIndex(finalResults, protectedSet);
|
|
25
|
+
if (replacementIndex === -1) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
finalResults[replacementIndex] = protectedResult;
|
|
29
|
+
selectedFingerprints.add(fingerprint);
|
|
30
|
+
}
|
|
31
|
+
return finalResults
|
|
32
|
+
.sort((left, right) => right.score - left.score)
|
|
33
|
+
.slice(0, limit);
|
|
34
|
+
}
|
|
35
|
+
function dedupeByFingerprint(results) {
|
|
36
|
+
const byFingerprint = new Map();
|
|
37
|
+
for (const result of results) {
|
|
38
|
+
const fingerprint = buildTemporalFingerprint(result.content);
|
|
39
|
+
const existing = byFingerprint.get(fingerprint);
|
|
40
|
+
if (!existing || result.score > existing.score) {
|
|
41
|
+
byFingerprint.set(fingerprint, result);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return [...byFingerprint.values()];
|
|
45
|
+
}
|
|
46
|
+
function findReplacementIndex(results, protectedFingerprints) {
|
|
47
|
+
let replacementIndex = -1;
|
|
48
|
+
let lowestScore = Infinity;
|
|
49
|
+
for (let i = 0; i < results.length; i++) {
|
|
50
|
+
const result = results[i];
|
|
51
|
+
if (protectedFingerprints.has(buildTemporalFingerprint(result.content))) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (result.score < lowestScore) {
|
|
55
|
+
lowestScore = result.score;
|
|
56
|
+
replacementIndex = i;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return replacementIndex;
|
|
60
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEAM v38: write-time temporal-state pipeline (classifier + supersede).
|
|
3
|
+
*
|
|
4
|
+
* Two helpers split the path so `memory-storage.ts` can:
|
|
5
|
+
* 1. classify BEFORE storing (so state_key / event_start land on the
|
|
6
|
+
* new memory row directly), and
|
|
7
|
+
* 2. supersede AFTER storing (so the new row is excluded from the
|
|
8
|
+
* UPDATE via its own id).
|
|
9
|
+
*
|
|
10
|
+
* Failure modes:
|
|
11
|
+
* - LLM classifier throws: re-thrown. The ingest path decides whether
|
|
12
|
+
* to abort. We do NOT silently drop the signal.
|
|
13
|
+
* - LLM returns non_stateful: helper returns null; caller skips the
|
|
14
|
+
* supersede sweep and the row stores with NULL state_key.
|
|
15
|
+
* - Supersede UPDATE throws: re-thrown. Fail-closed.
|
|
16
|
+
*/
|
|
17
|
+
import type pg from 'pg';
|
|
18
|
+
import { type TemporalStateClassification } from './temporal-classifier.js';
|
|
19
|
+
/** Input bundle for the pre-store classifier call. */
|
|
20
|
+
export interface TemporalClassifyForWriteInput {
|
|
21
|
+
/** User scope (used to namespace the state_key slug). */
|
|
22
|
+
userId: string;
|
|
23
|
+
/** Extracted fact text. */
|
|
24
|
+
memoryText: string;
|
|
25
|
+
/** Logical observed_at — used as event_start when the LLM does not. */
|
|
26
|
+
observedAt: Date;
|
|
27
|
+
/** Anthropic model ID for the classifier. */
|
|
28
|
+
model: string;
|
|
29
|
+
}
|
|
30
|
+
/** Re-export so callers don't depend on the classifier module directly. */
|
|
31
|
+
export type { TemporalStateClassification };
|
|
32
|
+
/**
|
|
33
|
+
* Classify a single memory's temporal state. Returns null when the
|
|
34
|
+
* memory is non-stateful or the classifier rejects the model output.
|
|
35
|
+
* Throws on transport / API failures so the caller fails closed.
|
|
36
|
+
*/
|
|
37
|
+
export declare function classifyTemporalStateForWrite(input: TemporalClassifyForWriteInput): Promise<TemporalStateClassification | null>;
|
|
38
|
+
/** Input bundle for the post-store supersede call. */
|
|
39
|
+
export interface SupersedeAfterStoreInput {
|
|
40
|
+
/** Postgres pool — used for the UPDATE. */
|
|
41
|
+
pool: pg.Pool;
|
|
42
|
+
/** User scope. */
|
|
43
|
+
userId: string;
|
|
44
|
+
/** Stable state key chosen by the classifier. */
|
|
45
|
+
stateKey: string;
|
|
46
|
+
/** Newly stored memory's id (excluded from the UPDATE). */
|
|
47
|
+
newMemoryId: string;
|
|
48
|
+
/** New row's event_start, used as event_end for displaced rows. */
|
|
49
|
+
eventStart: Date;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* UPDATE every prior, non-deleted memory with the same (user_id, state_key)
|
|
53
|
+
* so it closes its `event_end` window at the new row's event_start.
|
|
54
|
+
* Returns the count of rows touched. Re-throws on driver errors so the
|
|
55
|
+
* ingest can fail closed.
|
|
56
|
+
*/
|
|
57
|
+
export declare function supersedeAfterStore(input: SupersedeAfterStoreInput): Promise<number>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BEAM v38: write-time temporal-state pipeline (classifier + supersede).
|
|
3
|
+
*
|
|
4
|
+
* Two helpers split the path so `memory-storage.ts` can:
|
|
5
|
+
* 1. classify BEFORE storing (so state_key / event_start land on the
|
|
6
|
+
* new memory row directly), and
|
|
7
|
+
* 2. supersede AFTER storing (so the new row is excluded from the
|
|
8
|
+
* UPDATE via its own id).
|
|
9
|
+
*
|
|
10
|
+
* Failure modes:
|
|
11
|
+
* - LLM classifier throws: re-thrown. The ingest path decides whether
|
|
12
|
+
* to abort. We do NOT silently drop the signal.
|
|
13
|
+
* - LLM returns non_stateful: helper returns null; caller skips the
|
|
14
|
+
* supersede sweep and the row stores with NULL state_key.
|
|
15
|
+
* - Supersede UPDATE throws: re-thrown. Fail-closed.
|
|
16
|
+
*/
|
|
17
|
+
import { classifyTemporalState } from './temporal-classifier.js';
|
|
18
|
+
import { supersedePriorStateMemories } from '../db/repository-temporal-state.js';
|
|
19
|
+
/**
|
|
20
|
+
* Classify a single memory's temporal state. Returns null when the
|
|
21
|
+
* memory is non-stateful or the classifier rejects the model output.
|
|
22
|
+
* Throws on transport / API failures so the caller fails closed.
|
|
23
|
+
*/
|
|
24
|
+
export async function classifyTemporalStateForWrite(input) {
|
|
25
|
+
return classifyTemporalState({
|
|
26
|
+
memoryText: input.memoryText,
|
|
27
|
+
observedAt: input.observedAt,
|
|
28
|
+
userId: input.userId,
|
|
29
|
+
model: input.model,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* UPDATE every prior, non-deleted memory with the same (user_id, state_key)
|
|
34
|
+
* so it closes its `event_end` window at the new row's event_start.
|
|
35
|
+
* Returns the count of rows touched. Re-throws on driver errors so the
|
|
36
|
+
* ingest can fail closed.
|
|
37
|
+
*/
|
|
38
|
+
export async function supersedeAfterStore(input) {
|
|
39
|
+
return supersedePriorStateMemories(input.pool, {
|
|
40
|
+
userId: input.userId,
|
|
41
|
+
stateKey: input.stateKey,
|
|
42
|
+
newMemoryId: input.newMemoryId,
|
|
43
|
+
eventEnd: input.eventStart,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiered Context Loading — L0/L1/L2 style multi-resolution memory representations.
|
|
3
|
+
*
|
|
4
|
+
* Extends the existing staged loading with a proper three-tier model:
|
|
5
|
+
* - L0 (~10 words): Headline/abstract — compact preview for browsing and listing.
|
|
6
|
+
* Stored in the `summary` column, generated at extraction time.
|
|
7
|
+
* - L1 (~1-3 sentences): Overview — mid-level summary preserving key details.
|
|
8
|
+
* Generated on demand or at ingest time. Good for planning/reasoning.
|
|
9
|
+
* - L2 (full content): Complete memory content. Used for detailed drill-in.
|
|
10
|
+
*
|
|
11
|
+
* Token budget model:
|
|
12
|
+
* Given a total injection budget, the tier selector assigns each memory
|
|
13
|
+
* a tier based on its relevance score. High-relevance memories get L2,
|
|
14
|
+
* mid-relevance get L1, low-relevance get L0. This maximizes information
|
|
15
|
+
* density within the budget.
|
|
16
|
+
*
|
|
17
|
+
* Inspired by OpenViking's three-tier model (82% token reduction on LoCoMo10).
|
|
18
|
+
* Phase 2 roadmap item: "Tiered context loading" (OpenViking review, 2026-03-16).
|
|
19
|
+
*/
|
|
20
|
+
/** Memory content at different resolution levels. */
|
|
21
|
+
export interface TieredContent {
|
|
22
|
+
l0: string;
|
|
23
|
+
l1: string | null;
|
|
24
|
+
l2: string;
|
|
25
|
+
}
|
|
26
|
+
/** Tier assignment for a single memory in a retrieval result set. */
|
|
27
|
+
export interface TierAssignment {
|
|
28
|
+
memoryId: string;
|
|
29
|
+
tier: ContextTier;
|
|
30
|
+
content: string;
|
|
31
|
+
estimatedTokens: number;
|
|
32
|
+
}
|
|
33
|
+
export type ContextTier = 'L0' | 'L1' | 'L2';
|
|
34
|
+
/** Score thresholds for tier assignment. */
|
|
35
|
+
export interface TierThresholds {
|
|
36
|
+
l2MinScore: number;
|
|
37
|
+
l1MinScore: number;
|
|
38
|
+
}
|
|
39
|
+
export declare const DEFAULT_TIER_THRESHOLDS: TierThresholds;
|
|
40
|
+
/** Rank-based tier counts (used with selectRanksForQuery). */
|
|
41
|
+
export interface TierRanks {
|
|
42
|
+
l2Count: number;
|
|
43
|
+
l1Count: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate an L1 overview from full content.
|
|
47
|
+
* Uses a simple extractive approach: takes the first 2-3 sentences.
|
|
48
|
+
* No LLM call required — deterministic and fast.
|
|
49
|
+
*/
|
|
50
|
+
export declare function generateL1Overview(content: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Build tiered content from a memory's existing fields.
|
|
53
|
+
* L0 = summary/headline, L1 = generated overview, L2 = full content.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildTieredContent(content: string, summary: string): TieredContent;
|
|
56
|
+
/**
|
|
57
|
+
* Assign context tiers to a set of scored memories within a token budget.
|
|
58
|
+
*
|
|
59
|
+
* Algorithm:
|
|
60
|
+
* 1. Sort memories by score (descending).
|
|
61
|
+
* 2. Greedily assign the highest affordable tier to each memory.
|
|
62
|
+
* 3. If budget runs out, remaining memories get L0.
|
|
63
|
+
*
|
|
64
|
+
* Returns assignments in the original order.
|
|
65
|
+
*/
|
|
66
|
+
export declare function assignTiers(memories: Array<{
|
|
67
|
+
id: string;
|
|
68
|
+
score: number;
|
|
69
|
+
content: string;
|
|
70
|
+
summary: string;
|
|
71
|
+
}>, tokenBudget: number, thresholds?: TierThresholds): TierAssignment[];
|
|
72
|
+
/**
|
|
73
|
+
* Format tiered memory assignments into XML injection text.
|
|
74
|
+
* Each memory includes its tier level so the consuming LLM knows
|
|
75
|
+
* which memories have full detail vs summaries.
|
|
76
|
+
*/
|
|
77
|
+
export declare function formatTieredInjection(assignments: TierAssignment[]): string;
|
|
78
|
+
/**
|
|
79
|
+
* Estimate token count using the ~4 chars per token heuristic.
|
|
80
|
+
* Good enough for budget allocation; not meant to be exact.
|
|
81
|
+
*/
|
|
82
|
+
export declare function estimateTokens(text: string): number;
|
|
83
|
+
/**
|
|
84
|
+
* Calculate token savings from tiered loading vs all-L2.
|
|
85
|
+
* Returns the percentage of tokens saved.
|
|
86
|
+
*/
|
|
87
|
+
export declare function calculateTokenSavings(assignments: TierAssignment[], fullContentLengths: number[]): number;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiered Context Loading — L0/L1/L2 style multi-resolution memory representations.
|
|
3
|
+
*
|
|
4
|
+
* Extends the existing staged loading with a proper three-tier model:
|
|
5
|
+
* - L0 (~10 words): Headline/abstract — compact preview for browsing and listing.
|
|
6
|
+
* Stored in the `summary` column, generated at extraction time.
|
|
7
|
+
* - L1 (~1-3 sentences): Overview — mid-level summary preserving key details.
|
|
8
|
+
* Generated on demand or at ingest time. Good for planning/reasoning.
|
|
9
|
+
* - L2 (full content): Complete memory content. Used for detailed drill-in.
|
|
10
|
+
*
|
|
11
|
+
* Token budget model:
|
|
12
|
+
* Given a total injection budget, the tier selector assigns each memory
|
|
13
|
+
* a tier based on its relevance score. High-relevance memories get L2,
|
|
14
|
+
* mid-relevance get L1, low-relevance get L0. This maximizes information
|
|
15
|
+
* density within the budget.
|
|
16
|
+
*
|
|
17
|
+
* Inspired by OpenViking's three-tier model (82% token reduction on LoCoMo10).
|
|
18
|
+
* Phase 2 roadmap item: "Tiered context loading" (OpenViking review, 2026-03-16).
|
|
19
|
+
*/
|
|
20
|
+
import { escapeXml } from '../xml-escape.js';
|
|
21
|
+
export const DEFAULT_TIER_THRESHOLDS = {
|
|
22
|
+
l2MinScore: 0.70,
|
|
23
|
+
l1MinScore: 0.40,
|
|
24
|
+
};
|
|
25
|
+
/** Approximate token budget per tier (used for budget allocation). */
|
|
26
|
+
const TIER_TOKEN_ESTIMATES = {
|
|
27
|
+
L0: 15,
|
|
28
|
+
L1: 80,
|
|
29
|
+
L2: 200,
|
|
30
|
+
};
|
|
31
|
+
const DEFAULT_TIER_RANKS = {
|
|
32
|
+
l2Count: 2,
|
|
33
|
+
l1Count: 2,
|
|
34
|
+
};
|
|
35
|
+
/** Promoted ranks for multi-fact queries: all L2, no truncation. */
|
|
36
|
+
const PROMOTED_TIER_RANKS = {
|
|
37
|
+
l2Count: 10,
|
|
38
|
+
l1Count: 0,
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Multi-fact query patterns that need full context across memories.
|
|
42
|
+
* These queries ask to connect, enumerate, or synthesize multiple facts.
|
|
43
|
+
*/
|
|
44
|
+
const MULTI_FACT_PATTERNS = [
|
|
45
|
+
/\bconnection\b/i,
|
|
46
|
+
/\brelationship\b/i,
|
|
47
|
+
/\brelate\b/i,
|
|
48
|
+
/\bboth\b/i,
|
|
49
|
+
/\ball\b/i,
|
|
50
|
+
/\bfull\b.*\b(stack|list|set|trajectory|history)\b/i,
|
|
51
|
+
/\btwo\b.*\b(projects?|papers?|tools?|colleagues?)\b/i,
|
|
52
|
+
/\bcompare\b/i,
|
|
53
|
+
/\btogether\b/i,
|
|
54
|
+
/\bin what order\b/i,
|
|
55
|
+
/\bhow many\b/i,
|
|
56
|
+
/\bwhat are the\b.*\band\b/i,
|
|
57
|
+
];
|
|
58
|
+
/**
|
|
59
|
+
* Detect whether a query needs full content from all memories.
|
|
60
|
+
* Returns promoted ranks for multi-fact queries, default ranks otherwise.
|
|
61
|
+
*/
|
|
62
|
+
function selectRanksForQuery(query) {
|
|
63
|
+
const needsPromotion = MULTI_FACT_PATTERNS.some((pattern) => pattern.test(query));
|
|
64
|
+
return needsPromotion ? PROMOTED_TIER_RANKS : DEFAULT_TIER_RANKS;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generate an L1 overview from full content.
|
|
68
|
+
* Uses a simple extractive approach: takes the first 2-3 sentences.
|
|
69
|
+
* No LLM call required — deterministic and fast.
|
|
70
|
+
*/
|
|
71
|
+
export function generateL1Overview(content) {
|
|
72
|
+
const sentences = splitSentences(content);
|
|
73
|
+
if (sentences.length <= 2)
|
|
74
|
+
return content;
|
|
75
|
+
const targetLength = 3;
|
|
76
|
+
const overview = sentences.slice(0, targetLength).join(' ');
|
|
77
|
+
if (overview.length > 300) {
|
|
78
|
+
return sentences.slice(0, 2).join(' ');
|
|
79
|
+
}
|
|
80
|
+
return overview;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build tiered content from a memory's existing fields.
|
|
84
|
+
* L0 = summary/headline, L1 = generated overview, L2 = full content.
|
|
85
|
+
*/
|
|
86
|
+
export function buildTieredContent(content, summary) {
|
|
87
|
+
const l0 = summary || truncateToHeadline(content);
|
|
88
|
+
const l1 = generateL1Overview(content);
|
|
89
|
+
const l1IsSameAsL2 = l1 === content;
|
|
90
|
+
return {
|
|
91
|
+
l0,
|
|
92
|
+
l1: l1IsSameAsL2 ? null : l1,
|
|
93
|
+
l2: content,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Assign context tiers to a set of scored memories within a token budget.
|
|
98
|
+
*
|
|
99
|
+
* Algorithm:
|
|
100
|
+
* 1. Sort memories by score (descending).
|
|
101
|
+
* 2. Greedily assign the highest affordable tier to each memory.
|
|
102
|
+
* 3. If budget runs out, remaining memories get L0.
|
|
103
|
+
*
|
|
104
|
+
* Returns assignments in the original order.
|
|
105
|
+
*/
|
|
106
|
+
export function assignTiers(memories, tokenBudget, thresholds = DEFAULT_TIER_THRESHOLDS) {
|
|
107
|
+
if (memories.length === 0)
|
|
108
|
+
return [];
|
|
109
|
+
const indexed = memories.map((m, i) => ({ ...m, originalIndex: i }));
|
|
110
|
+
indexed.sort((a, b) => b.score - a.score);
|
|
111
|
+
let remainingBudget = tokenBudget;
|
|
112
|
+
const assignments = [];
|
|
113
|
+
for (const memory of indexed) {
|
|
114
|
+
const tiered = buildTieredContent(memory.content, memory.summary);
|
|
115
|
+
const { tier, content, tokens } = selectTierForBudget(memory.score, tiered, remainingBudget, thresholds);
|
|
116
|
+
remainingBudget -= tokens;
|
|
117
|
+
assignments.push({
|
|
118
|
+
memoryId: memory.id,
|
|
119
|
+
tier,
|
|
120
|
+
content,
|
|
121
|
+
estimatedTokens: tokens,
|
|
122
|
+
originalIndex: memory.originalIndex,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
assignments.sort((a, b) => a.originalIndex - b.originalIndex);
|
|
126
|
+
return assignments.map(({ originalIndex: _, ...rest }) => rest);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Select the highest-quality tier that fits within the remaining budget.
|
|
130
|
+
*/
|
|
131
|
+
function selectTierForBudget(score, tiered, remainingBudget, thresholds) {
|
|
132
|
+
const l2Tokens = estimateTokens(tiered.l2);
|
|
133
|
+
if (score >= thresholds.l2MinScore && l2Tokens <= remainingBudget) {
|
|
134
|
+
return { tier: 'L2', content: tiered.l2, tokens: l2Tokens };
|
|
135
|
+
}
|
|
136
|
+
if (tiered.l1 !== null) {
|
|
137
|
+
const l1Tokens = estimateTokens(tiered.l1);
|
|
138
|
+
if (score >= thresholds.l1MinScore && l1Tokens <= remainingBudget) {
|
|
139
|
+
return { tier: 'L1', content: tiered.l1, tokens: l1Tokens };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const l0Tokens = estimateTokens(tiered.l0);
|
|
143
|
+
return { tier: 'L0', content: tiered.l0, tokens: l0Tokens };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Format tiered memory assignments into XML injection text.
|
|
147
|
+
* Each memory includes its tier level so the consuming LLM knows
|
|
148
|
+
* which memories have full detail vs summaries.
|
|
149
|
+
*/
|
|
150
|
+
export function formatTieredInjection(assignments) {
|
|
151
|
+
if (assignments.length === 0)
|
|
152
|
+
return '';
|
|
153
|
+
const tierCounts = countTiers(assignments);
|
|
154
|
+
const totalTokens = assignments.reduce((sum, a) => sum + a.estimatedTokens, 0);
|
|
155
|
+
const expandableIds = assignments
|
|
156
|
+
.filter((a) => a.tier !== 'L2')
|
|
157
|
+
.map((a) => a.memoryId);
|
|
158
|
+
const lines = assignments.map((a, i) => {
|
|
159
|
+
const tierAttr = `tier="${a.tier}"`;
|
|
160
|
+
return `<memory index="${i + 1}" memory_id="${a.memoryId}" ${tierAttr}>\n${escapeXml(a.content)}\n</memory>`;
|
|
161
|
+
});
|
|
162
|
+
const header = [
|
|
163
|
+
`<atomicmem_context count="${assignments.length}"`,
|
|
164
|
+
`mode="tiered"`,
|
|
165
|
+
`tokens="~${totalTokens}"`,
|
|
166
|
+
`tiers="L0:${tierCounts.L0},L1:${tierCounts.L1},L2:${tierCounts.L2}"`,
|
|
167
|
+
expandableIds.length > 0 ? `expand_ids="${expandableIds.join(',')}"` : '',
|
|
168
|
+
].filter(Boolean).join(' ');
|
|
169
|
+
const parts = [`${header}>`];
|
|
170
|
+
parts.push(lines.join('\n'));
|
|
171
|
+
if (expandableIds.length > 0) {
|
|
172
|
+
parts.push('<expand_hint>Request expansion by ID for full content of L0/L1 memories.</expand_hint>');
|
|
173
|
+
}
|
|
174
|
+
parts.push('</atomicmem_context>');
|
|
175
|
+
return parts.join('\n');
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Estimate token count using the ~4 chars per token heuristic.
|
|
179
|
+
* Good enough for budget allocation; not meant to be exact.
|
|
180
|
+
*/
|
|
181
|
+
export function estimateTokens(text) {
|
|
182
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Calculate token savings from tiered loading vs all-L2.
|
|
186
|
+
* Returns the percentage of tokens saved.
|
|
187
|
+
*/
|
|
188
|
+
export function calculateTokenSavings(assignments, fullContentLengths) {
|
|
189
|
+
if (assignments.length === 0 || fullContentLengths.length === 0)
|
|
190
|
+
return 0;
|
|
191
|
+
const fullTokens = fullContentLengths.reduce((sum, len) => sum + estimateTokens(Array(len).fill('x').join('')), 0);
|
|
192
|
+
const tieredTokens = assignments.reduce((sum, a) => sum + a.estimatedTokens, 0);
|
|
193
|
+
if (fullTokens === 0)
|
|
194
|
+
return 0;
|
|
195
|
+
return ((fullTokens - tieredTokens) / fullTokens) * 100;
|
|
196
|
+
}
|
|
197
|
+
function countTiers(assignments) {
|
|
198
|
+
const counts = { L0: 0, L1: 0, L2: 0 };
|
|
199
|
+
for (const a of assignments)
|
|
200
|
+
counts[a.tier]++;
|
|
201
|
+
return counts;
|
|
202
|
+
}
|
|
203
|
+
function splitSentences(text) {
|
|
204
|
+
return text
|
|
205
|
+
.split(/(?<=[.!?])\s+/)
|
|
206
|
+
.map((s) => s.trim())
|
|
207
|
+
.filter(Boolean);
|
|
208
|
+
}
|
|
209
|
+
function truncateToHeadline(content) {
|
|
210
|
+
const words = content.split(/\s+/);
|
|
211
|
+
if (words.length <= 10)
|
|
212
|
+
return content;
|
|
213
|
+
return words.slice(0, 10).join(' ') + '...';
|
|
214
|
+
}
|