memorix 1.1.11 → 1.1.12
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 +16 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +350 -73
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +289 -44
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.js +252 -36
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +16 -0
- package/dist/memcode-runtime/package.json +4 -4
- package/dist/sdk.js +289 -44
- package/dist/sdk.js.map +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +1 -1
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/dev-log/progress.txt +56 -47
- package/docs/hooks-architecture.md +24 -12
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -0
- package/plugins/codex/memorix/hooks/hooks.json +30 -0
- package/src/cli/commands/hooks-install.ts +2 -1
- package/src/cli/commands/setup.ts +7 -1
- package/src/cli/tui/chat-service.ts +3 -9
- package/src/cli/tui/data.ts +9 -11
- package/src/embedding/api-provider.ts +105 -6
- package/src/embedding/provider.ts +31 -3
- package/src/hooks/handler.ts +51 -14
- package/src/hooks/installers/index.ts +48 -7
- package/src/hooks/normalizer.ts +15 -0
- package/src/memory/observations.ts +90 -15
- package/src/store/orama-store.ts +169 -17
package/dist/cli/index.js
CHANGED
|
@@ -3212,7 +3212,7 @@ ${import_picocolors.default.gray(m3)} ${s2}
|
|
|
3212
3212
|
|
|
3213
3213
|
// src/cli/version.ts
|
|
3214
3214
|
function getCliVersion() {
|
|
3215
|
-
return true ? "1.1.
|
|
3215
|
+
return true ? "1.1.12" : pkg.version;
|
|
3216
3216
|
}
|
|
3217
3217
|
var init_version = __esm({
|
|
3218
3218
|
"src/cli/version.ts"() {
|
|
@@ -13667,6 +13667,45 @@ function dimsCacheKey(config2) {
|
|
|
13667
13667
|
config2.requestedDimensions ?? "native"
|
|
13668
13668
|
].join("|");
|
|
13669
13669
|
}
|
|
13670
|
+
function isValidDimension(value) {
|
|
13671
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
13672
|
+
}
|
|
13673
|
+
async function loadCachedVectorDimensions(config2) {
|
|
13674
|
+
try {
|
|
13675
|
+
const raw = await readFile2(CACHE_META_FILE, "utf-8");
|
|
13676
|
+
const data = JSON.parse(raw);
|
|
13677
|
+
const namespace = cacheNamespace(config2);
|
|
13678
|
+
if (!Array.isArray(data?.entries)) return null;
|
|
13679
|
+
const entry = data.entries.find(
|
|
13680
|
+
(candidate) => typeof candidate === "object" && candidate !== null && candidate.namespace === namespace && isValidDimension(candidate.dimensions)
|
|
13681
|
+
);
|
|
13682
|
+
return entry?.dimensions ?? null;
|
|
13683
|
+
} catch {
|
|
13684
|
+
return null;
|
|
13685
|
+
}
|
|
13686
|
+
}
|
|
13687
|
+
async function saveCachedVectorDimensions(config2, dimensions) {
|
|
13688
|
+
if (!isValidDimension(dimensions)) return;
|
|
13689
|
+
try {
|
|
13690
|
+
await mkdir2(CACHE_DIR2, { recursive: true });
|
|
13691
|
+
let entries = [];
|
|
13692
|
+
try {
|
|
13693
|
+
const raw = await readFile2(CACHE_META_FILE, "utf-8");
|
|
13694
|
+
const data = JSON.parse(raw);
|
|
13695
|
+
if (Array.isArray(data?.entries)) {
|
|
13696
|
+
entries = data.entries.filter(
|
|
13697
|
+
(candidate) => typeof candidate === "object" && candidate !== null && typeof candidate.namespace === "string" && isValidDimension(candidate.dimensions) && typeof candidate.ts === "number"
|
|
13698
|
+
);
|
|
13699
|
+
}
|
|
13700
|
+
} catch {
|
|
13701
|
+
}
|
|
13702
|
+
const namespace = cacheNamespace(config2);
|
|
13703
|
+
entries = entries.filter((entry) => entry.namespace !== namespace);
|
|
13704
|
+
entries.push({ namespace, dimensions, ts: Date.now() });
|
|
13705
|
+
await writeFile2(CACHE_META_FILE, JSON.stringify({ version: 1, entries }));
|
|
13706
|
+
} catch {
|
|
13707
|
+
}
|
|
13708
|
+
}
|
|
13670
13709
|
async function loadCachedDims(config2) {
|
|
13671
13710
|
try {
|
|
13672
13711
|
const raw = await readFile2(DIMS_CACHE_FILE, "utf-8");
|
|
@@ -13729,6 +13768,7 @@ async function saveCachedDims(config2, dimensions) {
|
|
|
13729
13768
|
await writeFile2(DIMS_CACHE_FILE, JSON.stringify({ entries }));
|
|
13730
13769
|
} catch {
|
|
13731
13770
|
}
|
|
13771
|
+
await saveCachedVectorDimensions(config2, dimensions);
|
|
13732
13772
|
}
|
|
13733
13773
|
async function saveDiskCacheNow() {
|
|
13734
13774
|
if (!diskCacheDirty2) return;
|
|
@@ -13811,7 +13851,7 @@ async function fetchWithRetry(url, apiKey, body, attempt = 0) {
|
|
|
13811
13851
|
const errorText2 = await response.text().catch(() => "unknown error");
|
|
13812
13852
|
throw new Error(`Embedding API error (${response.status}): ${errorText2}`);
|
|
13813
13853
|
}
|
|
13814
|
-
var CACHE_DIR2, CACHE_FILE2, DIMS_CACHE_FILE, cache3, MAX_CACHE_SIZE3, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES, BASE_DELAY_MS, APIEmbeddingProvider;
|
|
13854
|
+
var CACHE_DIR2, CACHE_FILE2, DIMS_CACHE_FILE, CACHE_META_FILE, cache3, MAX_CACHE_SIZE3, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES, BASE_DELAY_MS, APIEmbeddingProvider;
|
|
13815
13855
|
var init_api_provider = __esm({
|
|
13816
13856
|
"src/embedding/api-provider.ts"() {
|
|
13817
13857
|
"use strict";
|
|
@@ -13819,6 +13859,7 @@ var init_api_provider = __esm({
|
|
|
13819
13859
|
CACHE_DIR2 = process.env.MEMORIX_DATA_DIR || join4(homedir7(), ".memorix", "data");
|
|
13820
13860
|
CACHE_FILE2 = join4(CACHE_DIR2, ".embedding-api-cache.json");
|
|
13821
13861
|
DIMS_CACHE_FILE = join4(CACHE_DIR2, ".embedding-dims-cache.json");
|
|
13862
|
+
CACHE_META_FILE = join4(CACHE_DIR2, ".embedding-api-cache-meta.json");
|
|
13822
13863
|
cache3 = /* @__PURE__ */ new Map();
|
|
13823
13864
|
MAX_CACHE_SIZE3 = 1e4;
|
|
13824
13865
|
diskCacheDirty2 = false;
|
|
@@ -13845,13 +13886,22 @@ var init_api_provider = __esm({
|
|
|
13845
13886
|
this.dimensions = detectedDimensions;
|
|
13846
13887
|
this.name = `api-${config2.model.replace(/\//g, "-")}`;
|
|
13847
13888
|
}
|
|
13848
|
-
static async create() {
|
|
13889
|
+
static async create(options2 = {}) {
|
|
13849
13890
|
const config2 = _APIEmbeddingProvider.resolveConfig();
|
|
13850
|
-
|
|
13891
|
+
const allowNetworkProbe = options2.allowNetworkProbe !== false;
|
|
13851
13892
|
let probeDimensions = await loadCachedDims(config2);
|
|
13893
|
+
let dimensionSource = "dims-cache";
|
|
13894
|
+
if (probeDimensions === null) {
|
|
13895
|
+
probeDimensions = await loadCachedVectorDimensions(config2);
|
|
13896
|
+
if (probeDimensions !== null) dimensionSource = "vector-cache";
|
|
13897
|
+
}
|
|
13852
13898
|
if (probeDimensions !== null) {
|
|
13853
|
-
console.error(`[memorix] API embedding: ${config2.model} @ ${config2.baseUrl} (${probeDimensions}d) [
|
|
13899
|
+
console.error(`[memorix] API embedding: ${config2.model} @ ${config2.baseUrl} (${probeDimensions}d) [${dimensionSource}]`);
|
|
13900
|
+
if (dimensionSource === "dims-cache") {
|
|
13901
|
+
void saveCachedVectorDimensions(config2, probeDimensions);
|
|
13902
|
+
}
|
|
13854
13903
|
} else {
|
|
13904
|
+
if (!allowNetworkProbe) return null;
|
|
13855
13905
|
probeDimensions = await _APIEmbeddingProvider.probeAPI(config2);
|
|
13856
13906
|
console.error(`[memorix] API embedding: ${config2.model} @ ${config2.baseUrl} (${probeDimensions}d)`);
|
|
13857
13907
|
saveCachedDims(config2, probeDimensions).catch(() => {
|
|
@@ -13860,6 +13910,7 @@ var init_api_provider = __esm({
|
|
|
13860
13910
|
if (config2.requestedDimensions) {
|
|
13861
13911
|
console.error(`[memorix] Dimension shortening: ${config2.requestedDimensions}d requested`);
|
|
13862
13912
|
}
|
|
13913
|
+
startDiskCacheLoad();
|
|
13863
13914
|
return new _APIEmbeddingProvider(config2, probeDimensions);
|
|
13864
13915
|
}
|
|
13865
13916
|
static resolveConfig() {
|
|
@@ -14038,6 +14089,13 @@ var init_api_provider = __esm({
|
|
|
14038
14089
|
scheduleDiskSave();
|
|
14039
14090
|
return results;
|
|
14040
14091
|
}
|
|
14092
|
+
async getCachedEmbeddings(texts) {
|
|
14093
|
+
await ensureDiskCacheLoaded();
|
|
14094
|
+
return texts.map((text) => {
|
|
14095
|
+
const hash = textHash2(normalizeText(text), this.cacheKeyNamespace);
|
|
14096
|
+
return cache3.get(hash) ?? null;
|
|
14097
|
+
});
|
|
14098
|
+
}
|
|
14041
14099
|
getStats() {
|
|
14042
14100
|
return {
|
|
14043
14101
|
totalTokens: this.totalTokensUsed,
|
|
@@ -14146,10 +14204,10 @@ async function createTransformersProvider() {
|
|
|
14146
14204
|
return null;
|
|
14147
14205
|
}
|
|
14148
14206
|
}
|
|
14149
|
-
async function createAPIProvider() {
|
|
14207
|
+
async function createAPIProvider(options2) {
|
|
14150
14208
|
try {
|
|
14151
14209
|
const { APIEmbeddingProvider: APIEmbeddingProvider2 } = await Promise.resolve().then(() => (init_api_provider(), api_provider_exports));
|
|
14152
|
-
return await APIEmbeddingProvider2.create();
|
|
14210
|
+
return await APIEmbeddingProvider2.create(options2 ?? {});
|
|
14153
14211
|
} catch (e3) {
|
|
14154
14212
|
warnOnce(`[memorix] Failed to init API embedding: ${e3 instanceof Error ? e3.message : e3}`);
|
|
14155
14213
|
return null;
|
|
@@ -14204,11 +14262,24 @@ function wrapProvider(candidate) {
|
|
|
14204
14262
|
}
|
|
14205
14263
|
throw error2;
|
|
14206
14264
|
}
|
|
14207
|
-
}
|
|
14265
|
+
},
|
|
14266
|
+
...candidate.getCachedEmbeddings ? {
|
|
14267
|
+
async getCachedEmbeddings(texts) {
|
|
14268
|
+
return candidate.getCachedEmbeddings(texts);
|
|
14269
|
+
}
|
|
14270
|
+
} : {}
|
|
14208
14271
|
};
|
|
14209
14272
|
}
|
|
14210
|
-
async function getEmbeddingProvider() {
|
|
14273
|
+
async function getEmbeddingProvider(options2 = {}) {
|
|
14211
14274
|
if (provider) return provider;
|
|
14275
|
+
if (options2.allowNetworkProbe === false) {
|
|
14276
|
+
const mode = getEmbeddingMode2();
|
|
14277
|
+
if (mode !== "api" && !(mode === "auto" && hasAPIEmbeddingConfig())) {
|
|
14278
|
+
return null;
|
|
14279
|
+
}
|
|
14280
|
+
const cached2 = await createAPIProvider({ allowNetworkProbe: false });
|
|
14281
|
+
return cached2 ? wrapProvider(cached2) : null;
|
|
14282
|
+
}
|
|
14212
14283
|
if (lastInitWasTemporaryFailure) {
|
|
14213
14284
|
const elapsed = Date.now() - lastFailureTimestamp;
|
|
14214
14285
|
if (elapsed < RETRY_COOLDOWN_MS) {
|
|
@@ -15721,12 +15792,15 @@ __export(orama_store_exports, {
|
|
|
15721
15792
|
batchGenerateEmbeddings: () => batchGenerateEmbeddings,
|
|
15722
15793
|
generateEmbedding: () => generateEmbedding,
|
|
15723
15794
|
getDb: () => getDb,
|
|
15795
|
+
getDeferredCachedVectorHydration: () => getDeferredCachedVectorHydration,
|
|
15724
15796
|
getLastSearchMode: () => getLastSearchMode,
|
|
15725
15797
|
getObservationCount: () => getObservationCount,
|
|
15726
15798
|
getObservationsByIds: () => getObservationsByIds,
|
|
15727
15799
|
getTimeline: () => getTimeline,
|
|
15728
15800
|
getVectorDimensions: () => getVectorDimensions,
|
|
15801
|
+
hasObservationVector: () => hasObservationVector,
|
|
15729
15802
|
hydrateIndex: () => hydrateIndex,
|
|
15803
|
+
hydrateIndexForStartup: () => hydrateIndexForStartup,
|
|
15730
15804
|
insertObservation: () => insertObservation,
|
|
15731
15805
|
isEmbeddingEnabled: () => isEmbeddingEnabled,
|
|
15732
15806
|
makeOramaObservationId: () => makeOramaObservationId,
|
|
@@ -15786,11 +15860,10 @@ function stripVectorSearchParams(params) {
|
|
|
15786
15860
|
const { mode, vector, similarity, hybridWeights, ...rest } = params;
|
|
15787
15861
|
return rest;
|
|
15788
15862
|
}
|
|
15789
|
-
async function
|
|
15790
|
-
|
|
15791
|
-
const
|
|
15792
|
-
|
|
15793
|
-
embeddingDimensions = provider2?.dimensions ?? null;
|
|
15863
|
+
async function initializeDb(options2, generation) {
|
|
15864
|
+
const provider2 = await getEmbeddingProvider({ allowNetworkProbe: options2.allowNetworkProbe });
|
|
15865
|
+
const nextEmbeddingEnabled = provider2 !== null;
|
|
15866
|
+
const nextEmbeddingDimensions = provider2?.dimensions ?? null;
|
|
15794
15867
|
const baseSchema = {
|
|
15795
15868
|
id: "string",
|
|
15796
15869
|
observationId: "number",
|
|
@@ -15813,15 +15886,39 @@ async function getDb() {
|
|
|
15813
15886
|
documentType: "string",
|
|
15814
15887
|
knowledgeLayer: "string"
|
|
15815
15888
|
};
|
|
15816
|
-
const dims =
|
|
15817
|
-
const schema =
|
|
15818
|
-
|
|
15819
|
-
|
|
15889
|
+
const dims = nextEmbeddingDimensions ?? 384;
|
|
15890
|
+
const schema = nextEmbeddingEnabled ? { ...baseSchema, embedding: `vector[${dims}]` } : baseSchema;
|
|
15891
|
+
const nextDb = await create5({ schema });
|
|
15892
|
+
if (generation !== dbGeneration) {
|
|
15893
|
+
return getDb(options2);
|
|
15894
|
+
}
|
|
15895
|
+
indexEmbeddingProvider = provider2;
|
|
15896
|
+
embeddingEnabled = nextEmbeddingEnabled;
|
|
15897
|
+
embeddingDimensions = nextEmbeddingDimensions;
|
|
15898
|
+
db = nextDb;
|
|
15899
|
+
return nextDb;
|
|
15900
|
+
}
|
|
15901
|
+
async function getDb(options2 = {}) {
|
|
15902
|
+
if (db) return db;
|
|
15903
|
+
if (dbInitPromise) return dbInitPromise;
|
|
15904
|
+
const initPromise2 = initializeDb(options2, dbGeneration);
|
|
15905
|
+
dbInitPromise = initPromise2;
|
|
15906
|
+
try {
|
|
15907
|
+
return await initPromise2;
|
|
15908
|
+
} finally {
|
|
15909
|
+
if (dbInitPromise === initPromise2) {
|
|
15910
|
+
dbInitPromise = null;
|
|
15911
|
+
}
|
|
15912
|
+
}
|
|
15820
15913
|
}
|
|
15821
15914
|
async function resetDb() {
|
|
15915
|
+
dbGeneration++;
|
|
15822
15916
|
db = null;
|
|
15917
|
+
dbInitPromise = null;
|
|
15823
15918
|
embeddingEnabled = false;
|
|
15824
15919
|
embeddingDimensions = null;
|
|
15920
|
+
indexEmbeddingProvider = null;
|
|
15921
|
+
deferredCachedVectorHydration = null;
|
|
15825
15922
|
lastSearchModeByProject.clear();
|
|
15826
15923
|
docByObservationKey.clear();
|
|
15827
15924
|
}
|
|
@@ -15849,14 +15946,64 @@ async function batchGenerateEmbeddings(texts) {
|
|
|
15849
15946
|
return texts.map(() => null);
|
|
15850
15947
|
}
|
|
15851
15948
|
}
|
|
15852
|
-
async function
|
|
15853
|
-
|
|
15949
|
+
async function getCachedEmbeddings(texts) {
|
|
15950
|
+
if (!embeddingEnabled || texts.length === 0) return texts.map(() => null);
|
|
15951
|
+
const provider2 = indexEmbeddingProvider;
|
|
15952
|
+
if (!provider2?.getCachedEmbeddings) return texts.map(() => null);
|
|
15953
|
+
try {
|
|
15954
|
+
return await provider2.getCachedEmbeddings(texts);
|
|
15955
|
+
} catch {
|
|
15956
|
+
return texts.map(() => null);
|
|
15957
|
+
}
|
|
15958
|
+
}
|
|
15959
|
+
function observationEmbeddingText(observation) {
|
|
15960
|
+
return [
|
|
15961
|
+
observation.title ?? "",
|
|
15962
|
+
observation.narrative ?? "",
|
|
15963
|
+
...Array.isArray(observation.facts) ? observation.facts : []
|
|
15964
|
+
].join(" ");
|
|
15965
|
+
}
|
|
15966
|
+
function documentEmbeddingText(document) {
|
|
15967
|
+
return [document.title ?? "", document.narrative ?? "", document.facts ?? ""].join(" ");
|
|
15968
|
+
}
|
|
15969
|
+
function isCompatibleCachedVector(vector) {
|
|
15970
|
+
return Boolean(
|
|
15971
|
+
vector && embeddingDimensions !== null && vector.length === embeddingDimensions && vector.every(Number.isFinite)
|
|
15972
|
+
);
|
|
15973
|
+
}
|
|
15974
|
+
async function attachCachedVectors(database, candidates) {
|
|
15975
|
+
const cachedVectors = await getCachedEmbeddings(
|
|
15976
|
+
candidates.map(({ observation }) => observationEmbeddingText(observation))
|
|
15977
|
+
);
|
|
15978
|
+
if (db !== database) return;
|
|
15979
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
15980
|
+
const vector = cachedVectors[index];
|
|
15981
|
+
if (!isCompatibleCachedVector(vector)) continue;
|
|
15982
|
+
const existing = getByID(database, candidates[index].id);
|
|
15983
|
+
if (!existing || documentEmbeddingText(existing) !== observationEmbeddingText(candidates[index].observation)) continue;
|
|
15984
|
+
try {
|
|
15985
|
+
await update(database, candidates[index].id, { ...existing, embedding: vector });
|
|
15986
|
+
} catch {
|
|
15987
|
+
}
|
|
15988
|
+
}
|
|
15989
|
+
}
|
|
15990
|
+
async function hydrateIndex(observations2, options2 = {}) {
|
|
15991
|
+
const database = await getDb({ allowNetworkProbe: options2.allowNetworkProbe });
|
|
15992
|
+
const candidates = [];
|
|
15993
|
+
for (const observation of observations2) {
|
|
15994
|
+
if (!observation || !observation.id || !observation.projectId) continue;
|
|
15995
|
+
const id = makeOramaObservationId(observation.projectId, observation.id);
|
|
15996
|
+
if (getByID(database, id)) continue;
|
|
15997
|
+
candidates.push({ observation, id });
|
|
15998
|
+
}
|
|
15999
|
+
const deferCachedVectors = options2.deferCachedVectors === true && Boolean(indexEmbeddingProvider?.getCachedEmbeddings);
|
|
16000
|
+
const cachedVectors = deferCachedVectors ? candidates.map(() => null) : await getCachedEmbeddings(candidates.map(({ observation }) => observationEmbeddingText(observation)));
|
|
15854
16001
|
let inserted = 0;
|
|
15855
|
-
for (
|
|
15856
|
-
|
|
16002
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
16003
|
+
const { observation: obs, id } = candidates[index];
|
|
15857
16004
|
try {
|
|
15858
|
-
const
|
|
15859
|
-
|
|
16005
|
+
const vector = cachedVectors[index];
|
|
16006
|
+
const compatibleVector = isCompatibleCachedVector(vector) ? vector : null;
|
|
15860
16007
|
const doc = {
|
|
15861
16008
|
id,
|
|
15862
16009
|
observationId: obs.id,
|
|
@@ -15875,7 +16022,8 @@ async function hydrateIndex(observations2) {
|
|
|
15875
16022
|
status: obs.status ?? "active",
|
|
15876
16023
|
source: obs.source || "agent",
|
|
15877
16024
|
documentType: "observation",
|
|
15878
|
-
knowledgeLayer: resolveKnowledgeLayer("observation", obs.sourceDetail, obs.source)
|
|
16025
|
+
knowledgeLayer: resolveKnowledgeLayer("observation", obs.sourceDetail, obs.source),
|
|
16026
|
+
...compatibleVector ? { embedding: compatibleVector } : {}
|
|
15879
16027
|
};
|
|
15880
16028
|
await insert3(database, doc);
|
|
15881
16029
|
rememberObservationDoc(doc);
|
|
@@ -15883,8 +16031,24 @@ async function hydrateIndex(observations2) {
|
|
|
15883
16031
|
} catch {
|
|
15884
16032
|
}
|
|
15885
16033
|
}
|
|
16034
|
+
deferredCachedVectorHydration = deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
|
|
16035
|
+
}) : null;
|
|
15886
16036
|
return inserted;
|
|
15887
16037
|
}
|
|
16038
|
+
async function hydrateIndexForStartup(observations2) {
|
|
16039
|
+
return hydrateIndex(observations2, {
|
|
16040
|
+
allowNetworkProbe: false,
|
|
16041
|
+
deferCachedVectors: true
|
|
16042
|
+
});
|
|
16043
|
+
}
|
|
16044
|
+
function getDeferredCachedVectorHydration() {
|
|
16045
|
+
return deferredCachedVectorHydration;
|
|
16046
|
+
}
|
|
16047
|
+
function hasObservationVector(projectId, observationId) {
|
|
16048
|
+
if (!db || !embeddingEnabled || embeddingDimensions === null) return false;
|
|
16049
|
+
const document = getByID(db, makeOramaObservationId(projectId, observationId));
|
|
16050
|
+
return Array.isArray(document?.embedding) && document.embedding.length === embeddingDimensions && document.embedding.every(Number.isFinite);
|
|
16051
|
+
}
|
|
15888
16052
|
async function insertObservation(doc) {
|
|
15889
16053
|
const database = await getDb();
|
|
15890
16054
|
await insert3(database, doc);
|
|
@@ -16418,7 +16582,7 @@ function formatTime(isoDate) {
|
|
|
16418
16582
|
return isoDate;
|
|
16419
16583
|
}
|
|
16420
16584
|
}
|
|
16421
|
-
var db, embeddingEnabled, embeddingDimensions, docByObservationKey, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, COMMAND_LOG_TITLE2, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
16585
|
+
var db, dbInitPromise, dbGeneration, embeddingEnabled, embeddingDimensions, indexEmbeddingProvider, deferredCachedVectorHydration, docByObservationKey, NON_CJK_HYBRID_SIMILARITY, lastSearchModeByProject, SEARCH_MODE_DEFAULT_KEY, COMMAND_LOG_TITLE2, COMMAND_STYLE_TITLE, COMMAND_LIKE_QUERY2, COMMAND_INTENT_QUERY, NATURAL_LANGUAGE_MARKERS;
|
|
16422
16586
|
var init_orama_store = __esm({
|
|
16423
16587
|
"src/store/orama-store.ts"() {
|
|
16424
16588
|
"use strict";
|
|
@@ -16431,8 +16595,12 @@ var init_orama_store = __esm({
|
|
|
16431
16595
|
init_intent_detector();
|
|
16432
16596
|
init_query_expansion();
|
|
16433
16597
|
db = null;
|
|
16598
|
+
dbInitPromise = null;
|
|
16599
|
+
dbGeneration = 0;
|
|
16434
16600
|
embeddingEnabled = false;
|
|
16435
16601
|
embeddingDimensions = null;
|
|
16602
|
+
indexEmbeddingProvider = null;
|
|
16603
|
+
deferredCachedVectorHydration = null;
|
|
16436
16604
|
docByObservationKey = /* @__PURE__ */ new Map();
|
|
16437
16605
|
NON_CJK_HYBRID_SIMILARITY = 0.45;
|
|
16438
16606
|
lastSearchModeByProject = /* @__PURE__ */ new Map();
|
|
@@ -18213,7 +18381,18 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
18213
18381
|
function isVectorCompatibleWithCurrentIndex(embedding) {
|
|
18214
18382
|
if (!embedding) return false;
|
|
18215
18383
|
const vectorDimensions = getVectorDimensions();
|
|
18216
|
-
return vectorDimensions
|
|
18384
|
+
return vectorDimensions !== null && embedding.length === vectorDimensions && embedding.every(Number.isFinite);
|
|
18385
|
+
}
|
|
18386
|
+
async function upgradeVectorSchemaAfterFirstEmbedding(embedding) {
|
|
18387
|
+
if (isVectorCompatibleWithCurrentIndex(embedding)) return true;
|
|
18388
|
+
if (getVectorDimensions() !== null || !embedding.every(Number.isFinite)) return false;
|
|
18389
|
+
const targetProjectDir = projectDir;
|
|
18390
|
+
if (!vectorSchemaUpgradePromise) {
|
|
18391
|
+
vectorSchemaUpgradePromise = reindexObservations().then(() => projectDir === targetProjectDir && isVectorCompatibleWithCurrentIndex(embedding)).catch(() => false).finally(() => {
|
|
18392
|
+
vectorSchemaUpgradePromise = null;
|
|
18393
|
+
});
|
|
18394
|
+
}
|
|
18395
|
+
return vectorSchemaUpgradePromise;
|
|
18217
18396
|
}
|
|
18218
18397
|
async function initObservations(dir) {
|
|
18219
18398
|
if (projectDir === dir) return;
|
|
@@ -18223,6 +18402,7 @@ async function initObservations(dir) {
|
|
|
18223
18402
|
nextId = await store2.loadIdCounter();
|
|
18224
18403
|
projectDir = dir;
|
|
18225
18404
|
searchIndexPrepared = false;
|
|
18405
|
+
vectorSchemaUpgradePromise = null;
|
|
18226
18406
|
}
|
|
18227
18407
|
async function ensureFreshObservations() {
|
|
18228
18408
|
if (!projectDir) return false;
|
|
@@ -18402,6 +18582,9 @@ async function storeObservation(input) {
|
|
|
18402
18582
|
const searchableText = [input.title, input.narrative, ...input.facts ?? []].join(" ");
|
|
18403
18583
|
generateEmbedding(searchableText).then(async (embedding) => {
|
|
18404
18584
|
if (embedding) {
|
|
18585
|
+
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
18586
|
+
await upgradeVectorSchemaAfterFirstEmbedding(embedding);
|
|
18587
|
+
}
|
|
18405
18588
|
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
18406
18589
|
const vectorDimensions = getVectorDimensions();
|
|
18407
18590
|
console.error(
|
|
@@ -18512,6 +18695,13 @@ async function upsertObservation(existing, input, now) {
|
|
|
18512
18695
|
vectorMissingIds.add(obsId);
|
|
18513
18696
|
generateEmbedding(searchableText).then(async (embedding) => {
|
|
18514
18697
|
if (embedding) {
|
|
18698
|
+
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
18699
|
+
await upgradeVectorSchemaAfterFirstEmbedding(embedding);
|
|
18700
|
+
}
|
|
18701
|
+
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
18702
|
+
queueVectorBackfill(existing.projectId);
|
|
18703
|
+
return;
|
|
18704
|
+
}
|
|
18515
18705
|
try {
|
|
18516
18706
|
const { removeObservation: removeObs } = await Promise.resolve().then(() => (init_orama_store(), orama_store_exports));
|
|
18517
18707
|
await removeObs(makeOramaObservationId(existing.projectId, obsId));
|
|
@@ -18656,14 +18846,21 @@ async function reindexObservations() {
|
|
|
18656
18846
|
let embeddings = observations.map(() => null);
|
|
18657
18847
|
const provider2 = await getEmbeddingProvider();
|
|
18658
18848
|
const canBatchEmbedAtStartup = provider2 !== null && !provider2.name.startsWith("api-");
|
|
18849
|
+
await getDb();
|
|
18850
|
+
const texts = observations.map(
|
|
18851
|
+
(obs) => [obs.title, obs.narrative, ...obs.facts].join(" ")
|
|
18852
|
+
);
|
|
18853
|
+
if (provider2?.getCachedEmbeddings) {
|
|
18854
|
+
try {
|
|
18855
|
+
embeddings = await provider2.getCachedEmbeddings(texts);
|
|
18856
|
+
} catch {
|
|
18857
|
+
}
|
|
18858
|
+
}
|
|
18659
18859
|
if (provider2 && !canBatchEmbedAtStartup) {
|
|
18660
|
-
console.error("[memorix] Startup reindex:
|
|
18860
|
+
console.error("[memorix] Startup reindex: restored cached API embeddings; uncached vectors stay in background recovery");
|
|
18661
18861
|
}
|
|
18662
18862
|
if (canBatchEmbedAtStartup) {
|
|
18663
18863
|
try {
|
|
18664
|
-
const texts = observations.map(
|
|
18665
|
-
(obs) => [obs.title, obs.narrative, ...obs.facts].join(" ")
|
|
18666
|
-
);
|
|
18667
18864
|
embeddings = await batchGenerateEmbeddings(texts);
|
|
18668
18865
|
} catch {
|
|
18669
18866
|
}
|
|
@@ -18716,16 +18913,31 @@ async function reindexObservations() {
|
|
|
18716
18913
|
}
|
|
18717
18914
|
async function prepareSearchIndex() {
|
|
18718
18915
|
if (searchIndexPrepared) return 0;
|
|
18719
|
-
const count3 = await
|
|
18916
|
+
const count3 = await hydrateIndexForStartup(observations);
|
|
18720
18917
|
if (count3 === 0) {
|
|
18721
18918
|
searchIndexPrepared = true;
|
|
18722
18919
|
return 0;
|
|
18723
18920
|
}
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
|
|
18921
|
+
const hydratedProjectDir = projectDir;
|
|
18922
|
+
const queueMissingVectors = () => {
|
|
18923
|
+
if (projectDir !== hydratedProjectDir) return;
|
|
18924
|
+
vectorMissingIds.clear();
|
|
18925
|
+
if (!isEmbeddingExplicitlyDisabled()) {
|
|
18926
|
+
const projectsWithMissingVectors = /* @__PURE__ */ new Set();
|
|
18927
|
+
for (const obs of observations) {
|
|
18928
|
+
if (!hasObservationVector(obs.projectId, obs.id)) {
|
|
18929
|
+
vectorMissingIds.add(obs.id);
|
|
18930
|
+
projectsWithMissingVectors.add(obs.projectId);
|
|
18931
|
+
}
|
|
18932
|
+
}
|
|
18933
|
+
for (const projectId of projectsWithMissingVectors) queueVectorBackfill(projectId);
|
|
18728
18934
|
}
|
|
18935
|
+
};
|
|
18936
|
+
const cacheHydration = getDeferredCachedVectorHydration();
|
|
18937
|
+
if (cacheHydration) {
|
|
18938
|
+
void cacheHydration.finally(queueMissingVectors);
|
|
18939
|
+
} else {
|
|
18940
|
+
queueMissingVectors();
|
|
18729
18941
|
}
|
|
18730
18942
|
searchIndexPrepared = true;
|
|
18731
18943
|
return count3;
|
|
@@ -18785,6 +18997,9 @@ async function backfillVectorEmbeddings(options2 = {}) {
|
|
|
18785
18997
|
try {
|
|
18786
18998
|
const embedding = await generateEmbedding(text);
|
|
18787
18999
|
if (embedding) {
|
|
19000
|
+
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
19001
|
+
await upgradeVectorSchemaAfterFirstEmbedding(embedding);
|
|
19002
|
+
}
|
|
18788
19003
|
if (!isVectorCompatibleWithCurrentIndex(embedding)) {
|
|
18789
19004
|
const vectorDimensions = getVectorDimensions();
|
|
18790
19005
|
console.error(
|
|
@@ -18847,7 +19062,7 @@ async function backfillVectorEmbeddings(options2 = {}) {
|
|
|
18847
19062
|
}
|
|
18848
19063
|
return { attempted: ids.length, succeeded, failed };
|
|
18849
19064
|
}
|
|
18850
|
-
var observations, nextId, projectDir, searchIndexPrepared, vectorMissingIds, vectorBackfillRunning, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
19065
|
+
var observations, nextId, projectDir, searchIndexPrepared, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
18851
19066
|
var init_observations = __esm({
|
|
18852
19067
|
"src/memory/observations.ts"() {
|
|
18853
19068
|
"use strict";
|
|
@@ -18865,6 +19080,7 @@ var init_observations = __esm({
|
|
|
18865
19080
|
searchIndexPrepared = false;
|
|
18866
19081
|
vectorMissingIds = /* @__PURE__ */ new Set();
|
|
18867
19082
|
vectorBackfillRunning = false;
|
|
19083
|
+
vectorSchemaUpgradePromise = null;
|
|
18868
19084
|
lastVectorBackfill = null;
|
|
18869
19085
|
embeddingFailureLogTimestamps = /* @__PURE__ */ new Map();
|
|
18870
19086
|
EMBEDDING_FAILURE_LOG_COOLDOWN_MS = 3e4;
|
|
@@ -19574,11 +19790,8 @@ function normalizeSearchMode(raw) {
|
|
|
19574
19790
|
}
|
|
19575
19791
|
async function prepareProjectSearch(projectId, dataDir) {
|
|
19576
19792
|
if (preparedProjects.has(projectId)) return;
|
|
19577
|
-
await initObservationStore(dataDir);
|
|
19578
19793
|
await initObservations(dataDir);
|
|
19579
|
-
await
|
|
19580
|
-
const allObs = getAllObservations();
|
|
19581
|
-
await hydrateIndex(allObs);
|
|
19794
|
+
await prepareSearchIndex();
|
|
19582
19795
|
preparedProjects.add(projectId);
|
|
19583
19796
|
}
|
|
19584
19797
|
function executeSearchMemories(args, ctx) {
|
|
@@ -19984,7 +20197,6 @@ var init_chat_service = __esm({
|
|
|
19984
20197
|
init_provider2();
|
|
19985
20198
|
init_observations();
|
|
19986
20199
|
init_detector();
|
|
19987
|
-
init_obs_store();
|
|
19988
20200
|
init_orama_store();
|
|
19989
20201
|
init_persistence();
|
|
19990
20202
|
SEARCH_LIMIT = 6;
|
|
@@ -21931,6 +22143,7 @@ __export(installers_exports, {
|
|
|
21931
22143
|
getProjectConfigPath: () => getProjectConfigPath,
|
|
21932
22144
|
installAgentGuidance: () => installAgentGuidance,
|
|
21933
22145
|
installHooks: () => installHooks,
|
|
22146
|
+
resolveOpenCodeHookCommand: () => resolveOpenCodeHookCommand,
|
|
21934
22147
|
uninstallHooks: () => uninstallHooks
|
|
21935
22148
|
});
|
|
21936
22149
|
import * as fs9 from "fs/promises";
|
|
@@ -21943,6 +22156,22 @@ function resolveHookCommand() {
|
|
|
21943
22156
|
}
|
|
21944
22157
|
return "memorix";
|
|
21945
22158
|
}
|
|
22159
|
+
function resolveWindowsMemorixShim() {
|
|
22160
|
+
try {
|
|
22161
|
+
const output = String(execSync2("where.exe memorix.cmd", {
|
|
22162
|
+
encoding: "utf-8",
|
|
22163
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
22164
|
+
windowsHide: true
|
|
22165
|
+
}));
|
|
22166
|
+
return output.split(/\r?\n/).map((candidate) => candidate.trim()).find((candidate) => path13.isAbsolute(candidate)) ?? null;
|
|
22167
|
+
} catch {
|
|
22168
|
+
return null;
|
|
22169
|
+
}
|
|
22170
|
+
}
|
|
22171
|
+
function resolveOpenCodeHookCommand(platform2 = process.platform, resolveWindowsShim = resolveWindowsMemorixShim) {
|
|
22172
|
+
if (platform2 !== "win32") return "memorix";
|
|
22173
|
+
return resolveWindowsShim() ?? "memorix.cmd";
|
|
22174
|
+
}
|
|
21946
22175
|
function generateClaudeConfig() {
|
|
21947
22176
|
const cmd = `${resolveHookCommand()} hook`;
|
|
21948
22177
|
const hookEntry = {
|
|
@@ -22142,6 +22371,7 @@ async function installOfficialSkillsForAgent(agent, projectRoot, global2 = false
|
|
|
22142
22371
|
return skillPaths;
|
|
22143
22372
|
}
|
|
22144
22373
|
function generateOpenCodePlugin() {
|
|
22374
|
+
const hookCommand = JSON.stringify(resolveOpenCodeHookCommand());
|
|
22145
22375
|
return `/**
|
|
22146
22376
|
* Memorix - Cross-Agent Memory Bridge Plugin for OpenCode
|
|
22147
22377
|
* @generated-version ${OPENCODE_PLUGIN_VERSION}
|
|
@@ -22160,6 +22390,16 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
22160
22390
|
const sessionId = \`opencode-\${Date.now().toString(36)}-\${Math.random().toString(36).slice(2, 8)}\`;
|
|
22161
22391
|
let pendingAssistantResponse = null;
|
|
22162
22392
|
let lastDeliveredAssistantKey = '';
|
|
22393
|
+
let hookFailureReported = false;
|
|
22394
|
+
const hookCommand = ${hookCommand};
|
|
22395
|
+
|
|
22396
|
+
function reportHookFailure(eventName, detail) {
|
|
22397
|
+
// OpenCode renders console.error output inside the conversation. Delivery is
|
|
22398
|
+
// best-effort, so keep normal sessions quiet while retaining opt-in diagnostics.
|
|
22399
|
+
if (process.env.MEMORIX_HOOK_DEBUG !== '1' || hookFailureReported) return;
|
|
22400
|
+
hookFailureReported = true;
|
|
22401
|
+
console.error('[memorix-plugin] hook delivery failed:', eventName, detail);
|
|
22402
|
+
}
|
|
22163
22403
|
|
|
22164
22404
|
/**
|
|
22165
22405
|
* Send event JSON to \`memorix hook\` via child_process.spawnSync.
|
|
@@ -22175,8 +22415,7 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
22175
22415
|
const data = JSON.stringify(payload);
|
|
22176
22416
|
const eventName = payload.hook_event_name || 'unknown';
|
|
22177
22417
|
try {
|
|
22178
|
-
const
|
|
22179
|
-
const result = spawnSync(cmd, ['hook'], {
|
|
22418
|
+
const result = spawnSync(hookCommand, ['hook'], {
|
|
22180
22419
|
input: data,
|
|
22181
22420
|
timeout: 10_000,
|
|
22182
22421
|
encoding: 'utf-8',
|
|
@@ -22184,12 +22423,14 @@ export const MemorixPlugin = async ({ project, client, $, directory, worktree })
|
|
|
22184
22423
|
shell: process.platform === 'win32',
|
|
22185
22424
|
});
|
|
22186
22425
|
if (result.status !== 0) {
|
|
22187
|
-
|
|
22188
|
-
|
|
22189
|
-
|
|
22426
|
+
reportHookFailure(eventName, {
|
|
22427
|
+
exit: result.status,
|
|
22428
|
+
stderr: (result.stderr || '').slice(0, 200),
|
|
22429
|
+
error: result.error?.message,
|
|
22430
|
+
});
|
|
22190
22431
|
}
|
|
22191
22432
|
} catch (e) {
|
|
22192
|
-
|
|
22433
|
+
reportHookFailure(eventName, e?.message ?? e);
|
|
22193
22434
|
}
|
|
22194
22435
|
}
|
|
22195
22436
|
|
|
@@ -23016,7 +23257,7 @@ var init_installers = __esm({
|
|
|
23016
23257
|
"use strict";
|
|
23017
23258
|
init_esm_shims();
|
|
23018
23259
|
init_official_skills();
|
|
23019
|
-
OPENCODE_PLUGIN_VERSION =
|
|
23260
|
+
OPENCODE_PLUGIN_VERSION = 7;
|
|
23020
23261
|
AGENT_SKILL_DIRS = {
|
|
23021
23262
|
cursor: { project: path13.join(".cursor", "skills"), global: path13.join(".cursor", "skills") },
|
|
23022
23263
|
windsurf: { project: path13.join(".windsurf", "skills"), global: path13.join(".windsurf", "skills") },
|
|
@@ -23068,7 +23309,7 @@ function buildSetupPlan(options2) {
|
|
|
23068
23309
|
if (wantsPlugin && options2.agent !== "all") {
|
|
23069
23310
|
if (options2.agent === "opencode") {
|
|
23070
23311
|
actions.push("opencode-local-plugin");
|
|
23071
|
-
} else if (PLUGIN_PACKAGE_AGENTS.has(options2.agent)) {
|
|
23312
|
+
} else if (PLUGIN_PACKAGE_AGENTS.has(options2.agent) && options2.global) {
|
|
23072
23313
|
actions.push("plugin-package");
|
|
23073
23314
|
} else if (EXTENSION_PACKAGE_AGENTS.has(options2.agent)) {
|
|
23074
23315
|
actions.push("extension-package");
|
|
@@ -23745,6 +23986,9 @@ async function installAgentSetup(agent, plan, global2) {
|
|
|
23745
23986
|
const hasHermesPlugin = plan.actions.includes("hermes-plugin") && agent === "hermes";
|
|
23746
23987
|
const hasOmpPackage = plan.actions.includes("omp-package") && agent === "omp";
|
|
23747
23988
|
const wantsMcpConfig = plan.mcp !== "none" && agent !== "pi";
|
|
23989
|
+
if (PLUGIN_PACKAGE_AGENTS.has(agent) && plan.includePlugin && !global2) {
|
|
23990
|
+
v3.info(`${agent}: project setup leaves user-level plugins untouched. Run \`memorix setup --agent ${agent} --global\` to install its plugin, skills, and lifecycle hooks.`);
|
|
23991
|
+
}
|
|
23748
23992
|
if (hasPluginPackage) {
|
|
23749
23993
|
const result = await installPluginPackage({
|
|
23750
23994
|
agent,
|
|
@@ -24030,7 +24274,8 @@ var init_setup = __esm({
|
|
|
24030
24274
|
mcp,
|
|
24031
24275
|
hooks: !args.noHooks,
|
|
24032
24276
|
rules: !args.noRules,
|
|
24033
|
-
plugin: !args.noPlugin
|
|
24277
|
+
plugin: !args.noPlugin,
|
|
24278
|
+
global: Boolean(args.global)
|
|
24034
24279
|
});
|
|
24035
24280
|
await installAgentSetup(agent, plan, Boolean(args.global));
|
|
24036
24281
|
}
|
|
@@ -63609,7 +63854,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
63609
63854
|
};
|
|
63610
63855
|
const server = existingServer ?? new McpServer({
|
|
63611
63856
|
name: "memorix",
|
|
63612
|
-
version: true ? "1.1.
|
|
63857
|
+
version: true ? "1.1.12" : "1.0.1"
|
|
63613
63858
|
});
|
|
63614
63859
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
63615
63860
|
server.registerTool = ((name, ...args) => {
|
|
@@ -70349,6 +70594,8 @@ function extractEventName(payload, agent) {
|
|
|
70349
70594
|
return payload.hook_event_name ?? inferCursorEvent(payload);
|
|
70350
70595
|
case "claude":
|
|
70351
70596
|
return payload.hook_event_name ?? "";
|
|
70597
|
+
case "codex":
|
|
70598
|
+
return payload.hook_event_name ?? "";
|
|
70352
70599
|
case "antigravity":
|
|
70353
70600
|
case "gemini-cli":
|
|
70354
70601
|
return payload._memorix_event ?? payload.hook_event_name ?? "";
|
|
@@ -70397,6 +70644,13 @@ function normalizeClaude(payload, event) {
|
|
|
70397
70644
|
if (payload.prompt) {
|
|
70398
70645
|
result.userPrompt = payload.prompt;
|
|
70399
70646
|
}
|
|
70647
|
+
const assistantMessage = firstString(
|
|
70648
|
+
payload.last_assistant_message,
|
|
70649
|
+
payload.assistant_message
|
|
70650
|
+
);
|
|
70651
|
+
if (assistantMessage) {
|
|
70652
|
+
result.aiResponse = assistantMessage;
|
|
70653
|
+
}
|
|
70400
70654
|
return result;
|
|
70401
70655
|
}
|
|
70402
70656
|
function normalizeWindsurf(payload, event) {
|
|
@@ -71213,6 +71467,7 @@ var init_significance_filter = __esm({
|
|
|
71213
71467
|
var handler_exports = {};
|
|
71214
71468
|
__export(handler_exports, {
|
|
71215
71469
|
TYPE_EMOJI: () => TYPE_EMOJI2,
|
|
71470
|
+
formatHookOutput: () => formatHookOutput,
|
|
71216
71471
|
handleHookEvent: () => handleHookEvent,
|
|
71217
71472
|
resetCooldowns: () => resetCooldowns,
|
|
71218
71473
|
runHook: () => runHook
|
|
@@ -71465,6 +71720,38 @@ async function handleHookEvent(input) {
|
|
|
71465
71720
|
output: defaultOutput
|
|
71466
71721
|
};
|
|
71467
71722
|
}
|
|
71723
|
+
function formatHookOutput(agent, rawEventName, output) {
|
|
71724
|
+
if (agent === "codex") {
|
|
71725
|
+
const codexOutput = { continue: output.continue };
|
|
71726
|
+
if (output.stopReason) codexOutput.stopReason = output.stopReason;
|
|
71727
|
+
if (rawEventName === "SessionStart" && output.systemMessage) {
|
|
71728
|
+
codexOutput.hookSpecificOutput = {
|
|
71729
|
+
hookEventName: "SessionStart",
|
|
71730
|
+
additionalContext: output.systemMessage
|
|
71731
|
+
};
|
|
71732
|
+
}
|
|
71733
|
+
return codexOutput;
|
|
71734
|
+
}
|
|
71735
|
+
const finalOutput = { ...output };
|
|
71736
|
+
const hookSpecificOutputEvents = /* @__PURE__ */ new Set([
|
|
71737
|
+
"PreToolUse",
|
|
71738
|
+
"UserPromptSubmit",
|
|
71739
|
+
"PostToolUse",
|
|
71740
|
+
"postToolUse",
|
|
71741
|
+
"preToolUse",
|
|
71742
|
+
"userPromptSubmitted"
|
|
71743
|
+
]);
|
|
71744
|
+
if (rawEventName && hookSpecificOutputEvents.has(rawEventName)) {
|
|
71745
|
+
const hookSpecificOutput = { hookEventName: rawEventName };
|
|
71746
|
+
if (output.systemMessage) {
|
|
71747
|
+
hookSpecificOutput.additionalContext = output.systemMessage;
|
|
71748
|
+
} else if (rawEventName === "UserPromptSubmit") {
|
|
71749
|
+
hookSpecificOutput.additionalContext = "";
|
|
71750
|
+
}
|
|
71751
|
+
finalOutput.hookSpecificOutput = hookSpecificOutput;
|
|
71752
|
+
}
|
|
71753
|
+
return finalOutput;
|
|
71754
|
+
}
|
|
71468
71755
|
async function runHook(agentOverride, eventOverride) {
|
|
71469
71756
|
const rawInput = await new Promise((resolve4) => {
|
|
71470
71757
|
const chunks = [];
|
|
@@ -71597,21 +71884,11 @@ ${emoji2} Memorix saved: ${observation.title} [${observation.type}]`;
|
|
|
71597
71884
|
}
|
|
71598
71885
|
}
|
|
71599
71886
|
const rawEventName = payload._memorix_event ?? payload.hook_event_name ?? payload.hookEventName ?? "";
|
|
71600
|
-
const finalOutput = { ...output };
|
|
71601
71887
|
if (input.agent === "antigravity") {
|
|
71602
71888
|
process.stdout.write(JSON.stringify(toAntigravityHookOutput(rawEventName, output)));
|
|
71603
71889
|
return;
|
|
71604
71890
|
}
|
|
71605
|
-
const
|
|
71606
|
-
if (rawEventName && HSO_EVENTS.has(rawEventName)) {
|
|
71607
|
-
const hso = { hookEventName: rawEventName };
|
|
71608
|
-
if (output.systemMessage) {
|
|
71609
|
-
hso.additionalContext = output.systemMessage;
|
|
71610
|
-
} else if (rawEventName === "UserPromptSubmit") {
|
|
71611
|
-
hso.additionalContext = "";
|
|
71612
|
-
}
|
|
71613
|
-
finalOutput.hookSpecificOutput = hso;
|
|
71614
|
-
}
|
|
71891
|
+
const finalOutput = formatHookOutput(input.agent, rawEventName, output);
|
|
71615
71892
|
process.stdout.write(JSON.stringify(finalOutput));
|
|
71616
71893
|
}
|
|
71617
71894
|
function toAntigravityHookOutput(rawEventName, output) {
|
|
@@ -71770,6 +72047,7 @@ async function installSingleAgent2(agent, cwd, global2) {
|
|
|
71770
72047
|
function getAgentLabel2(agent) {
|
|
71771
72048
|
const labels = {
|
|
71772
72049
|
claude: "Claude Code",
|
|
72050
|
+
codex: "Codex",
|
|
71773
72051
|
windsurf: "Windsurf",
|
|
71774
72052
|
cursor: "Cursor",
|
|
71775
72053
|
copilot: "VS Code Copilot",
|
|
@@ -71798,7 +72076,7 @@ function getAgentHint2(agent) {
|
|
|
71798
72076
|
hermes: "Hermes plugin hooks; use `memorix setup --agent hermes`",
|
|
71799
72077
|
omp: "Oh-my-Pi package hooks; use `memorix setup --agent omp`",
|
|
71800
72078
|
trae: ".trae/rules/project_rules.md (rules only, no hooks system)",
|
|
71801
|
-
codex: "
|
|
72079
|
+
codex: "Codex plugin hooks; use `memorix setup --agent codex`"
|
|
71802
72080
|
};
|
|
71803
72081
|
return hints[agent] || "";
|
|
71804
72082
|
}
|
|
@@ -80450,6 +80728,7 @@ function formatSearchModeLabel(mode) {
|
|
|
80450
80728
|
}
|
|
80451
80729
|
function formatEmbeddingLabel(status, providerName) {
|
|
80452
80730
|
if (status === "disabled") return "Disabled";
|
|
80731
|
+
if (status === "pending") return "On demand";
|
|
80453
80732
|
if (status === "unavailable") return "Unavailable";
|
|
80454
80733
|
if ((providerName || "").startsWith("api-")) return "API ready";
|
|
80455
80734
|
if (providerName) return "Local ready";
|
|
@@ -80519,8 +80798,8 @@ async function getHealthInfo(projectId) {
|
|
|
80519
80798
|
if (isEmbeddingExplicitlyDisabled2()) {
|
|
80520
80799
|
defaults.embeddingProvider = "disabled";
|
|
80521
80800
|
} else {
|
|
80522
|
-
const provider2 = await getEmbeddingProvider2();
|
|
80523
|
-
defaults.embeddingProvider = provider2 ? "ready" : "
|
|
80801
|
+
const provider2 = await getEmbeddingProvider2({ allowNetworkProbe: false });
|
|
80802
|
+
defaults.embeddingProvider = provider2 ? "ready" : "pending";
|
|
80524
80803
|
defaults.embeddingProviderName = provider2?.name;
|
|
80525
80804
|
}
|
|
80526
80805
|
defaults.embeddingLabel = formatEmbeddingLabel(
|
|
@@ -80548,6 +80827,8 @@ async function getHealthInfo(projectId) {
|
|
|
80548
80827
|
defaults.searchDiagnostic = "Vector index ready";
|
|
80549
80828
|
} else if (defaults.embeddingProvider === "ready" && !vectorActive) {
|
|
80550
80829
|
defaults.searchDiagnostic = "Provider ready, no index yet";
|
|
80830
|
+
} else if (defaults.embeddingProvider === "pending") {
|
|
80831
|
+
defaults.searchDiagnostic = "BM25 ready; embeddings initialize on demand";
|
|
80551
80832
|
} else if (defaults.embeddingProvider === "unavailable") {
|
|
80552
80833
|
defaults.searchDiagnostic = "BM25 only (no provider)";
|
|
80553
80834
|
} else {
|
|
@@ -80591,19 +80872,15 @@ async function getRecentMemories(limit = 8, projectId) {
|
|
|
80591
80872
|
}
|
|
80592
80873
|
async function searchMemories(query, limit = 10) {
|
|
80593
80874
|
try {
|
|
80594
|
-
const { searchObservations: searchObservations2
|
|
80875
|
+
const { searchObservations: searchObservations2 } = await Promise.resolve().then(() => (init_orama_store(), orama_store_exports));
|
|
80595
80876
|
const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
80596
80877
|
const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
80597
|
-
const { initObservations: initObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
80598
|
-
const { initObservationStore: initObservationStore2, getObservationStore: getStore } = await Promise.resolve().then(() => (init_obs_store(), obs_store_exports));
|
|
80878
|
+
const { initObservations: initObservations2, prepareSearchIndex: prepareSearchIndex2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
80599
80879
|
const proj = detectProject2(process.cwd());
|
|
80600
80880
|
if (!proj) return [];
|
|
80601
80881
|
const dataDir = await getProjectDataDir2(proj.id);
|
|
80602
|
-
await initObservationStore2(dataDir);
|
|
80603
80882
|
await initObservations2(dataDir);
|
|
80604
|
-
await
|
|
80605
|
-
const allObs = await getStore().loadAll();
|
|
80606
|
-
await hydrateIndex2(allObs);
|
|
80883
|
+
await prepareSearchIndex2();
|
|
80607
80884
|
const results = await searchObservations2({ query, limit, projectId: proj.id });
|
|
80608
80885
|
const typeIcons = {
|
|
80609
80886
|
gotcha: "!",
|