memorix 1.2.4 → 1.2.5
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 +13 -0
- package/dist/cli/index.js +147 -61
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +92 -55
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.js +79 -35
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +13 -0
- package/dist/sdk.d.ts +4 -2
- package/dist/sdk.js +93 -55
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.js.map +1 -1
- package/docs/1.2.5-RETRIEVAL-PERFORMANCE.md +85 -0
- package/docs/PERFORMANCE.md +22 -1
- package/docs/dev-log/progress.txt +33 -8
- package/package.json +2 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/cli/commands/memory.ts +12 -3
- package/src/cli/commands/operator-shared.ts +74 -2
- package/src/cli/index.ts +2 -0
- package/src/config/resolved-config.ts +29 -4
- package/src/runtime/project-maintenance.ts +1 -14
- package/src/sdk.ts +4 -0
- package/src/server.ts +8 -18
- package/src/store/orama-store.ts +39 -18
- package/src/timeout.ts +23 -0
- package/src/types.ts +8 -0
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.2.5] - 2026-07-27
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Explicit retrieval profiles** -- Search now accepts `fast`, `balanced` (default), or `thorough` through the CLI, MCP, and SDK. Fast is fully local, balanced keeps optional LLM work out of everyday retrieval, and thorough explicitly opts into configured LLM query refinement.
|
|
9
|
+
- **Reproducible retrieval evidence** -- Added `npm run benchmark:retrieval` for a clearly-labelled hot in-process SDK lexical benchmark with p50/p95/p99 output. It does not present CLI startup, MCP transport, remote embedding, or LLM latency as the same metric.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- **Lighter read-only CLI path** -- Memory search, detail, timeline, recent, graph context, and help no longer create session bookkeeping or maintenance-target metadata. Identity and visibility checks remain unchanged.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- **Completed searches no longer retain timeout watchdogs** -- Embedding, rerank, MCP search, and maintenance timeout paths share a helper that clears the timer when work settles. This removes the avoidable CLI exit delay caused by an already-completed optional rerank.
|
|
16
|
+
- **OpenRouter lane isolation** -- An embedding-only `OPENROUTER_API_KEY` no longer silently enables the memory LLM lane. It remains valid for a memory LLM only when that lane explicitly selects an OpenRouter provider or base URL.
|
|
17
|
+
|
|
5
18
|
## [1.2.4] - 2026-07-26
|
|
6
19
|
|
|
7
20
|
### Added
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entity, Relation, KnowledgeGraph, ProjectInfo, DetectionResult, ObservationType, ObservationStatus, ProgressInfo, Observation, IndexEntry } from './types.js';
|
|
1
|
+
import { Entity, Relation, KnowledgeGraph, ProjectInfo, DetectionResult, ObservationType, ObservationStatus, RetrievalQuality, ProgressInfo, Observation, IndexEntry } from './types.js';
|
|
2
2
|
export { AgentTarget, DEFAULT_CONFIG, DetectionFailure, DetectionFailureReason, DocumentType, KnowledgeLayer, MCPConfigAdapter, MCPServerEntry, MemorixConfig, MemorixDocument, MemoryRef, MiniSkill, OBSERVATION_ICONS, ObservationAdmissionState, ObservationReader, ObservationRef, ObservationVisibility, RuleFormatAdapter, RuleSource, SearchOptions, Session, SkillConflict, SkillEntry, SnapshotObservation, SourceSnapshot, TOPIC_KEY_FAMILIES, TimelineContext, UnifiedRule, WorkflowEntry, WorkspaceSyncResult } from './types.js';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
|
|
@@ -559,6 +559,8 @@ interface ClientSearchOptions {
|
|
|
559
559
|
status?: ObservationStatus | 'all';
|
|
560
560
|
/** Maximum results. Default: 20 */
|
|
561
561
|
limit?: number;
|
|
562
|
+
/** Retrieval profile. Default: balanced. */
|
|
563
|
+
quality?: RetrievalQuality;
|
|
562
564
|
}
|
|
563
565
|
/** Result from resolving observations */
|
|
564
566
|
interface ResolveResult {
|
|
@@ -687,4 +689,4 @@ declare class MemoryClient {
|
|
|
687
689
|
*/
|
|
688
690
|
declare function createMemoryClient(options: MemoryClientOptions): Promise<MemoryClient>;
|
|
689
691
|
|
|
690
|
-
export { type ClientSearchOptions, type CreateMemorixServerOptions, DetectionResult, Entity, IndexEntry, KnowledgeGraph, MemoryClient, type MemoryClientOptions, Observation, ObservationStatus, ObservationType, ProgressInfo, ProjectInfo, Relation, type ResolveResult, type StoreInput, type StoreResult, createMemorixServer, createMemoryClient, detectProject, detectProjectWithDiagnostics };
|
|
692
|
+
export { type ClientSearchOptions, type CreateMemorixServerOptions, DetectionResult, Entity, IndexEntry, KnowledgeGraph, MemoryClient, type MemoryClientOptions, Observation, ObservationStatus, ObservationType, ProgressInfo, ProjectInfo, Relation, type ResolveResult, RetrievalQuality, type StoreInput, type StoreResult, createMemorixServer, createMemoryClient, detectProject, detectProjectWithDiagnostics };
|
package/dist/sdk.js
CHANGED
|
@@ -2807,6 +2807,25 @@ function getResolvedConfig(options = {}) {
|
|
|
2807
2807
|
const legacy = loadFileConfig();
|
|
2808
2808
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml2.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
2809
2809
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2810
|
+
const memoryLlmProvider = first(
|
|
2811
|
+
process.env.MEMORIX_LLM_PROVIDER,
|
|
2812
|
+
toml.memory?.llm?.provider,
|
|
2813
|
+
yaml2.llm?.provider,
|
|
2814
|
+
legacy.llm?.provider
|
|
2815
|
+
);
|
|
2816
|
+
const memoryLlmModel = first(
|
|
2817
|
+
process.env.MEMORIX_LLM_MODEL,
|
|
2818
|
+
toml.memory?.llm?.model,
|
|
2819
|
+
yaml2.llm?.model,
|
|
2820
|
+
legacy.llm?.model
|
|
2821
|
+
);
|
|
2822
|
+
const memoryLlmBaseUrl = first(
|
|
2823
|
+
process.env.MEMORIX_LLM_BASE_URL,
|
|
2824
|
+
toml.memory?.llm?.base_url,
|
|
2825
|
+
yaml2.llm?.baseUrl,
|
|
2826
|
+
legacy.llm?.baseUrl
|
|
2827
|
+
);
|
|
2828
|
+
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2810
2829
|
const resolved = {
|
|
2811
2830
|
agent: {
|
|
2812
2831
|
provider: first(
|
|
@@ -2844,9 +2863,9 @@ function getResolvedConfig(options = {}) {
|
|
|
2844
2863
|
autoCleanup: firstBool(toml.memory?.auto_cleanup, yaml2.behavior?.autoCleanup),
|
|
2845
2864
|
syncAdvisory: firstBool(toml.memory?.sync_advisory, yaml2.behavior?.syncAdvisory),
|
|
2846
2865
|
llm: {
|
|
2847
|
-
provider:
|
|
2848
|
-
model:
|
|
2849
|
-
baseUrl:
|
|
2866
|
+
provider: memoryLlmProvider,
|
|
2867
|
+
model: memoryLlmModel,
|
|
2868
|
+
baseUrl: memoryLlmBaseUrl,
|
|
2850
2869
|
apiKey: first(
|
|
2851
2870
|
process.env.MEMORIX_LLM_API_KEY,
|
|
2852
2871
|
process.env.MEMORIX_API_KEY,
|
|
@@ -2855,7 +2874,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2855
2874
|
legacy.llm?.apiKey,
|
|
2856
2875
|
process.env.OPENAI_API_KEY,
|
|
2857
2876
|
process.env.ANTHROPIC_API_KEY,
|
|
2858
|
-
|
|
2877
|
+
openRouterMemoryLlmApiKey
|
|
2859
2878
|
)
|
|
2860
2879
|
}
|
|
2861
2880
|
},
|
|
@@ -2992,6 +3011,9 @@ function isOpenRouterUrl(value) {
|
|
|
2992
3011
|
return /(^|\.)openrouter\.ai(?::|\/|$)/i.test(value);
|
|
2993
3012
|
}
|
|
2994
3013
|
}
|
|
3014
|
+
function isOpenRouterMemoryLane(provider2, baseUrl) {
|
|
3015
|
+
return provider2?.trim().toLowerCase() === "openrouter" || isOpenRouterUrl(baseUrl);
|
|
3016
|
+
}
|
|
2995
3017
|
function normalizeExternalContext(value) {
|
|
2996
3018
|
const normalized = value?.trim().toLowerCase();
|
|
2997
3019
|
if (normalized === "auto" || normalized === "off") return normalized;
|
|
@@ -5039,6 +5061,29 @@ Rules:
|
|
|
5039
5061
|
}
|
|
5040
5062
|
});
|
|
5041
5063
|
|
|
5064
|
+
// src/timeout.ts
|
|
5065
|
+
function withTimeout(promise, ms, label) {
|
|
5066
|
+
return new Promise((resolve2, reject) => {
|
|
5067
|
+
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
5068
|
+
promise.then(
|
|
5069
|
+
(value) => {
|
|
5070
|
+
clearTimeout(timer);
|
|
5071
|
+
resolve2(value);
|
|
5072
|
+
},
|
|
5073
|
+
(error) => {
|
|
5074
|
+
clearTimeout(timer);
|
|
5075
|
+
reject(error);
|
|
5076
|
+
}
|
|
5077
|
+
);
|
|
5078
|
+
});
|
|
5079
|
+
}
|
|
5080
|
+
var init_timeout = __esm({
|
|
5081
|
+
"src/timeout.ts"() {
|
|
5082
|
+
"use strict";
|
|
5083
|
+
init_esm_shims();
|
|
5084
|
+
}
|
|
5085
|
+
});
|
|
5086
|
+
|
|
5042
5087
|
// src/project/aliases.ts
|
|
5043
5088
|
var aliases_exports = {};
|
|
5044
5089
|
__export(aliases_exports, {
|
|
@@ -5804,8 +5849,12 @@ async function searchObservations(options) {
|
|
|
5804
5849
|
}
|
|
5805
5850
|
};
|
|
5806
5851
|
const modeKey = options.projectId ?? SEARCH_MODE_DEFAULT_KEY;
|
|
5807
|
-
|
|
5852
|
+
const quality = options.quality ?? "balanced";
|
|
5808
5853
|
const database = await getDb();
|
|
5854
|
+
lastSearchModeByProject.set(
|
|
5855
|
+
modeKey,
|
|
5856
|
+
quality === "fast" ? "fulltext (fast profile)" : embeddingEnabled ? "hybrid" : "fulltext"
|
|
5857
|
+
);
|
|
5809
5858
|
let projectIds = null;
|
|
5810
5859
|
if (options.projectId) {
|
|
5811
5860
|
try {
|
|
@@ -5827,11 +5876,15 @@ async function searchObservations(options) {
|
|
|
5827
5876
|
}
|
|
5828
5877
|
const hasQuery = options.query && options.query.trim().length > 0;
|
|
5829
5878
|
const originalQuery = options.query;
|
|
5830
|
-
const tier = hasQuery ? classifyQueryTier(originalQuery) : "fast";
|
|
5879
|
+
const tier = quality === "fast" ? "fast" : hasQuery ? classifyQueryTier(originalQuery) : "fast";
|
|
5831
5880
|
mark(`tier=${tier}`);
|
|
5832
|
-
|
|
5881
|
+
if (quality === "thorough" && hasQuery) {
|
|
5882
|
+
const { initLLM: initLLM2, isLLMEnabled: isLLMEnabled2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
|
|
5883
|
+
if (!isLLMEnabled2()) initLLM2();
|
|
5884
|
+
}
|
|
5885
|
+
const expandedEmbeddingQuery = quality === "thorough" && tier === "heavy" ? await maybeExpandSearchQuery(options.query) : options.query;
|
|
5833
5886
|
mark("queryExpansion");
|
|
5834
|
-
const intentResult = hasQuery ? detectQueryIntent(originalQuery)
|
|
5887
|
+
const intentResult = quality === "fast" || !hasQuery ? null : detectQueryIntent(originalQuery);
|
|
5835
5888
|
const requestLimit = projectIds ? (options.limit ?? 20) * 3 : options.limit ?? 20;
|
|
5836
5889
|
const defaultBoost = {
|
|
5837
5890
|
title: 3,
|
|
@@ -5845,17 +5898,21 @@ async function searchObservations(options) {
|
|
|
5845
5898
|
let searchParams = {
|
|
5846
5899
|
term: originalQuery,
|
|
5847
5900
|
limit: requestLimit,
|
|
5848
|
-
|
|
5901
|
+
// Fast search never uses vectors, so returning them only adds work and
|
|
5902
|
+
// payload pressure to an explicitly latency-sensitive path.
|
|
5903
|
+
includeVectors: quality !== "fast",
|
|
5849
5904
|
...Object.keys(filters).length > 0 ? { where: filters } : {},
|
|
5850
5905
|
// Search specific fields (not tokens, accessCount, etc.)
|
|
5851
5906
|
properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
|
|
5852
5907
|
// Field boosting: intent-aware or default
|
|
5853
5908
|
boost: fieldBoost,
|
|
5854
5909
|
// Fuzzy tolerance: allow 1-char typos for short queries, 2 for longer
|
|
5855
|
-
|
|
5910
|
+
// Fuzzy matching is useful for ordinary recall, but grows sharply with
|
|
5911
|
+
// corpus size. The fast profile deliberately uses exact lexical matching.
|
|
5912
|
+
...hasQuery && quality !== "fast" ? { tolerance: originalQuery.length > 6 ? 2 : 1 } : {}
|
|
5856
5913
|
};
|
|
5857
5914
|
let queryVector = null;
|
|
5858
|
-
if (embeddingEnabled && hasQuery && tier !== "fast") {
|
|
5915
|
+
if (quality !== "fast" && embeddingEnabled && hasQuery && tier !== "fast") {
|
|
5859
5916
|
try {
|
|
5860
5917
|
const provider2 = await getEmbeddingProvider();
|
|
5861
5918
|
if (provider2) {
|
|
@@ -5870,11 +5927,11 @@ async function searchObservations(options) {
|
|
|
5870
5927
|
);
|
|
5871
5928
|
} else {
|
|
5872
5929
|
const EMBEDDING_TIMEOUT_MS = 15e3;
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5930
|
+
queryVector = await withTimeout(
|
|
5931
|
+
provider2.embed(expandedEmbeddingQuery),
|
|
5932
|
+
EMBEDDING_TIMEOUT_MS,
|
|
5933
|
+
"Embedding"
|
|
5876
5934
|
);
|
|
5877
|
-
queryVector = await Promise.race([embedPromise, timeoutPromise]);
|
|
5878
5935
|
mark("embedding");
|
|
5879
5936
|
const cjkRatio = (originalQuery.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length / originalQuery.length;
|
|
5880
5937
|
const isCJKHeavy = cjkRatio > 0.3;
|
|
@@ -6115,7 +6172,7 @@ async function searchObservations(options) {
|
|
|
6115
6172
|
}
|
|
6116
6173
|
}
|
|
6117
6174
|
}
|
|
6118
|
-
const shouldRerank = tier === "heavy" && hasQuery && intermediate.length > 2 && (() => {
|
|
6175
|
+
const shouldRerank = quality === "thorough" && tier === "heavy" && hasQuery && intermediate.length > 2 && (() => {
|
|
6119
6176
|
const top = intermediate[0]?.score ?? 0;
|
|
6120
6177
|
const second = intermediate[1]?.score ?? 0;
|
|
6121
6178
|
return top > 0 && second / top > 0.7;
|
|
@@ -6139,11 +6196,11 @@ async function searchObservations(options) {
|
|
|
6139
6196
|
}));
|
|
6140
6197
|
const _parsedRerank = parseInt(process.env.MEMORIX_RERANK_TIMEOUT_MS || "", 10);
|
|
6141
6198
|
const RERANK_TIMEOUT_MS = Number.isFinite(_parsedRerank) && _parsedRerank > 0 ? _parsedRerank : 5e3;
|
|
6142
|
-
const
|
|
6143
|
-
|
|
6144
|
-
|
|
6199
|
+
const { reranked, usedLLM } = await withTimeout(
|
|
6200
|
+
rerankResults2(originalQuery, candidates),
|
|
6201
|
+
RERANK_TIMEOUT_MS,
|
|
6202
|
+
"LLM rerank"
|
|
6145
6203
|
);
|
|
6146
|
-
const { reranked, usedLLM } = await Promise.race([rerankPromise, timeoutPromise]);
|
|
6147
6204
|
mark(`rerank(usedLLM=${usedLLM})`);
|
|
6148
6205
|
if (usedLLM) {
|
|
6149
6206
|
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + LLM rerank");
|
|
@@ -6335,6 +6392,7 @@ var init_orama_store = __esm({
|
|
|
6335
6392
|
init_project_affinity();
|
|
6336
6393
|
init_intent_detector();
|
|
6337
6394
|
init_query_expansion();
|
|
6395
|
+
init_timeout();
|
|
6338
6396
|
db = null;
|
|
6339
6397
|
dbInitPromise = null;
|
|
6340
6398
|
dbGeneration = 0;
|
|
@@ -14859,21 +14917,6 @@ async function loadWorkspaceForMaintenance(projectId, projectDir2, mode) {
|
|
|
14859
14917
|
]);
|
|
14860
14918
|
return versioned ?? local;
|
|
14861
14919
|
}
|
|
14862
|
-
function withTimeout(promise, ms, label) {
|
|
14863
|
-
return new Promise((resolve2, reject) => {
|
|
14864
|
-
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
14865
|
-
promise.then(
|
|
14866
|
-
(value) => {
|
|
14867
|
-
clearTimeout(timer);
|
|
14868
|
-
resolve2(value);
|
|
14869
|
-
},
|
|
14870
|
-
(error) => {
|
|
14871
|
-
clearTimeout(timer);
|
|
14872
|
-
reject(error);
|
|
14873
|
-
}
|
|
14874
|
-
);
|
|
14875
|
-
});
|
|
14876
|
-
}
|
|
14877
14920
|
async function runAutomaticConsolidation(projectId, projectDir2, options) {
|
|
14878
14921
|
const { isLLMEnabled: isLLMEnabled2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
|
|
14879
14922
|
if (!isLLMEnabled2()) {
|
|
@@ -15258,6 +15301,7 @@ var init_project_maintenance = __esm({
|
|
|
15258
15301
|
init_esm_shims();
|
|
15259
15302
|
init_isolated_maintenance();
|
|
15260
15303
|
init_lifecycle();
|
|
15304
|
+
init_timeout();
|
|
15261
15305
|
DEFAULT_VECTOR_BATCH_SIZE = 12;
|
|
15262
15306
|
DEFAULT_RETENTION_BATCH_SIZE = 100;
|
|
15263
15307
|
DEFAULT_CONSOLIDATION_BATCH_SIZE = 200;
|
|
@@ -26805,18 +26849,10 @@ function parseFormationTimeoutMs(raw) {
|
|
|
26805
26849
|
}
|
|
26806
26850
|
|
|
26807
26851
|
// src/server.ts
|
|
26852
|
+
init_timeout();
|
|
26808
26853
|
var FORMATION_TIMEOUT_MS = parseFormationTimeoutMs(process.env.MEMORIX_FORMATION_TIMEOUT_MS);
|
|
26809
26854
|
var COMPACT_ON_WRITE_TIMEOUT_MS = 12e3;
|
|
26810
26855
|
var COMPRESSION_TIMEOUT_MS = 5e3;
|
|
26811
|
-
function withTimeout2(promise, ms, label) {
|
|
26812
|
-
let timer;
|
|
26813
|
-
return Promise.race([
|
|
26814
|
-
promise,
|
|
26815
|
-
new Promise((_, reject) => {
|
|
26816
|
-
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
26817
|
-
})
|
|
26818
|
-
]).finally(() => clearTimeout(timer));
|
|
26819
|
-
}
|
|
26820
26856
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
26821
26857
|
const orderedStages = ["extract", "resolve", "evaluate"];
|
|
26822
26858
|
const parts = orderedStages.filter((stage) => stageDurationsMs[stage] !== void 0).map((stage) => `${stage}=${stageDurationsMs[stage]}ms`);
|
|
@@ -27192,7 +27228,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
27192
27228
|
};
|
|
27193
27229
|
const server = existingServer ?? new McpServer({
|
|
27194
27230
|
name: "memorix",
|
|
27195
|
-
version: true ? "1.2.
|
|
27231
|
+
version: true ? "1.2.5" : "1.0.1"
|
|
27196
27232
|
});
|
|
27197
27233
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
27198
27234
|
server.registerTool = ((name, ...args) => {
|
|
@@ -27389,7 +27425,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
27389
27425
|
getEntityNames: () => graphManager.getEntityNames(),
|
|
27390
27426
|
onStageEvent: onFormationStageEvent
|
|
27391
27427
|
};
|
|
27392
|
-
formationResult = await
|
|
27428
|
+
formationResult = await withTimeout(
|
|
27393
27429
|
runFormation({
|
|
27394
27430
|
entityName,
|
|
27395
27431
|
type,
|
|
@@ -27510,7 +27546,7 @@ ${modeIcon} Formation[active]: ${formationResult.evaluation.category} (${formati
|
|
|
27510
27546
|
facts: d.facts,
|
|
27511
27547
|
score: similarEntries[i]?.score ?? 0
|
|
27512
27548
|
}));
|
|
27513
|
-
const decision = await
|
|
27549
|
+
const decision = await withTimeout(
|
|
27514
27550
|
compactOnWrite(
|
|
27515
27551
|
{ title, narrative, facts: safeFacts ?? [] },
|
|
27516
27552
|
existingMemories
|
|
@@ -27606,7 +27642,7 @@ Mode: ${decision.usedLLM ? "LLM" : "heuristic"}`
|
|
|
27606
27642
|
let compressionNote = "";
|
|
27607
27643
|
try {
|
|
27608
27644
|
const { compressNarrative: compressNarrative2 } = await Promise.resolve().then(() => (init_quality(), quality_exports));
|
|
27609
|
-
const { compressed, saved, usedLLM } = await
|
|
27645
|
+
const { compressed, saved, usedLLM } = await withTimeout(
|
|
27610
27646
|
compressNarrative2(narrative, safeFacts, type),
|
|
27611
27647
|
COMPRESSION_TIMEOUT_MS,
|
|
27612
27648
|
"Narrative compression"
|
|
@@ -27728,7 +27764,7 @@ Auto-enriched: ${enrichmentParts.join(", ")}` : "";
|
|
|
27728
27764
|
},
|
|
27729
27765
|
getEntityNames: () => graphManager.getEntityNames()
|
|
27730
27766
|
};
|
|
27731
|
-
const formed = await
|
|
27767
|
+
const formed = await withTimeout(
|
|
27732
27768
|
runFormation({ entityName, type, title, narrative, facts: safeFacts, projectId: project.id, source: "explicit", topicKey }, formationConfig),
|
|
27733
27769
|
FORMATION_TIMEOUT_MS,
|
|
27734
27770
|
"Shadow formation"
|
|
@@ -27819,6 +27855,9 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
27819
27855
|
source: z2.enum(["agent", "git", "manual"]).optional().describe(
|
|
27820
27856
|
'Filter by memory source. "git" returns only commit-derived ground truth memories. Omit for all sources.'
|
|
27821
27857
|
),
|
|
27858
|
+
quality: z2.enum(["fast", "balanced", "thorough"]).optional().default("balanced").describe(
|
|
27859
|
+
"Retrieval profile: fast stays local, balanced uses configured embeddings, thorough explicitly permits optional LLM refinement."
|
|
27860
|
+
),
|
|
27822
27861
|
purpose: z2.string().optional().describe(
|
|
27823
27862
|
"Why this must expand beyond the latest Autopilot brief. Name the missing fact or the user's explicit request."
|
|
27824
27863
|
),
|
|
@@ -27827,7 +27866,7 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
27827
27866
|
)
|
|
27828
27867
|
}
|
|
27829
27868
|
},
|
|
27830
|
-
async ({ query, limit, type, maxTokens, scope, since, until, status, source, purpose, force }) => {
|
|
27869
|
+
async ({ query, limit, type, maxTokens, scope, since, until, status, source, quality, purpose, force }) => {
|
|
27831
27870
|
if (scope !== "global") {
|
|
27832
27871
|
const unresolved = requireResolvedProject("search the current project");
|
|
27833
27872
|
if (unresolved) return unresolved;
|
|
@@ -27852,16 +27891,14 @@ Use this as the \`topicKey\` parameter in \`memorix_store\` to enable upsert beh
|
|
|
27852
27891
|
projectId: scope === "global" ? void 0 : project.id,
|
|
27853
27892
|
status: status ?? "active",
|
|
27854
27893
|
source,
|
|
27894
|
+
quality,
|
|
27855
27895
|
reader: getObservationReader(scope === "global" ? "global" : "project")
|
|
27856
27896
|
});
|
|
27857
|
-
const timeoutPromise = new Promise(
|
|
27858
|
-
(_, reject) => setTimeout(() => reject(new Error(`Search timeout after ${TIMEOUT_MS}ms`)), TIMEOUT_MS)
|
|
27859
|
-
);
|
|
27860
27897
|
let result;
|
|
27861
27898
|
try {
|
|
27862
|
-
result = await
|
|
27899
|
+
result = await withTimeout(searchPromise, TIMEOUT_MS, "Search");
|
|
27863
27900
|
} catch (error) {
|
|
27864
|
-
if (error instanceof Error && error.message
|
|
27901
|
+
if (error instanceof Error && /\btimeout\b|timed out/i.test(error.message)) {
|
|
27865
27902
|
return {
|
|
27866
27903
|
content: [
|
|
27867
27904
|
{
|
|
@@ -31030,6 +31067,7 @@ var MemoryClient = class {
|
|
|
31030
31067
|
type: options.type,
|
|
31031
31068
|
source: options.source,
|
|
31032
31069
|
status: options.status === "all" ? void 0 : options.status ?? "active",
|
|
31070
|
+
quality: options.quality,
|
|
31033
31071
|
reader: this._reader
|
|
31034
31072
|
};
|
|
31035
31073
|
return this._oramaStore.searchObservations(searchOpts);
|