memorix 1.9.9 → 1.9.11
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 +42 -0
- package/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/cli/index.js +855 -231
- package/dist/index.js +284 -77
- package/dist/maintenance-runner.js +74 -20
- package/dist/media-audio-runner.js +74 -20
- package/dist/media-video-runner.js +74 -20
- package/dist/memcode/index.js +1532 -1002
- package/dist/memcode-runtime/CHANGELOG.md +42 -0
- package/dist/memcode-runtime/package.json +4 -4
- package/dist/sdk.js +283 -76
- package/dist/vector-backfill-runner.js +74 -20
- package/docs/CONFIGURATION.md +26 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +3 -1
- package/docs/README.md +2 -1
- package/docs/SETUP.md +1 -1
- package/docs/hooks-architecture.md +5 -0
- package/package.json +18 -11
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/hooks-install.ts +2 -0
- package/src/cli/commands/init.ts +6 -2
- package/src/cli/commands/integrate.ts +2 -0
- package/src/cli/commands/setup.ts +1 -1
- package/src/cli/index.ts +2 -2
- package/src/cli/tui/ConfigureView.tsx +2 -0
- package/src/config/dotenv-loader.ts +1 -0
- package/src/config/resolved-config.ts +7 -3
- package/src/config/yaml-loader.ts +2 -2
- package/src/dashboard/server.ts +3 -0
- package/src/hooks/installers/index.ts +219 -31
- package/src/hooks/lifecycle.ts +4 -9
- package/src/hooks/normalizer.ts +6 -1
- package/src/hooks/types.ts +3 -1
- package/src/llm/provider.ts +2 -1
- package/src/memory/observations.ts +11 -0
- package/src/memory/session.ts +4 -13
- package/src/memory/visibility.ts +8 -2
- package/src/multimodal/image-loader.ts +6 -5
- package/src/server.ts +8 -4
- package/src/store/obs-store.ts +3 -0
- package/src/store/orama-store.ts +43 -6
- package/src/store/sqlite-store.ts +15 -0
|
@@ -2111,15 +2111,16 @@ function getResolvedConfig(options = {}) {
|
|
|
2111
2111
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2112
2112
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
2113
2113
|
const isRequesty = memoryLlmProvider === "requesty";
|
|
2114
|
-
const
|
|
2114
|
+
const isApiRoute = memoryLlmProvider === "apiroute";
|
|
2115
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty || isApiRoute;
|
|
2115
2116
|
const memoryLlmApiKey = first(
|
|
2116
2117
|
process.env.MEMORIX_LLM_API_KEY,
|
|
2117
2118
|
process.env.MEMORIX_API_KEY,
|
|
2118
2119
|
toml.memory?.llm?.api_key,
|
|
2119
2120
|
yaml.llm?.apiKey,
|
|
2120
2121
|
legacy.llm?.apiKey,
|
|
2121
|
-
// Never borrow another provider's credentials for
|
|
2122
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
2122
|
+
// Never borrow another provider's credentials for these gateway presets.
|
|
2123
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : isApiRoute ? process.env.API_ROUTE_API_KEY : process.env.OPENAI_API_KEY,
|
|
2123
2124
|
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
2124
2125
|
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
2125
2126
|
);
|
|
@@ -2302,6 +2303,7 @@ function getEnvSourceNames() {
|
|
|
2302
2303
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
2303
2304
|
"OPENROUTER_API_KEY",
|
|
2304
2305
|
"REQUESTY_API_KEY",
|
|
2306
|
+
"API_ROUTE_API_KEY",
|
|
2305
2307
|
"ATLASCLOUD_API_KEY"
|
|
2306
2308
|
].filter((name) => process.env[name]);
|
|
2307
2309
|
}
|
|
@@ -3146,6 +3148,7 @@ var init_provider = __esm({
|
|
|
3146
3148
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
3147
3149
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
3148
3150
|
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
3151
|
+
apiroute: { baseUrl: "https://global.api-route.com/v1", model: "deepseek-v4.1-flash" },
|
|
3149
3152
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
3150
3153
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
3151
3154
|
};
|
|
@@ -3583,6 +3586,19 @@ var init_sqlite_store = __esm({
|
|
|
3583
3586
|
async listProjectIds() {
|
|
3584
3587
|
return this.db.prepare("SELECT DISTINCT projectId FROM observations ORDER BY projectId").all().map((row) => row.projectId).filter((projectId) => Boolean(projectId));
|
|
3585
3588
|
}
|
|
3589
|
+
async migrateProjectIds(aliasIds, canonicalId) {
|
|
3590
|
+
const sourceIds = [...new Set(aliasIds.filter((projectId) => projectId && projectId !== canonicalId))];
|
|
3591
|
+
if (sourceIds.length === 0) return 0;
|
|
3592
|
+
return retrySqliteBusy(async () => {
|
|
3593
|
+
const placeholders = sourceIds.map(() => "?").join(", ");
|
|
3594
|
+
const result = this.db.prepare(
|
|
3595
|
+
`UPDATE observations SET projectId = ? WHERE projectId IN (${placeholders})`
|
|
3596
|
+
).run(canonicalId, ...sourceIds);
|
|
3597
|
+
const migrated = Number(result.changes ?? 0);
|
|
3598
|
+
if (migrated > 0) this.bumpGeneration();
|
|
3599
|
+
return migrated;
|
|
3600
|
+
}, "Migrate observation project IDs");
|
|
3601
|
+
}
|
|
3586
3602
|
async searchLexical(options) {
|
|
3587
3603
|
return searchObservationLexically(this.db, options).map((hit) => ({
|
|
3588
3604
|
observation: rowToObs(hit.row),
|
|
@@ -4012,9 +4028,9 @@ function sharedAgentIds(record80) {
|
|
|
4012
4028
|
return [];
|
|
4013
4029
|
}
|
|
4014
4030
|
}
|
|
4015
|
-
function canReadObservation(record80, reader) {
|
|
4031
|
+
function canReadObservation(record80, reader, allowedProjectIds) {
|
|
4016
4032
|
if (!reader) return true;
|
|
4017
|
-
const sameProject = reader.projectId === record80.projectId;
|
|
4033
|
+
const sameProject = allowedProjectIds ? allowedProjectIds.includes(record80.projectId) : reader.projectId === record80.projectId;
|
|
4018
4034
|
const visibility = resolveObservationVisibility(record80);
|
|
4019
4035
|
if (visibility === "project") return !reader.projectId || sameProject;
|
|
4020
4036
|
if (!sameProject || !reader.agentId) return false;
|
|
@@ -7129,6 +7145,7 @@ var orama_store_exports = {};
|
|
|
7129
7145
|
__export(orama_store_exports, {
|
|
7130
7146
|
_classifyQueryTier: () => classifyQueryTier,
|
|
7131
7147
|
batchGenerateEmbeddings: () => batchGenerateEmbeddings,
|
|
7148
|
+
createSearchTokenizer: () => createSearchTokenizer,
|
|
7132
7149
|
generateEmbedding: () => generateEmbedding,
|
|
7133
7150
|
generateEmbeddingInput: () => generateEmbeddingInput,
|
|
7134
7151
|
getActiveSemanticIndexProfile: () => getActiveSemanticIndexProfile,
|
|
@@ -7151,7 +7168,7 @@ __export(orama_store_exports, {
|
|
|
7151
7168
|
searchObservations: () => searchObservations,
|
|
7152
7169
|
updateObservationMetadata: () => updateObservationMetadata
|
|
7153
7170
|
});
|
|
7154
|
-
import { create, insert as insert2, insertMultiple, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
7171
|
+
import { components, create, insert as insert2, insertMultiple, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
7155
7172
|
function rememberSearchMode(key, value) {
|
|
7156
7173
|
if (!lastSearchModeByProject.has(key) && lastSearchModeByProject.size >= MAX_SEARCH_MODE_KEYS) {
|
|
7157
7174
|
const oldest = lastSearchModeByProject.keys().next().value;
|
|
@@ -7170,6 +7187,26 @@ function getOptionalObservationStore() {
|
|
|
7170
7187
|
return null;
|
|
7171
7188
|
}
|
|
7172
7189
|
}
|
|
7190
|
+
function createSearchTokenizer() {
|
|
7191
|
+
const defaultTokenizer = components.tokenizer.createTokenizer({ language: "english" });
|
|
7192
|
+
return {
|
|
7193
|
+
language: defaultTokenizer.language,
|
|
7194
|
+
normalizationCache: defaultTokenizer.normalizationCache,
|
|
7195
|
+
tokenize(raw, language, prop, withCache = true) {
|
|
7196
|
+
const defaultTokens = defaultTokenizer.tokenize(raw, language, prop, withCache);
|
|
7197
|
+
const cjkTokens = [];
|
|
7198
|
+
const normalized = raw.normalize("NFKC").toLowerCase();
|
|
7199
|
+
for (const match2 of normalized.matchAll(CJK_RUN)) {
|
|
7200
|
+
const characters = Array.from(match2[0]);
|
|
7201
|
+
cjkTokens.push(...characters);
|
|
7202
|
+
for (let index = 0; index + 1 < characters.length; index++) {
|
|
7203
|
+
cjkTokens.push(`${characters[index]}${characters[index + 1]}`);
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
return [.../* @__PURE__ */ new Set([...defaultTokens, ...cjkTokens])];
|
|
7207
|
+
}
|
|
7208
|
+
};
|
|
7209
|
+
}
|
|
7173
7210
|
async function shouldUsePersistentSearch(projectIds, projectId) {
|
|
7174
7211
|
const store = getOptionalObservationStore();
|
|
7175
7212
|
if (!store?.hasLexicalIndex?.()) return false;
|
|
@@ -7270,6 +7307,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
7270
7307
|
const lexical = await searchPersistentLexically(options, projectIds, limit2);
|
|
7271
7308
|
const store = getObservationStore();
|
|
7272
7309
|
const documents = /* @__PURE__ */ new Map();
|
|
7310
|
+
const vectorDocumentKeys = /* @__PURE__ */ new Map();
|
|
7273
7311
|
const addObservation = (observation) => {
|
|
7274
7312
|
const document2 = observationToSearchDocument(observation);
|
|
7275
7313
|
documents.set(makeEntryKey(document2.projectId, document2.observationId), document2);
|
|
@@ -7285,6 +7323,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
7285
7323
|
if (options.type && observation.type !== options.type) return null;
|
|
7286
7324
|
if (options.source && observation.source !== options.source) return null;
|
|
7287
7325
|
addObservation(observation);
|
|
7326
|
+
vectorDocumentKeys.set(hit.observationId, makeEntryKey(observation.projectId, observation.id));
|
|
7288
7327
|
return observation;
|
|
7289
7328
|
}));
|
|
7290
7329
|
const RRF_K = 60;
|
|
@@ -7294,7 +7333,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
7294
7333
|
scores.set(key, (scores.get(key) ?? 0) + 0.6 / (RRF_K + index + 1));
|
|
7295
7334
|
}
|
|
7296
7335
|
for (const [index, hit] of vectorHits.entries()) {
|
|
7297
|
-
const key = makeEntryKey(hit.projectId, hit.observationId);
|
|
7336
|
+
const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
|
|
7298
7337
|
if (!documents.has(key)) continue;
|
|
7299
7338
|
scores.set(key, (scores.get(key) ?? 0) + 0.4 / (RRF_K + index + 1));
|
|
7300
7339
|
}
|
|
@@ -7307,12 +7346,13 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
7307
7346
|
return {
|
|
7308
7347
|
count: vectorHits.length,
|
|
7309
7348
|
hits: vectorHits.map((hit, index) => {
|
|
7310
|
-
const key = makeEntryKey(hit.projectId, hit.observationId);
|
|
7349
|
+
const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
|
|
7311
7350
|
const document2 = documents.get(key);
|
|
7312
7351
|
return document2 ? { id: document2.id, score: 0.4 / (RRF_K + index + 1), document: document2 } : null;
|
|
7313
7352
|
}).filter((hit) => hit !== null).slice(0, limit2)
|
|
7314
7353
|
};
|
|
7315
7354
|
}
|
|
7355
|
+
if (hits.length === 0) return null;
|
|
7316
7356
|
return { count: hits.length, hits };
|
|
7317
7357
|
} catch {
|
|
7318
7358
|
return null;
|
|
@@ -7387,7 +7427,10 @@ async function initializeDb(options, generation) {
|
|
|
7387
7427
|
};
|
|
7388
7428
|
const dims = nextEmbeddingDimensions ?? 384;
|
|
7389
7429
|
const schema = nextEmbeddingEnabled ? { ...baseSchema, embedding: `vector[${dims}]` } : baseSchema;
|
|
7390
|
-
const nextDb = await create({
|
|
7430
|
+
const nextDb = await create({
|
|
7431
|
+
schema,
|
|
7432
|
+
components: { tokenizer: createSearchTokenizer() }
|
|
7433
|
+
});
|
|
7391
7434
|
if (generation !== dbGeneration) {
|
|
7392
7435
|
return getDb(options);
|
|
7393
7436
|
}
|
|
@@ -7821,7 +7864,7 @@ async function searchObservations(options) {
|
|
|
7821
7864
|
if (!projectIds) return true;
|
|
7822
7865
|
const doc = hit.document;
|
|
7823
7866
|
return projectIds.includes(doc.projectId);
|
|
7824
|
-
}).filter((hit) => canReadObservation(hit.document, options.reader)).filter((hit) => {
|
|
7867
|
+
}).filter((hit) => canReadObservation(hit.document, options.reader, projectIds ?? void 0)).filter((hit) => {
|
|
7825
7868
|
if (statusFilter === "all") return true;
|
|
7826
7869
|
const doc = hit.document;
|
|
7827
7870
|
return (doc.status || "active") === statusFilter;
|
|
@@ -8087,7 +8130,7 @@ async function searchObservations(options) {
|
|
|
8087
8130
|
let entries = intermediate.map(({ rawTime: _, _isCommandLog: _c, ...rest }) => rest);
|
|
8088
8131
|
for (const hit of results.hits) {
|
|
8089
8132
|
const doc = hit.document;
|
|
8090
|
-
if (canReadObservation(doc, options.reader)) rememberObservationDoc(doc);
|
|
8133
|
+
if (canReadObservation(doc, options.reader, projectIds ?? void 0)) rememberObservationDoc(doc);
|
|
8091
8134
|
}
|
|
8092
8135
|
if (hasQuery && originalQuery) {
|
|
8093
8136
|
const queryLower = originalQuery.toLowerCase();
|
|
@@ -8245,7 +8288,7 @@ function formatTime(isoDate) {
|
|
|
8245
8288
|
return isoDate;
|
|
8246
8289
|
}
|
|
8247
8290
|
}
|
|
8248
|
-
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
8291
|
+
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, CJK_RUN, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
8249
8292
|
var init_orama_store = __esm({
|
|
8250
8293
|
"src/store/orama-store.ts"() {
|
|
8251
8294
|
"use strict";
|
|
@@ -8269,6 +8312,7 @@ var init_orama_store = __esm({
|
|
|
8269
8312
|
indexEmbeddingProvider = null;
|
|
8270
8313
|
deferredCachedVectorHydration = null;
|
|
8271
8314
|
NON_CJK_HYBRID_SIMILARITY = 0.45;
|
|
8315
|
+
CJK_RUN = /[\u3400-\u4dbf\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]+/gu;
|
|
8272
8316
|
lastSearchModeByProject = /* @__PURE__ */ new Map();
|
|
8273
8317
|
SEARCH_MODE_DEFAULT_KEY = "__global__";
|
|
8274
8318
|
MAX_SEARCH_MODE_KEYS = 4096;
|
|
@@ -71849,16 +71893,16 @@ var require_pluggable_auth_handler = __commonJS({
|
|
|
71849
71893
|
* spaces are between quotation marks.
|
|
71850
71894
|
*/
|
|
71851
71895
|
static parseCommand(command) {
|
|
71852
|
-
const
|
|
71853
|
-
if (!
|
|
71896
|
+
const components2 = command.match(/(?:[^\s"]+|"[^"]*")+/g);
|
|
71897
|
+
if (!components2) {
|
|
71854
71898
|
throw new Error(`Provided command: "${command}" could not be parsed.`);
|
|
71855
71899
|
}
|
|
71856
|
-
for (let i2 = 0; i2 <
|
|
71857
|
-
if (
|
|
71858
|
-
|
|
71900
|
+
for (let i2 = 0; i2 < components2.length; i2++) {
|
|
71901
|
+
if (components2[i2][0] === '"' && components2[i2].slice(-1) === '"') {
|
|
71902
|
+
components2[i2] = components2[i2].slice(1, -1);
|
|
71859
71903
|
}
|
|
71860
71904
|
}
|
|
71861
|
-
return
|
|
71905
|
+
return components2;
|
|
71862
71906
|
}
|
|
71863
71907
|
};
|
|
71864
71908
|
exports.PluggableAuthHandler = PluggableAuthHandler;
|
|
@@ -151984,6 +152028,16 @@ function getProjectObservations(projectId) {
|
|
|
151984
152028
|
async function migrateProjectIds(aliasIds, canonicalId) {
|
|
151985
152029
|
const nonCanonical = new Set(aliasIds.filter((id) => id !== canonicalId));
|
|
151986
152030
|
if (nonCanonical.size === 0) return 0;
|
|
152031
|
+
const store = projectDir ? getObservationStore() : null;
|
|
152032
|
+
if (store?.migrateProjectIds) {
|
|
152033
|
+
const migrated2 = await store.migrateProjectIds(aliasIds, canonicalId);
|
|
152034
|
+
if (migrated2 > 0 && corpusLoaded) {
|
|
152035
|
+
for (const observation of observations) {
|
|
152036
|
+
if (nonCanonical.has(observation.projectId)) observation.projectId = canonicalId;
|
|
152037
|
+
}
|
|
152038
|
+
}
|
|
152039
|
+
return migrated2;
|
|
152040
|
+
}
|
|
151987
152041
|
let migrated = 0;
|
|
151988
152042
|
const changed = [];
|
|
151989
152043
|
for (const obs of observations) {
|
|
@@ -151994,8 +152048,8 @@ async function migrateProjectIds(aliasIds, canonicalId) {
|
|
|
151994
152048
|
}
|
|
151995
152049
|
}
|
|
151996
152050
|
if (migrated > 0 && projectDir) {
|
|
151997
|
-
const
|
|
151998
|
-
await
|
|
152051
|
+
const store2 = getObservationStore();
|
|
152052
|
+
await store2.atomic(async (tx) => {
|
|
151999
152053
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
152000
152054
|
});
|
|
152001
152055
|
}
|
|
@@ -3026,9 +3026,9 @@ function sharedAgentIds(record80) {
|
|
|
3026
3026
|
return [];
|
|
3027
3027
|
}
|
|
3028
3028
|
}
|
|
3029
|
-
function canReadObservation(record80, reader) {
|
|
3029
|
+
function canReadObservation(record80, reader, allowedProjectIds) {
|
|
3030
3030
|
if (!reader) return true;
|
|
3031
|
-
const sameProject = reader.projectId === record80.projectId;
|
|
3031
|
+
const sameProject = allowedProjectIds ? allowedProjectIds.includes(record80.projectId) : reader.projectId === record80.projectId;
|
|
3032
3032
|
const visibility = resolveObservationVisibility(record80);
|
|
3033
3033
|
if (visibility === "project") return !reader.projectId || sameProject;
|
|
3034
3034
|
if (!sameProject || !reader.agentId) return false;
|
|
@@ -3394,15 +3394,16 @@ function getResolvedConfig(options = {}) {
|
|
|
3394
3394
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3395
3395
|
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
3396
3396
|
const isRequesty = memoryLlmProvider === "requesty";
|
|
3397
|
-
const
|
|
3397
|
+
const isApiRoute = memoryLlmProvider === "apiroute";
|
|
3398
|
+
const usesPresetKeyOnly = isAtlasCloud || isRequesty || isApiRoute;
|
|
3398
3399
|
const memoryLlmApiKey = first(
|
|
3399
3400
|
process.env.MEMORIX_LLM_API_KEY,
|
|
3400
3401
|
process.env.MEMORIX_API_KEY,
|
|
3401
3402
|
toml.memory?.llm?.api_key,
|
|
3402
3403
|
yaml.llm?.apiKey,
|
|
3403
3404
|
legacy.llm?.apiKey,
|
|
3404
|
-
// Never borrow another provider's credentials for
|
|
3405
|
-
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : process.env.OPENAI_API_KEY,
|
|
3405
|
+
// Never borrow another provider's credentials for these gateway presets.
|
|
3406
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : isRequesty ? process.env.REQUESTY_API_KEY : isApiRoute ? process.env.API_ROUTE_API_KEY : process.env.OPENAI_API_KEY,
|
|
3406
3407
|
usesPresetKeyOnly ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
3407
3408
|
usesPresetKeyOnly ? void 0 : openRouterMemoryLlmApiKey
|
|
3408
3409
|
);
|
|
@@ -3585,6 +3586,7 @@ function getEnvSourceNames() {
|
|
|
3585
3586
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
3586
3587
|
"OPENROUTER_API_KEY",
|
|
3587
3588
|
"REQUESTY_API_KEY",
|
|
3589
|
+
"API_ROUTE_API_KEY",
|
|
3588
3590
|
"ATLASCLOUD_API_KEY"
|
|
3589
3591
|
].filter((name) => process.env[name]);
|
|
3590
3592
|
}
|
|
@@ -6578,6 +6580,7 @@ var init_provider2 = __esm({
|
|
|
6578
6580
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
6579
6581
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
6580
6582
|
requesty: { baseUrl: "https://router.requesty.ai/v1", model: "openai/gpt-4.1-nano" },
|
|
6583
|
+
apiroute: { baseUrl: "https://global.api-route.com/v1", model: "deepseek-v4.1-flash" },
|
|
6581
6584
|
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
6582
6585
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
6583
6586
|
};
|
|
@@ -7072,6 +7075,19 @@ var init_sqlite_store = __esm({
|
|
|
7072
7075
|
async listProjectIds() {
|
|
7073
7076
|
return this.db.prepare("SELECT DISTINCT projectId FROM observations ORDER BY projectId").all().map((row) => row.projectId).filter((projectId) => Boolean(projectId));
|
|
7074
7077
|
}
|
|
7078
|
+
async migrateProjectIds(aliasIds, canonicalId) {
|
|
7079
|
+
const sourceIds = [...new Set(aliasIds.filter((projectId) => projectId && projectId !== canonicalId))];
|
|
7080
|
+
if (sourceIds.length === 0) return 0;
|
|
7081
|
+
return retrySqliteBusy(async () => {
|
|
7082
|
+
const placeholders = sourceIds.map(() => "?").join(", ");
|
|
7083
|
+
const result = this.db.prepare(
|
|
7084
|
+
`UPDATE observations SET projectId = ? WHERE projectId IN (${placeholders})`
|
|
7085
|
+
).run(canonicalId, ...sourceIds);
|
|
7086
|
+
const migrated = Number(result.changes ?? 0);
|
|
7087
|
+
if (migrated > 0) this.bumpGeneration();
|
|
7088
|
+
return migrated;
|
|
7089
|
+
}, "Migrate observation project IDs");
|
|
7090
|
+
}
|
|
7075
7091
|
async searchLexical(options) {
|
|
7076
7092
|
return searchObservationLexically(this.db, options).map((hit) => ({
|
|
7077
7093
|
observation: rowToObs(hit.row),
|
|
@@ -8117,6 +8133,7 @@ var orama_store_exports = {};
|
|
|
8117
8133
|
__export(orama_store_exports, {
|
|
8118
8134
|
_classifyQueryTier: () => classifyQueryTier,
|
|
8119
8135
|
batchGenerateEmbeddings: () => batchGenerateEmbeddings,
|
|
8136
|
+
createSearchTokenizer: () => createSearchTokenizer,
|
|
8120
8137
|
generateEmbedding: () => generateEmbedding,
|
|
8121
8138
|
generateEmbeddingInput: () => generateEmbeddingInput,
|
|
8122
8139
|
getActiveSemanticIndexProfile: () => getActiveSemanticIndexProfile,
|
|
@@ -8139,7 +8156,7 @@ __export(orama_store_exports, {
|
|
|
8139
8156
|
searchObservations: () => searchObservations,
|
|
8140
8157
|
updateObservationMetadata: () => updateObservationMetadata
|
|
8141
8158
|
});
|
|
8142
|
-
import { create, insert as insert2, insertMultiple, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
8159
|
+
import { components, create, insert as insert2, insertMultiple, search, remove as remove2, update, count, getByID } from "@orama/orama";
|
|
8143
8160
|
function rememberSearchMode(key, value) {
|
|
8144
8161
|
if (!lastSearchModeByProject.has(key) && lastSearchModeByProject.size >= MAX_SEARCH_MODE_KEYS) {
|
|
8145
8162
|
const oldest = lastSearchModeByProject.keys().next().value;
|
|
@@ -8158,6 +8175,26 @@ function getOptionalObservationStore() {
|
|
|
8158
8175
|
return null;
|
|
8159
8176
|
}
|
|
8160
8177
|
}
|
|
8178
|
+
function createSearchTokenizer() {
|
|
8179
|
+
const defaultTokenizer = components.tokenizer.createTokenizer({ language: "english" });
|
|
8180
|
+
return {
|
|
8181
|
+
language: defaultTokenizer.language,
|
|
8182
|
+
normalizationCache: defaultTokenizer.normalizationCache,
|
|
8183
|
+
tokenize(raw, language, prop, withCache = true) {
|
|
8184
|
+
const defaultTokens = defaultTokenizer.tokenize(raw, language, prop, withCache);
|
|
8185
|
+
const cjkTokens = [];
|
|
8186
|
+
const normalized = raw.normalize("NFKC").toLowerCase();
|
|
8187
|
+
for (const match2 of normalized.matchAll(CJK_RUN)) {
|
|
8188
|
+
const characters = Array.from(match2[0]);
|
|
8189
|
+
cjkTokens.push(...characters);
|
|
8190
|
+
for (let index = 0; index + 1 < characters.length; index++) {
|
|
8191
|
+
cjkTokens.push(`${characters[index]}${characters[index + 1]}`);
|
|
8192
|
+
}
|
|
8193
|
+
}
|
|
8194
|
+
return [.../* @__PURE__ */ new Set([...defaultTokens, ...cjkTokens])];
|
|
8195
|
+
}
|
|
8196
|
+
};
|
|
8197
|
+
}
|
|
8161
8198
|
async function shouldUsePersistentSearch(projectIds, projectId) {
|
|
8162
8199
|
const store = getOptionalObservationStore();
|
|
8163
8200
|
if (!store?.hasLexicalIndex?.()) return false;
|
|
@@ -8258,6 +8295,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
8258
8295
|
const lexical = await searchPersistentLexically(options, projectIds, limit2);
|
|
8259
8296
|
const store = getObservationStore();
|
|
8260
8297
|
const documents = /* @__PURE__ */ new Map();
|
|
8298
|
+
const vectorDocumentKeys = /* @__PURE__ */ new Map();
|
|
8261
8299
|
const addObservation = (observation) => {
|
|
8262
8300
|
const document2 = observationToSearchDocument(observation);
|
|
8263
8301
|
documents.set(makeEntryKey(document2.projectId, document2.observationId), document2);
|
|
@@ -8273,6 +8311,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
8273
8311
|
if (options.type && observation.type !== options.type) return null;
|
|
8274
8312
|
if (options.source && observation.source !== options.source) return null;
|
|
8275
8313
|
addObservation(observation);
|
|
8314
|
+
vectorDocumentKeys.set(hit.observationId, makeEntryKey(observation.projectId, observation.id));
|
|
8276
8315
|
return observation;
|
|
8277
8316
|
}));
|
|
8278
8317
|
const RRF_K = 60;
|
|
@@ -8282,7 +8321,7 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
8282
8321
|
scores.set(key, (scores.get(key) ?? 0) + 0.6 / (RRF_K + index + 1));
|
|
8283
8322
|
}
|
|
8284
8323
|
for (const [index, hit] of vectorHits.entries()) {
|
|
8285
|
-
const key = makeEntryKey(hit.projectId, hit.observationId);
|
|
8324
|
+
const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
|
|
8286
8325
|
if (!documents.has(key)) continue;
|
|
8287
8326
|
scores.set(key, (scores.get(key) ?? 0) + 0.4 / (RRF_K + index + 1));
|
|
8288
8327
|
}
|
|
@@ -8295,12 +8334,13 @@ async function searchPersistentSemantically(options, projectIds, limit2, queryVe
|
|
|
8295
8334
|
return {
|
|
8296
8335
|
count: vectorHits.length,
|
|
8297
8336
|
hits: vectorHits.map((hit, index) => {
|
|
8298
|
-
const key = makeEntryKey(hit.projectId, hit.observationId);
|
|
8337
|
+
const key = vectorDocumentKeys.get(hit.observationId) ?? makeEntryKey(hit.projectId, hit.observationId);
|
|
8299
8338
|
const document2 = documents.get(key);
|
|
8300
8339
|
return document2 ? { id: document2.id, score: 0.4 / (RRF_K + index + 1), document: document2 } : null;
|
|
8301
8340
|
}).filter((hit) => hit !== null).slice(0, limit2)
|
|
8302
8341
|
};
|
|
8303
8342
|
}
|
|
8343
|
+
if (hits.length === 0) return null;
|
|
8304
8344
|
return { count: hits.length, hits };
|
|
8305
8345
|
} catch {
|
|
8306
8346
|
return null;
|
|
@@ -8375,7 +8415,10 @@ async function initializeDb(options, generation) {
|
|
|
8375
8415
|
};
|
|
8376
8416
|
const dims = nextEmbeddingDimensions ?? 384;
|
|
8377
8417
|
const schema = nextEmbeddingEnabled ? { ...baseSchema, embedding: `vector[${dims}]` } : baseSchema;
|
|
8378
|
-
const nextDb = await create({
|
|
8418
|
+
const nextDb = await create({
|
|
8419
|
+
schema,
|
|
8420
|
+
components: { tokenizer: createSearchTokenizer() }
|
|
8421
|
+
});
|
|
8379
8422
|
if (generation !== dbGeneration) {
|
|
8380
8423
|
return getDb(options);
|
|
8381
8424
|
}
|
|
@@ -8809,7 +8852,7 @@ async function searchObservations(options) {
|
|
|
8809
8852
|
if (!projectIds) return true;
|
|
8810
8853
|
const doc = hit.document;
|
|
8811
8854
|
return projectIds.includes(doc.projectId);
|
|
8812
|
-
}).filter((hit) => canReadObservation(hit.document, options.reader)).filter((hit) => {
|
|
8855
|
+
}).filter((hit) => canReadObservation(hit.document, options.reader, projectIds ?? void 0)).filter((hit) => {
|
|
8813
8856
|
if (statusFilter === "all") return true;
|
|
8814
8857
|
const doc = hit.document;
|
|
8815
8858
|
return (doc.status || "active") === statusFilter;
|
|
@@ -9075,7 +9118,7 @@ async function searchObservations(options) {
|
|
|
9075
9118
|
let entries = intermediate.map(({ rawTime: _, _isCommandLog: _c, ...rest }) => rest);
|
|
9076
9119
|
for (const hit of results.hits) {
|
|
9077
9120
|
const doc = hit.document;
|
|
9078
|
-
if (canReadObservation(doc, options.reader)) rememberObservationDoc(doc);
|
|
9121
|
+
if (canReadObservation(doc, options.reader, projectIds ?? void 0)) rememberObservationDoc(doc);
|
|
9079
9122
|
}
|
|
9080
9123
|
if (hasQuery && originalQuery) {
|
|
9081
9124
|
const queryLower = originalQuery.toLowerCase();
|
|
@@ -9233,7 +9276,7 @@ function formatTime(isoDate) {
|
|
|
9233
9276
|
return isoDate;
|
|
9234
9277
|
}
|
|
9235
9278
|
}
|
|
9236
|
-
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
9279
|
+
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, NON_CJK_HYBRID_SIMILARITY, CJK_RUN, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, MAX_SEARCH_MODE_KEYS, COMMAND_LOG_TITLE, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
9237
9280
|
var init_orama_store = __esm({
|
|
9238
9281
|
"src/store/orama-store.ts"() {
|
|
9239
9282
|
"use strict";
|
|
@@ -9257,6 +9300,7 @@ var init_orama_store = __esm({
|
|
|
9257
9300
|
indexEmbeddingProvider = null;
|
|
9258
9301
|
deferredCachedVectorHydration = null;
|
|
9259
9302
|
NON_CJK_HYBRID_SIMILARITY = 0.45;
|
|
9303
|
+
CJK_RUN = /[\u3400-\u4dbf\u4e00-\u9fff\u3040-\u30ff\uac00-\ud7af]+/gu;
|
|
9260
9304
|
lastSearchModeByProject = /* @__PURE__ */ new Map();
|
|
9261
9305
|
SEARCH_MODE_DEFAULT_KEY = "__global__";
|
|
9262
9306
|
MAX_SEARCH_MODE_KEYS = 4096;
|
|
@@ -71774,16 +71818,16 @@ var require_pluggable_auth_handler = __commonJS({
|
|
|
71774
71818
|
* spaces are between quotation marks.
|
|
71775
71819
|
*/
|
|
71776
71820
|
static parseCommand(command) {
|
|
71777
|
-
const
|
|
71778
|
-
if (!
|
|
71821
|
+
const components2 = command.match(/(?:[^\s"]+|"[^"]*")+/g);
|
|
71822
|
+
if (!components2) {
|
|
71779
71823
|
throw new Error(`Provided command: "${command}" could not be parsed.`);
|
|
71780
71824
|
}
|
|
71781
|
-
for (let i2 = 0; i2 <
|
|
71782
|
-
if (
|
|
71783
|
-
|
|
71825
|
+
for (let i2 = 0; i2 < components2.length; i2++) {
|
|
71826
|
+
if (components2[i2][0] === '"' && components2[i2].slice(-1) === '"') {
|
|
71827
|
+
components2[i2] = components2[i2].slice(1, -1);
|
|
71784
71828
|
}
|
|
71785
71829
|
}
|
|
71786
|
-
return
|
|
71830
|
+
return components2;
|
|
71787
71831
|
}
|
|
71788
71832
|
};
|
|
71789
71833
|
exports.PluggableAuthHandler = PluggableAuthHandler;
|
|
@@ -151615,6 +151659,16 @@ function getProjectObservations(projectId) {
|
|
|
151615
151659
|
async function migrateProjectIds(aliasIds, canonicalId) {
|
|
151616
151660
|
const nonCanonical = new Set(aliasIds.filter((id) => id !== canonicalId));
|
|
151617
151661
|
if (nonCanonical.size === 0) return 0;
|
|
151662
|
+
const store = projectDir ? getObservationStore() : null;
|
|
151663
|
+
if (store?.migrateProjectIds) {
|
|
151664
|
+
const migrated2 = await store.migrateProjectIds(aliasIds, canonicalId);
|
|
151665
|
+
if (migrated2 > 0 && corpusLoaded) {
|
|
151666
|
+
for (const observation of observations) {
|
|
151667
|
+
if (nonCanonical.has(observation.projectId)) observation.projectId = canonicalId;
|
|
151668
|
+
}
|
|
151669
|
+
}
|
|
151670
|
+
return migrated2;
|
|
151671
|
+
}
|
|
151618
151672
|
let migrated = 0;
|
|
151619
151673
|
const changed = [];
|
|
151620
151674
|
for (const obs of observations) {
|
|
@@ -151625,8 +151679,8 @@ async function migrateProjectIds(aliasIds, canonicalId) {
|
|
|
151625
151679
|
}
|
|
151626
151680
|
}
|
|
151627
151681
|
if (migrated > 0 && projectDir) {
|
|
151628
|
-
const
|
|
151629
|
-
await
|
|
151682
|
+
const store2 = getObservationStore();
|
|
151683
|
+
await store2.atomic(async (tx) => {
|
|
151630
151684
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
151631
151685
|
});
|
|
151632
151686
|
}
|