memorix 1.1.11 → 1.1.13
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 +25 -0
- package/README.md +3 -1
- package/README.zh-CN.md +3 -1
- package/dist/cli/index.js +679 -78
- 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 +25 -0
- package/dist/memcode-runtime/package.json +5 -4
- package/dist/sdk.js +289 -44
- package/dist/sdk.js.map +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +2 -2
- package/docs/DEVELOPMENT.md +3 -10
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/SETUP.md +3 -1
- package/docs/dev-log/progress.txt +34 -53
- package/docs/hooks-architecture.md +24 -12
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +2 -1
- package/plugins/codex/memorix/hooks/hooks.json +30 -0
- package/src/cli/commands/agent-integrations.ts +384 -2
- package/src/cli/commands/hooks-install.ts +2 -1
- package/src/cli/commands/setup.ts +20 -2
- 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.13" : 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") },
|
|
@@ -23044,7 +23285,8 @@ __export(setup_exports, {
|
|
|
23044
23285
|
installOmpPackage: () => installOmpPackage,
|
|
23045
23286
|
installOpenClawBundlePackage: () => installOpenClawBundlePackage,
|
|
23046
23287
|
installPiPackage: () => installPiPackage,
|
|
23047
|
-
installPluginPackage: () => installPluginPackage
|
|
23288
|
+
installPluginPackage: () => installPluginPackage,
|
|
23289
|
+
tryInstallCodexPlugin: () => tryInstallCodexPlugin
|
|
23048
23290
|
});
|
|
23049
23291
|
import { spawnSync } from "child_process";
|
|
23050
23292
|
import { existsSync as existsSync9 } from "fs";
|
|
@@ -23068,7 +23310,7 @@ function buildSetupPlan(options2) {
|
|
|
23068
23310
|
if (wantsPlugin && options2.agent !== "all") {
|
|
23069
23311
|
if (options2.agent === "opencode") {
|
|
23070
23312
|
actions.push("opencode-local-plugin");
|
|
23071
|
-
} else if (PLUGIN_PACKAGE_AGENTS.has(options2.agent)) {
|
|
23313
|
+
} else if (PLUGIN_PACKAGE_AGENTS.has(options2.agent) && options2.global) {
|
|
23072
23314
|
actions.push("plugin-package");
|
|
23073
23315
|
} else if (EXTENSION_PACKAGE_AGENTS.has(options2.agent)) {
|
|
23074
23316
|
actions.push("extension-package");
|
|
@@ -23142,6 +23384,16 @@ async function stripHookCaptureFromPlugin(pluginPath, agent) {
|
|
|
23142
23384
|
} catch {
|
|
23143
23385
|
}
|
|
23144
23386
|
}
|
|
23387
|
+
async function stampCodexPluginVersion(pluginPath) {
|
|
23388
|
+
const manifestPath = path14.join(pluginPath, ".codex-plugin", "plugin.json");
|
|
23389
|
+
const manifest = JSON.parse(await readFile5(manifestPath, "utf-8"));
|
|
23390
|
+
if (manifest.name !== "memorix") {
|
|
23391
|
+
throw new Error(`Unexpected Codex plugin manifest at ${manifestPath}`);
|
|
23392
|
+
}
|
|
23393
|
+
manifest.version = getCliVersion();
|
|
23394
|
+
await writeFile5(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
23395
|
+
`, "utf-8");
|
|
23396
|
+
}
|
|
23145
23397
|
async function stripHookCaptureFromOpenClawBundle(bundlePath) {
|
|
23146
23398
|
await rm(path14.join(bundlePath, "hooks"), { recursive: true, force: true });
|
|
23147
23399
|
const manifestPath = path14.join(bundlePath, ".codex-plugin", "plugin.json");
|
|
@@ -23406,6 +23658,7 @@ async function installPluginPackage(options2) {
|
|
|
23406
23658
|
const pluginPath2 = path14.join(home, ".codex", "plugins", "memorix");
|
|
23407
23659
|
const marketplacePath2 = path14.join(home, ".agents", "plugins", "marketplace.json");
|
|
23408
23660
|
await copyDir(source, pluginPath2);
|
|
23661
|
+
await stampCodexPluginVersion(pluginPath2);
|
|
23409
23662
|
if (!includeHooks) await stripHookCaptureFromPlugin(pluginPath2, "codex");
|
|
23410
23663
|
await writeOfficialSkills(path14.join(pluginPath2, "skills"));
|
|
23411
23664
|
await upsertCodexMarketplace(marketplacePath2, pluginPath2);
|
|
@@ -23745,6 +23998,9 @@ async function installAgentSetup(agent, plan, global2) {
|
|
|
23745
23998
|
const hasHermesPlugin = plan.actions.includes("hermes-plugin") && agent === "hermes";
|
|
23746
23999
|
const hasOmpPackage = plan.actions.includes("omp-package") && agent === "omp";
|
|
23747
24000
|
const wantsMcpConfig = plan.mcp !== "none" && agent !== "pi";
|
|
24001
|
+
if (PLUGIN_PACKAGE_AGENTS.has(agent) && plan.includePlugin && !global2) {
|
|
24002
|
+
v3.info(`${agent}: project setup leaves user-level plugins untouched. Run \`memorix setup --agent ${agent} --global\` to install its plugin, skills, and lifecycle hooks.`);
|
|
24003
|
+
}
|
|
23748
24004
|
if (hasPluginPackage) {
|
|
23749
24005
|
const result = await installPluginPackage({
|
|
23750
24006
|
agent,
|
|
@@ -24030,7 +24286,8 @@ var init_setup = __esm({
|
|
|
24030
24286
|
mcp,
|
|
24031
24287
|
hooks: !args.noHooks,
|
|
24032
24288
|
rules: !args.noRules,
|
|
24033
|
-
plugin: !args.noPlugin
|
|
24289
|
+
plugin: !args.noPlugin,
|
|
24290
|
+
global: Boolean(args.global)
|
|
24034
24291
|
});
|
|
24035
24292
|
await installAgentSetup(agent, plan, Boolean(args.global));
|
|
24036
24293
|
}
|
|
@@ -63609,7 +63866,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
63609
63866
|
};
|
|
63610
63867
|
const server = existingServer ?? new McpServer({
|
|
63611
63868
|
name: "memorix",
|
|
63612
|
-
version: true ? "1.1.
|
|
63869
|
+
version: true ? "1.1.13" : "1.0.1"
|
|
63613
63870
|
});
|
|
63614
63871
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
63615
63872
|
server.registerTool = ((name, ...args) => {
|
|
@@ -70349,6 +70606,8 @@ function extractEventName(payload, agent) {
|
|
|
70349
70606
|
return payload.hook_event_name ?? inferCursorEvent(payload);
|
|
70350
70607
|
case "claude":
|
|
70351
70608
|
return payload.hook_event_name ?? "";
|
|
70609
|
+
case "codex":
|
|
70610
|
+
return payload.hook_event_name ?? "";
|
|
70352
70611
|
case "antigravity":
|
|
70353
70612
|
case "gemini-cli":
|
|
70354
70613
|
return payload._memorix_event ?? payload.hook_event_name ?? "";
|
|
@@ -70397,6 +70656,13 @@ function normalizeClaude(payload, event) {
|
|
|
70397
70656
|
if (payload.prompt) {
|
|
70398
70657
|
result.userPrompt = payload.prompt;
|
|
70399
70658
|
}
|
|
70659
|
+
const assistantMessage = firstString(
|
|
70660
|
+
payload.last_assistant_message,
|
|
70661
|
+
payload.assistant_message
|
|
70662
|
+
);
|
|
70663
|
+
if (assistantMessage) {
|
|
70664
|
+
result.aiResponse = assistantMessage;
|
|
70665
|
+
}
|
|
70400
70666
|
return result;
|
|
70401
70667
|
}
|
|
70402
70668
|
function normalizeWindsurf(payload, event) {
|
|
@@ -71213,6 +71479,7 @@ var init_significance_filter = __esm({
|
|
|
71213
71479
|
var handler_exports = {};
|
|
71214
71480
|
__export(handler_exports, {
|
|
71215
71481
|
TYPE_EMOJI: () => TYPE_EMOJI2,
|
|
71482
|
+
formatHookOutput: () => formatHookOutput,
|
|
71216
71483
|
handleHookEvent: () => handleHookEvent,
|
|
71217
71484
|
resetCooldowns: () => resetCooldowns,
|
|
71218
71485
|
runHook: () => runHook
|
|
@@ -71465,6 +71732,38 @@ async function handleHookEvent(input) {
|
|
|
71465
71732
|
output: defaultOutput
|
|
71466
71733
|
};
|
|
71467
71734
|
}
|
|
71735
|
+
function formatHookOutput(agent, rawEventName, output) {
|
|
71736
|
+
if (agent === "codex") {
|
|
71737
|
+
const codexOutput = { continue: output.continue };
|
|
71738
|
+
if (output.stopReason) codexOutput.stopReason = output.stopReason;
|
|
71739
|
+
if (rawEventName === "SessionStart" && output.systemMessage) {
|
|
71740
|
+
codexOutput.hookSpecificOutput = {
|
|
71741
|
+
hookEventName: "SessionStart",
|
|
71742
|
+
additionalContext: output.systemMessage
|
|
71743
|
+
};
|
|
71744
|
+
}
|
|
71745
|
+
return codexOutput;
|
|
71746
|
+
}
|
|
71747
|
+
const finalOutput = { ...output };
|
|
71748
|
+
const hookSpecificOutputEvents = /* @__PURE__ */ new Set([
|
|
71749
|
+
"PreToolUse",
|
|
71750
|
+
"UserPromptSubmit",
|
|
71751
|
+
"PostToolUse",
|
|
71752
|
+
"postToolUse",
|
|
71753
|
+
"preToolUse",
|
|
71754
|
+
"userPromptSubmitted"
|
|
71755
|
+
]);
|
|
71756
|
+
if (rawEventName && hookSpecificOutputEvents.has(rawEventName)) {
|
|
71757
|
+
const hookSpecificOutput = { hookEventName: rawEventName };
|
|
71758
|
+
if (output.systemMessage) {
|
|
71759
|
+
hookSpecificOutput.additionalContext = output.systemMessage;
|
|
71760
|
+
} else if (rawEventName === "UserPromptSubmit") {
|
|
71761
|
+
hookSpecificOutput.additionalContext = "";
|
|
71762
|
+
}
|
|
71763
|
+
finalOutput.hookSpecificOutput = hookSpecificOutput;
|
|
71764
|
+
}
|
|
71765
|
+
return finalOutput;
|
|
71766
|
+
}
|
|
71468
71767
|
async function runHook(agentOverride, eventOverride) {
|
|
71469
71768
|
const rawInput = await new Promise((resolve4) => {
|
|
71470
71769
|
const chunks = [];
|
|
@@ -71597,21 +71896,11 @@ ${emoji2} Memorix saved: ${observation.title} [${observation.type}]`;
|
|
|
71597
71896
|
}
|
|
71598
71897
|
}
|
|
71599
71898
|
const rawEventName = payload._memorix_event ?? payload.hook_event_name ?? payload.hookEventName ?? "";
|
|
71600
|
-
const finalOutput = { ...output };
|
|
71601
71899
|
if (input.agent === "antigravity") {
|
|
71602
71900
|
process.stdout.write(JSON.stringify(toAntigravityHookOutput(rawEventName, output)));
|
|
71603
71901
|
return;
|
|
71604
71902
|
}
|
|
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
|
-
}
|
|
71903
|
+
const finalOutput = formatHookOutput(input.agent, rawEventName, output);
|
|
71615
71904
|
process.stdout.write(JSON.stringify(finalOutput));
|
|
71616
71905
|
}
|
|
71617
71906
|
function toAntigravityHookOutput(rawEventName, output) {
|
|
@@ -71770,6 +72059,7 @@ async function installSingleAgent2(agent, cwd, global2) {
|
|
|
71770
72059
|
function getAgentLabel2(agent) {
|
|
71771
72060
|
const labels = {
|
|
71772
72061
|
claude: "Claude Code",
|
|
72062
|
+
codex: "Codex",
|
|
71773
72063
|
windsurf: "Windsurf",
|
|
71774
72064
|
cursor: "Cursor",
|
|
71775
72065
|
copilot: "VS Code Copilot",
|
|
@@ -71798,7 +72088,7 @@ function getAgentHint2(agent) {
|
|
|
71798
72088
|
hermes: "Hermes plugin hooks; use `memorix setup --agent hermes`",
|
|
71799
72089
|
omp: "Oh-my-Pi package hooks; use `memorix setup --agent omp`",
|
|
71800
72090
|
trae: ".trae/rules/project_rules.md (rules only, no hooks system)",
|
|
71801
|
-
codex: "
|
|
72091
|
+
codex: "Codex plugin hooks; use `memorix setup --agent codex`"
|
|
71802
72092
|
};
|
|
71803
72093
|
return hints[agent] || "";
|
|
71804
72094
|
}
|
|
@@ -73630,8 +73920,10 @@ __export(agent_integrations_exports, {
|
|
|
73630
73920
|
formatAgentIntegrationReport: () => formatAgentIntegrationReport,
|
|
73631
73921
|
formatAgentRepairResult: () => formatAgentRepairResult,
|
|
73632
73922
|
inspectAgentIntegrations: () => inspectAgentIntegrations,
|
|
73923
|
+
parseCodexPluginList: () => parseCodexPluginList,
|
|
73633
73924
|
repairAgentIntegrations: () => repairAgentIntegrations
|
|
73634
73925
|
});
|
|
73926
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
73635
73927
|
import { existsSync as existsSync23 } from "fs";
|
|
73636
73928
|
import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
|
|
73637
73929
|
import { basename as basename3, dirname as dirname7, resolve as resolve2 } from "path";
|
|
@@ -73709,6 +74001,275 @@ function aggregateGuidanceIssues(checks) {
|
|
|
73709
74001
|
function asRecord2(value) {
|
|
73710
74002
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
73711
74003
|
}
|
|
74004
|
+
function asRecordArray(value) {
|
|
74005
|
+
return Array.isArray(value) ? value.map(asRecord2).filter((entry) => entry !== null) : [];
|
|
74006
|
+
}
|
|
74007
|
+
function codexPluginPath() {
|
|
74008
|
+
return `${homedir32()}/.codex/plugins/${CODEX_PLUGIN_NAME}`;
|
|
74009
|
+
}
|
|
74010
|
+
function codexMarketplacePath() {
|
|
74011
|
+
return `${homedir32()}/.agents/plugins/marketplace.json`;
|
|
74012
|
+
}
|
|
74013
|
+
function codexConfigPath() {
|
|
74014
|
+
return `${homedir32()}/.codex/config.toml`;
|
|
74015
|
+
}
|
|
74016
|
+
function normalizeMarketplacePath(value) {
|
|
74017
|
+
return value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
74018
|
+
}
|
|
74019
|
+
function isMemorixCodexPlugin(value) {
|
|
74020
|
+
return value.pluginId === CODEX_PLUGIN_ID || value.name === CODEX_PLUGIN_NAME && value.marketplaceName === CODEX_PLUGIN_MARKETPLACE;
|
|
74021
|
+
}
|
|
74022
|
+
function parseCodexPluginList(output) {
|
|
74023
|
+
try {
|
|
74024
|
+
const parsed = asRecord2(JSON.parse(output));
|
|
74025
|
+
if (!parsed) return null;
|
|
74026
|
+
const entries = [...asRecordArray(parsed.installed), ...asRecordArray(parsed.available)];
|
|
74027
|
+
const plugin = entries.find(isMemorixCodexPlugin);
|
|
74028
|
+
if (!plugin) return { installed: false, enabled: false };
|
|
74029
|
+
return {
|
|
74030
|
+
installed: plugin.installed === true,
|
|
74031
|
+
enabled: plugin.enabled === true,
|
|
74032
|
+
...typeof plugin.version === "string" ? { version: plugin.version } : {}
|
|
74033
|
+
};
|
|
74034
|
+
} catch {
|
|
74035
|
+
return null;
|
|
74036
|
+
}
|
|
74037
|
+
}
|
|
74038
|
+
async function inspectCodexPluginBundle() {
|
|
74039
|
+
const pluginPath = codexPluginPath();
|
|
74040
|
+
const manifestPath = `${pluginPath}/.codex-plugin/plugin.json`;
|
|
74041
|
+
const hooksPath = `${pluginPath}/hooks/hooks.json`;
|
|
74042
|
+
if (!existsSync23(pluginPath)) {
|
|
74043
|
+
return {
|
|
74044
|
+
scope: "global",
|
|
74045
|
+
kind: "bundle",
|
|
74046
|
+
path: pluginPath,
|
|
74047
|
+
exists: false,
|
|
74048
|
+
status: "missing",
|
|
74049
|
+
issues: ["codex-plugin-bundle-missing"]
|
|
74050
|
+
};
|
|
74051
|
+
}
|
|
74052
|
+
if (!existsSync23(manifestPath)) {
|
|
74053
|
+
return {
|
|
74054
|
+
scope: "global",
|
|
74055
|
+
kind: "bundle",
|
|
74056
|
+
path: manifestPath,
|
|
74057
|
+
exists: false,
|
|
74058
|
+
status: "repairable",
|
|
74059
|
+
issues: ["codex-plugin-manifest-missing"]
|
|
74060
|
+
};
|
|
74061
|
+
}
|
|
74062
|
+
let manifest = null;
|
|
74063
|
+
try {
|
|
74064
|
+
manifest = asRecord2(JSON.parse(await readFile7(manifestPath, "utf-8")));
|
|
74065
|
+
} catch {
|
|
74066
|
+
return {
|
|
74067
|
+
scope: "global",
|
|
74068
|
+
kind: "bundle",
|
|
74069
|
+
path: manifestPath,
|
|
74070
|
+
exists: true,
|
|
74071
|
+
status: "repairable",
|
|
74072
|
+
issues: ["codex-plugin-manifest-unreadable"]
|
|
74073
|
+
};
|
|
74074
|
+
}
|
|
74075
|
+
if (!manifest || manifest.name !== CODEX_PLUGIN_NAME) {
|
|
74076
|
+
return {
|
|
74077
|
+
scope: "global",
|
|
74078
|
+
kind: "bundle",
|
|
74079
|
+
path: manifestPath,
|
|
74080
|
+
exists: true,
|
|
74081
|
+
status: "repairable",
|
|
74082
|
+
issues: ["codex-plugin-manifest-invalid"]
|
|
74083
|
+
};
|
|
74084
|
+
}
|
|
74085
|
+
const version2 = typeof manifest.version === "string" ? manifest.version : void 0;
|
|
74086
|
+
const issues = [];
|
|
74087
|
+
if (version2 !== getCliVersion()) issues.push("codex-plugin-version-mismatch");
|
|
74088
|
+
if (manifest.hooks !== "./hooks/hooks.json") issues.push("codex-hook-manifest-missing");
|
|
74089
|
+
let declared = [];
|
|
74090
|
+
if (!existsSync23(hooksPath)) {
|
|
74091
|
+
issues.push("codex-hook-manifest-missing");
|
|
74092
|
+
} else {
|
|
74093
|
+
try {
|
|
74094
|
+
const hooksConfig = asRecord2(JSON.parse(await readFile7(hooksPath, "utf-8")));
|
|
74095
|
+
const hooks = asRecord2(hooksConfig?.hooks);
|
|
74096
|
+
declared = hooks ? Object.keys(hooks) : [];
|
|
74097
|
+
if (CODEX_HOOK_EVENTS.some((event) => !declared.includes(event))) {
|
|
74098
|
+
issues.push("codex-hook-events-missing");
|
|
74099
|
+
}
|
|
74100
|
+
} catch {
|
|
74101
|
+
issues.push("codex-hook-manifest-unreadable");
|
|
74102
|
+
}
|
|
74103
|
+
}
|
|
74104
|
+
return {
|
|
74105
|
+
scope: "global",
|
|
74106
|
+
kind: "bundle",
|
|
74107
|
+
path: pluginPath,
|
|
74108
|
+
exists: true,
|
|
74109
|
+
status: issues.length > 0 ? "repairable" : "ok",
|
|
74110
|
+
issues: unique(issues),
|
|
74111
|
+
...version2 ? { version: version2 } : {},
|
|
74112
|
+
hooks: { declared, expected: [...CODEX_HOOK_EVENTS] }
|
|
74113
|
+
};
|
|
74114
|
+
}
|
|
74115
|
+
async function inspectCodexMarketplace() {
|
|
74116
|
+
const marketplacePath = codexMarketplacePath();
|
|
74117
|
+
if (!existsSync23(marketplacePath)) {
|
|
74118
|
+
return {
|
|
74119
|
+
scope: "global",
|
|
74120
|
+
kind: "marketplace",
|
|
74121
|
+
path: marketplacePath,
|
|
74122
|
+
exists: false,
|
|
74123
|
+
status: "missing",
|
|
74124
|
+
issues: ["codex-marketplace-missing"]
|
|
74125
|
+
};
|
|
74126
|
+
}
|
|
74127
|
+
let catalog = null;
|
|
74128
|
+
try {
|
|
74129
|
+
catalog = asRecord2(JSON.parse(await readFile7(marketplacePath, "utf-8")));
|
|
74130
|
+
} catch {
|
|
74131
|
+
return {
|
|
74132
|
+
scope: "global",
|
|
74133
|
+
kind: "marketplace",
|
|
74134
|
+
path: marketplacePath,
|
|
74135
|
+
exists: true,
|
|
74136
|
+
status: "repairable",
|
|
74137
|
+
issues: ["codex-marketplace-unreadable"]
|
|
74138
|
+
};
|
|
74139
|
+
}
|
|
74140
|
+
const entry = asRecordArray(catalog?.plugins).find((plugin) => plugin.name === CODEX_PLUGIN_NAME);
|
|
74141
|
+
if (!entry) {
|
|
74142
|
+
return {
|
|
74143
|
+
scope: "global",
|
|
74144
|
+
kind: "marketplace",
|
|
74145
|
+
path: marketplacePath,
|
|
74146
|
+
exists: true,
|
|
74147
|
+
status: "repairable",
|
|
74148
|
+
issues: ["codex-marketplace-entry-missing"]
|
|
74149
|
+
};
|
|
74150
|
+
}
|
|
74151
|
+
const source = asRecord2(entry.source);
|
|
74152
|
+
const sourcePath = typeof source?.path === "string" ? source.path : "";
|
|
74153
|
+
const issues = source?.source === "local" && normalizeMarketplacePath(sourcePath) === ".codex/plugins/memorix" ? [] : ["codex-marketplace-entry-stale"];
|
|
74154
|
+
return {
|
|
74155
|
+
scope: "global",
|
|
74156
|
+
kind: "marketplace",
|
|
74157
|
+
path: marketplacePath,
|
|
74158
|
+
exists: true,
|
|
74159
|
+
status: issues.length > 0 ? "repairable" : "ok",
|
|
74160
|
+
issues
|
|
74161
|
+
};
|
|
74162
|
+
}
|
|
74163
|
+
function inspectCodexPluginRuntime() {
|
|
74164
|
+
const command = "codex plugin list --marketplace personal --available --json";
|
|
74165
|
+
const result = spawnSync2("codex", ["plugin", "list", "--marketplace", CODEX_PLUGIN_MARKETPLACE, "--available", "--json"], {
|
|
74166
|
+
encoding: "utf-8",
|
|
74167
|
+
stdio: "pipe",
|
|
74168
|
+
shell: process.platform === "win32"
|
|
74169
|
+
});
|
|
74170
|
+
if (result.error || result.status !== 0) {
|
|
74171
|
+
return {
|
|
74172
|
+
scope: "global",
|
|
74173
|
+
kind: "runtime",
|
|
74174
|
+
path: command,
|
|
74175
|
+
exists: false,
|
|
74176
|
+
status: "skipped",
|
|
74177
|
+
issues: ["codex-plugin-runtime-unavailable"]
|
|
74178
|
+
};
|
|
74179
|
+
}
|
|
74180
|
+
const runtime = parseCodexPluginList(String(result.stdout ?? ""));
|
|
74181
|
+
if (!runtime) {
|
|
74182
|
+
return {
|
|
74183
|
+
scope: "global",
|
|
74184
|
+
kind: "runtime",
|
|
74185
|
+
path: command,
|
|
74186
|
+
exists: true,
|
|
74187
|
+
status: "skipped",
|
|
74188
|
+
issues: ["codex-plugin-runtime-unreadable"]
|
|
74189
|
+
};
|
|
74190
|
+
}
|
|
74191
|
+
const issues = [];
|
|
74192
|
+
if (!runtime.installed) issues.push("codex-plugin-not-installed");
|
|
74193
|
+
else if (!runtime.enabled) issues.push("codex-plugin-disabled");
|
|
74194
|
+
return {
|
|
74195
|
+
scope: "global",
|
|
74196
|
+
kind: "runtime",
|
|
74197
|
+
path: command,
|
|
74198
|
+
exists: true,
|
|
74199
|
+
status: issues.length > 0 ? "repairable" : "ok",
|
|
74200
|
+
issues,
|
|
74201
|
+
runtime
|
|
74202
|
+
};
|
|
74203
|
+
}
|
|
74204
|
+
async function inspectCodexHookTrust() {
|
|
74205
|
+
const configPath = codexConfigPath();
|
|
74206
|
+
if (!existsSync23(configPath)) {
|
|
74207
|
+
return {
|
|
74208
|
+
scope: "global",
|
|
74209
|
+
kind: "hook-trust",
|
|
74210
|
+
path: configPath,
|
|
74211
|
+
exists: false,
|
|
74212
|
+
status: "skipped",
|
|
74213
|
+
issues: ["codex-hook-trust-unavailable"]
|
|
74214
|
+
};
|
|
74215
|
+
}
|
|
74216
|
+
let config2 = "";
|
|
74217
|
+
try {
|
|
74218
|
+
config2 = await readFile7(configPath, "utf-8");
|
|
74219
|
+
} catch {
|
|
74220
|
+
return {
|
|
74221
|
+
scope: "global",
|
|
74222
|
+
kind: "hook-trust",
|
|
74223
|
+
path: configPath,
|
|
74224
|
+
exists: true,
|
|
74225
|
+
status: "skipped",
|
|
74226
|
+
issues: ["codex-hook-trust-unreadable"]
|
|
74227
|
+
};
|
|
74228
|
+
}
|
|
74229
|
+
const trusted = CODEX_HOOK_STATE_NAMES.filter(
|
|
74230
|
+
(event) => config2.includes(`[hooks.state."${CODEX_PLUGIN_ID}:hooks/hooks.json:${event}:`)
|
|
74231
|
+
);
|
|
74232
|
+
const issues = trusted.length === CODEX_HOOK_STATE_NAMES.length ? [] : ["codex-hook-trust-pending"];
|
|
74233
|
+
return {
|
|
74234
|
+
scope: "global",
|
|
74235
|
+
kind: "hook-trust",
|
|
74236
|
+
path: configPath,
|
|
74237
|
+
exists: true,
|
|
74238
|
+
status: issues.length > 0 ? "repairable" : "ok",
|
|
74239
|
+
issues,
|
|
74240
|
+
hookTrust: { trusted, expected: [...CODEX_HOOK_STATE_NAMES] }
|
|
74241
|
+
};
|
|
74242
|
+
}
|
|
74243
|
+
function aggregatePluginStatus(checks) {
|
|
74244
|
+
if (checks.length === 0) return "skipped";
|
|
74245
|
+
return worstStatus(checks.map((check2) => check2.status));
|
|
74246
|
+
}
|
|
74247
|
+
function aggregatePluginIssues(checks) {
|
|
74248
|
+
const status = aggregatePluginStatus(checks);
|
|
74249
|
+
if (status === "ok") {
|
|
74250
|
+
return unique(checks.filter((check2) => check2.status === "skipped").flatMap((check2) => check2.issues));
|
|
74251
|
+
}
|
|
74252
|
+
if (status === "repairable") {
|
|
74253
|
+
return unique(checks.filter((check2) => check2.status === "repairable" || check2.status === "missing").flatMap((check2) => check2.issues));
|
|
74254
|
+
}
|
|
74255
|
+
return unique(checks.filter((check2) => check2.status === status).flatMap((check2) => check2.issues));
|
|
74256
|
+
}
|
|
74257
|
+
async function inspectPlugin(agent, scope) {
|
|
74258
|
+
if (agent !== "codex" || scope === "local" || scope === "project") {
|
|
74259
|
+
return { status: "skipped", issues: [], checks: [] };
|
|
74260
|
+
}
|
|
74261
|
+
const checks = [
|
|
74262
|
+
await inspectCodexPluginBundle(),
|
|
74263
|
+
await inspectCodexMarketplace(),
|
|
74264
|
+
inspectCodexPluginRuntime(),
|
|
74265
|
+
await inspectCodexHookTrust()
|
|
74266
|
+
];
|
|
74267
|
+
return {
|
|
74268
|
+
status: aggregatePluginStatus(checks),
|
|
74269
|
+
issues: aggregatePluginIssues(checks),
|
|
74270
|
+
checks
|
|
74271
|
+
};
|
|
74272
|
+
}
|
|
73712
74273
|
function looksLikeStaleMemorixCommand(server) {
|
|
73713
74274
|
const text = [server.command, ...server.args ?? []].join(" ");
|
|
73714
74275
|
return /[\\/]\.worktrees[\\/]/i.test(text) || /[\\/]dist[\\/]cli[\\/]index\.js/i.test(text);
|
|
@@ -73977,10 +74538,11 @@ async function inspectAgentIntegrations(options2 = {}) {
|
|
|
73977
74538
|
entries.push({
|
|
73978
74539
|
agent,
|
|
73979
74540
|
mcp: await inspectMcp(agent, projectRoot, scope),
|
|
73980
|
-
guidance: await inspectGuidance(agent, projectRoot, scope)
|
|
74541
|
+
guidance: await inspectGuidance(agent, projectRoot, scope),
|
|
74542
|
+
plugin: await inspectPlugin(agent, scope)
|
|
73981
74543
|
});
|
|
73982
74544
|
}
|
|
73983
|
-
const entryStatuses = entries.map((entry) => worstStatus([entry.mcp.status, entry.guidance.status]));
|
|
74545
|
+
const entryStatuses = entries.map((entry) => worstStatus([entry.mcp.status, entry.guidance.status, entry.plugin.status]));
|
|
73984
74546
|
return {
|
|
73985
74547
|
projectRoot,
|
|
73986
74548
|
scope,
|
|
@@ -74002,10 +74564,11 @@ function formatAgentIntegrationReport(report) {
|
|
|
74002
74564
|
""
|
|
74003
74565
|
];
|
|
74004
74566
|
for (const entry of report.entries) {
|
|
74005
|
-
const status = worstStatus([entry.mcp.status, entry.guidance.status]);
|
|
74567
|
+
const status = worstStatus([entry.mcp.status, entry.guidance.status, entry.plugin.status]);
|
|
74006
74568
|
lines.push(`${entry.agent}: ${status}`);
|
|
74007
74569
|
if (entry.mcp.issues.length > 0) lines.push(` MCP: ${entry.mcp.issues.join(", ")}`);
|
|
74008
74570
|
if (entry.guidance.issues.length > 0) lines.push(` Guidance: ${entry.guidance.issues.join(", ")}`);
|
|
74571
|
+
if (entry.plugin.issues.length > 0) lines.push(` Plugin: ${entry.plugin.issues.join(", ")}`);
|
|
74009
74572
|
}
|
|
74010
74573
|
lines.push("");
|
|
74011
74574
|
lines.push(`Repair: ${report.repairCommand}`);
|
|
@@ -74058,6 +74621,39 @@ async function repairAgentIntegrations(options2 = {}) {
|
|
|
74058
74621
|
} else {
|
|
74059
74622
|
skipped.push(`${entry.agent}:guidance`);
|
|
74060
74623
|
}
|
|
74624
|
+
if (entry.agent === "codex" && entry.plugin.status !== "ok" && entry.plugin.status !== "skipped") {
|
|
74625
|
+
const bundleOrMarketplaceNeedsRepair = entry.plugin.checks.some(
|
|
74626
|
+
(check2) => (check2.kind === "bundle" || check2.kind === "marketplace") && check2.status !== "ok"
|
|
74627
|
+
);
|
|
74628
|
+
const runtime = entry.plugin.checks.find((check2) => check2.kind === "runtime");
|
|
74629
|
+
const hookTrust = entry.plugin.checks.find((check2) => check2.kind === "hook-trust");
|
|
74630
|
+
const needsInstall = runtime?.runtime?.installed === false;
|
|
74631
|
+
const needsManualEnable = runtime?.runtime?.installed === true && runtime.runtime.enabled === false;
|
|
74632
|
+
const needsHookTrust = hookTrust?.status === "repairable";
|
|
74633
|
+
const missingPluginFiles = entry.plugin.checks.some(
|
|
74634
|
+
(check2) => (check2.kind === "bundle" || check2.kind === "marketplace") && check2.status === "missing"
|
|
74635
|
+
);
|
|
74636
|
+
if (needsManualEnable) {
|
|
74637
|
+
skipped.push("codex:plugin:global:enable-in-plugin-browser");
|
|
74638
|
+
}
|
|
74639
|
+
if (needsHookTrust) {
|
|
74640
|
+
skipped.push("codex:plugin:global:review-hooks");
|
|
74641
|
+
}
|
|
74642
|
+
if (bundleOrMarketplaceNeedsRepair || needsInstall) {
|
|
74643
|
+
if ((missingPluginFiles || needsInstall) && !canInstallMissing) {
|
|
74644
|
+
skipped.push("codex:plugin:global:missing");
|
|
74645
|
+
} else {
|
|
74646
|
+
if (!options2.dry) {
|
|
74647
|
+
await installPluginPackage({ agent: "codex" });
|
|
74648
|
+
if (needsInstall) {
|
|
74649
|
+
const install = tryInstallCodexPlugin();
|
|
74650
|
+
if (!install.ok) skipped.push("codex:plugin:global:install-pending");
|
|
74651
|
+
}
|
|
74652
|
+
}
|
|
74653
|
+
changed.push("codex:plugin:global");
|
|
74654
|
+
}
|
|
74655
|
+
}
|
|
74656
|
+
}
|
|
74061
74657
|
}
|
|
74062
74658
|
return {
|
|
74063
74659
|
projectRoot,
|
|
@@ -74088,13 +74684,14 @@ function formatAgentRepairResult(result) {
|
|
|
74088
74684
|
}
|
|
74089
74685
|
return lines.join("\n");
|
|
74090
74686
|
}
|
|
74091
|
-
var GUIDANCE_AGENTS;
|
|
74687
|
+
var GUIDANCE_AGENTS, CODEX_PLUGIN_NAME, CODEX_PLUGIN_MARKETPLACE, CODEX_PLUGIN_ID, CODEX_HOOK_EVENTS, CODEX_HOOK_STATE_NAMES;
|
|
74092
74688
|
var init_agent_integrations = __esm({
|
|
74093
74689
|
"src/cli/commands/agent-integrations.ts"() {
|
|
74094
74690
|
"use strict";
|
|
74095
74691
|
init_esm_shims();
|
|
74096
74692
|
init_installers();
|
|
74097
74693
|
init_setup();
|
|
74694
|
+
init_version();
|
|
74098
74695
|
GUIDANCE_AGENTS = /* @__PURE__ */ new Set([
|
|
74099
74696
|
"claude",
|
|
74100
74697
|
"codex",
|
|
@@ -74107,6 +74704,11 @@ var init_agent_integrations = __esm({
|
|
|
74107
74704
|
"opencode",
|
|
74108
74705
|
"trae"
|
|
74109
74706
|
]);
|
|
74707
|
+
CODEX_PLUGIN_NAME = "memorix";
|
|
74708
|
+
CODEX_PLUGIN_MARKETPLACE = "personal";
|
|
74709
|
+
CODEX_PLUGIN_ID = `${CODEX_PLUGIN_NAME}@${CODEX_PLUGIN_MARKETPLACE}`;
|
|
74710
|
+
CODEX_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PostToolUse", "PreCompact", "Stop"];
|
|
74711
|
+
CODEX_HOOK_STATE_NAMES = ["session_start", "user_prompt_submit", "post_tool_use", "pre_compact", "stop"];
|
|
74110
74712
|
}
|
|
74111
74713
|
});
|
|
74112
74714
|
|
|
@@ -80450,6 +81052,7 @@ function formatSearchModeLabel(mode) {
|
|
|
80450
81052
|
}
|
|
80451
81053
|
function formatEmbeddingLabel(status, providerName) {
|
|
80452
81054
|
if (status === "disabled") return "Disabled";
|
|
81055
|
+
if (status === "pending") return "On demand";
|
|
80453
81056
|
if (status === "unavailable") return "Unavailable";
|
|
80454
81057
|
if ((providerName || "").startsWith("api-")) return "API ready";
|
|
80455
81058
|
if (providerName) return "Local ready";
|
|
@@ -80519,8 +81122,8 @@ async function getHealthInfo(projectId) {
|
|
|
80519
81122
|
if (isEmbeddingExplicitlyDisabled2()) {
|
|
80520
81123
|
defaults.embeddingProvider = "disabled";
|
|
80521
81124
|
} else {
|
|
80522
|
-
const provider2 = await getEmbeddingProvider2();
|
|
80523
|
-
defaults.embeddingProvider = provider2 ? "ready" : "
|
|
81125
|
+
const provider2 = await getEmbeddingProvider2({ allowNetworkProbe: false });
|
|
81126
|
+
defaults.embeddingProvider = provider2 ? "ready" : "pending";
|
|
80524
81127
|
defaults.embeddingProviderName = provider2?.name;
|
|
80525
81128
|
}
|
|
80526
81129
|
defaults.embeddingLabel = formatEmbeddingLabel(
|
|
@@ -80548,6 +81151,8 @@ async function getHealthInfo(projectId) {
|
|
|
80548
81151
|
defaults.searchDiagnostic = "Vector index ready";
|
|
80549
81152
|
} else if (defaults.embeddingProvider === "ready" && !vectorActive) {
|
|
80550
81153
|
defaults.searchDiagnostic = "Provider ready, no index yet";
|
|
81154
|
+
} else if (defaults.embeddingProvider === "pending") {
|
|
81155
|
+
defaults.searchDiagnostic = "BM25 ready; embeddings initialize on demand";
|
|
80551
81156
|
} else if (defaults.embeddingProvider === "unavailable") {
|
|
80552
81157
|
defaults.searchDiagnostic = "BM25 only (no provider)";
|
|
80553
81158
|
} else {
|
|
@@ -80591,19 +81196,15 @@ async function getRecentMemories(limit = 8, projectId) {
|
|
|
80591
81196
|
}
|
|
80592
81197
|
async function searchMemories(query, limit = 10) {
|
|
80593
81198
|
try {
|
|
80594
|
-
const { searchObservations: searchObservations2
|
|
81199
|
+
const { searchObservations: searchObservations2 } = await Promise.resolve().then(() => (init_orama_store(), orama_store_exports));
|
|
80595
81200
|
const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
80596
81201
|
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));
|
|
81202
|
+
const { initObservations: initObservations2, prepareSearchIndex: prepareSearchIndex2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
80599
81203
|
const proj = detectProject2(process.cwd());
|
|
80600
81204
|
if (!proj) return [];
|
|
80601
81205
|
const dataDir = await getProjectDataDir2(proj.id);
|
|
80602
|
-
await initObservationStore2(dataDir);
|
|
80603
81206
|
await initObservations2(dataDir);
|
|
80604
|
-
await
|
|
80605
|
-
const allObs = await getStore().loadAll();
|
|
80606
|
-
await hydrateIndex2(allObs);
|
|
81207
|
+
await prepareSearchIndex2();
|
|
80607
81208
|
const results = await searchObservations2({ query, limit, projectId: proj.id });
|
|
80608
81209
|
const typeIcons = {
|
|
80609
81210
|
gotcha: "!",
|