memorix 1.6.1 → 1.6.2
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 +22 -0
- package/TEAM.md +86 -86
- package/dist/cli/index.js +1574 -1063
- package/dist/index.js +588 -107
- package/dist/maintenance-runner.js +565 -84
- package/dist/media-audio-runner.js +565 -84
- package/dist/media-video-runner.js +565 -84
- package/dist/memcode-runtime/CHANGELOG.md +22 -0
- package/dist/sdk.js +621 -111
- package/dist/vector-backfill-runner.js +565 -84
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/PERFORMANCE.md +15 -0
- package/package.json +2 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/audit/index.ts +156 -156
- package/src/cli/commands/background.ts +34 -2
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +54 -54
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/lock.ts +82 -82
- package/src/cli/commands/message.ts +104 -104
- package/src/cli/commands/operator-shared.ts +6 -3
- package/src/cli/commands/poll.ts +58 -58
- package/src/cli/commands/reasoning.ts +118 -118
- package/src/cli/commands/serve-http.ts +4 -0
- package/src/cli/commands/skills.ts +114 -114
- package/src/cli/commands/task.ts +167 -167
- package/src/cli/commands/transfer.ts +47 -47
- package/src/cli/index.ts +406 -406
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/dashboard/project-classification.ts +64 -64
- package/src/embedding/api-provider.ts +503 -27
- package/src/embedding/provider.ts +20 -3
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/lifecycle.ts +1 -0
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/quality.ts +248 -248
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/disclosure-policy.ts +135 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/observations.ts +68 -18
- package/src/memory/refs.ts +94 -94
- package/src/memory/secret-filter.ts +79 -79
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +343 -343
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/project/aliases.ts +374 -374
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/syncer.ts +235 -235
- package/src/sdk.ts +12 -8
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/orama-store.ts +21 -3
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/team/event-bus.ts +76 -76
- package/src/team/handoff.ts +161 -161
- package/src/team/poll.ts +132 -132
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
package/dist/index.js
CHANGED
|
@@ -1195,8 +1195,8 @@ async function acquireLock(lockPath) {
|
|
|
1195
1195
|
const code = err instanceof Error && "code" in err ? err.code : void 0;
|
|
1196
1196
|
if (code === "EEXIST" || code === "EPERM") {
|
|
1197
1197
|
try {
|
|
1198
|
-
const
|
|
1199
|
-
if (Date.now() -
|
|
1198
|
+
const stat5 = await fs2.stat(lockPath);
|
|
1199
|
+
if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
|
|
1200
1200
|
await fs2.unlink(lockPath).catch(() => {
|
|
1201
1201
|
});
|
|
1202
1202
|
continue;
|
|
@@ -3713,24 +3713,131 @@ var init_transformers_provider = __esm({
|
|
|
3713
3713
|
// src/embedding/api-provider.ts
|
|
3714
3714
|
var api_provider_exports = {};
|
|
3715
3715
|
__export(api_provider_exports, {
|
|
3716
|
-
APIEmbeddingProvider: () => APIEmbeddingProvider
|
|
3716
|
+
APIEmbeddingProvider: () => APIEmbeddingProvider,
|
|
3717
|
+
convertArrayCacheToJsonl: () => convertArrayCacheToJsonl,
|
|
3718
|
+
ensureDiskCacheLoaded: () => ensureDiskCacheLoaded,
|
|
3719
|
+
getApiEmbeddingCachePayloadBytesForTests: () => getApiEmbeddingCachePayloadBytesForTests,
|
|
3720
|
+
getApiEmbeddingDiskCacheLoadCountForTests: () => getApiEmbeddingDiskCacheLoadCountForTests,
|
|
3721
|
+
getApiEmbeddingJsonlLineCountCallsForTests: () => getApiEmbeddingJsonlLineCountCallsForTests,
|
|
3722
|
+
getApiEmbeddingMaxEntriesForDimensionsForTests: () => getApiEmbeddingMaxEntriesForDimensionsForTests,
|
|
3723
|
+
migrateJsonArrayCacheToJsonl: () => migrateJsonArrayCacheToJsonl,
|
|
3724
|
+
parseCacheJsonInWorker: () => parseCacheJsonInWorker,
|
|
3725
|
+
resetApiEmbeddingCacheForTests: () => resetApiEmbeddingCacheForTests,
|
|
3726
|
+
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
3727
|
+
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
3717
3728
|
});
|
|
3718
3729
|
import { createHash as createHash2 } from "crypto";
|
|
3719
|
-
import {
|
|
3730
|
+
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
3731
|
+
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
3720
3732
|
import { join as join3 } from "path";
|
|
3721
3733
|
import { homedir as homedir7 } from "os";
|
|
3734
|
+
import { createInterface } from "readline";
|
|
3722
3735
|
function cacheDir() {
|
|
3723
3736
|
return process.env.MEMORIX_DATA_DIR || join3(homedir7(), ".memorix", "data");
|
|
3724
3737
|
}
|
|
3725
3738
|
function cacheFile() {
|
|
3726
3739
|
return join3(cacheDir(), ".embedding-api-cache.json");
|
|
3727
3740
|
}
|
|
3741
|
+
function cacheJsonlFile() {
|
|
3742
|
+
return join3(cacheDir(), ".embedding-api-cache.jsonl");
|
|
3743
|
+
}
|
|
3728
3744
|
function dimsCacheFile() {
|
|
3729
3745
|
return join3(cacheDir(), ".embedding-dims-cache.json");
|
|
3730
3746
|
}
|
|
3731
3747
|
function cacheMetaFile() {
|
|
3732
3748
|
return join3(cacheDir(), ".embedding-api-cache-meta.json");
|
|
3733
3749
|
}
|
|
3750
|
+
function cacheStatFile() {
|
|
3751
|
+
return join3(cacheDir(), ".embedding-api-cache-stat.json");
|
|
3752
|
+
}
|
|
3753
|
+
function payloadBytes(vector) {
|
|
3754
|
+
return vector.length * BYTES_PER_DIM;
|
|
3755
|
+
}
|
|
3756
|
+
function maxCachePayloadBytes() {
|
|
3757
|
+
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
3758
|
+
if (raw) {
|
|
3759
|
+
const parsed = Number.parseInt(raw, 10);
|
|
3760
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
3761
|
+
}
|
|
3762
|
+
return MAX_CACHE_PAYLOAD_BYTES;
|
|
3763
|
+
}
|
|
3764
|
+
function maxEntriesForDimensions(dimensions) {
|
|
3765
|
+
const dim = Math.max(1, Math.floor(dimensions));
|
|
3766
|
+
const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
|
|
3767
|
+
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
3768
|
+
}
|
|
3769
|
+
function rememberDimensions(vector) {
|
|
3770
|
+
if (vector.length > 0 && (cacheDimensions === null || vector.length > cacheDimensions)) {
|
|
3771
|
+
cacheDimensions = vector.length;
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
function evictOldest() {
|
|
3775
|
+
const firstKey = cache3.keys().next().value;
|
|
3776
|
+
if (firstKey === void 0) return;
|
|
3777
|
+
const old = cache3.get(firstKey);
|
|
3778
|
+
cache3.delete(firstKey);
|
|
3779
|
+
if (old) cachePayloadBytes -= payloadBytes(old);
|
|
3780
|
+
}
|
|
3781
|
+
function evictToFit(incomingBytes, incomingDims) {
|
|
3782
|
+
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
3783
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
|
|
3784
|
+
evictOldest();
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
function isNumberArray(value) {
|
|
3788
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
3789
|
+
}
|
|
3790
|
+
function parseCacheRow(raw) {
|
|
3791
|
+
if (Array.isArray(raw)) {
|
|
3792
|
+
const hash4 = raw[0];
|
|
3793
|
+
const vector = raw[1];
|
|
3794
|
+
if (typeof hash4 === "string" && isNumberArray(vector)) {
|
|
3795
|
+
return { hash: hash4, vector };
|
|
3796
|
+
}
|
|
3797
|
+
return null;
|
|
3798
|
+
}
|
|
3799
|
+
if (raw && typeof raw === "object") {
|
|
3800
|
+
const row = raw;
|
|
3801
|
+
if (typeof row.h === "string" && isNumberArray(row.v)) {
|
|
3802
|
+
return { hash: row.h, vector: row.v };
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
return null;
|
|
3806
|
+
}
|
|
3807
|
+
function cacheInsert(hash4, value, dirty) {
|
|
3808
|
+
rememberDimensions(value);
|
|
3809
|
+
const incoming = payloadBytes(value);
|
|
3810
|
+
const existing = cache3.get(hash4);
|
|
3811
|
+
if (existing) {
|
|
3812
|
+
cachePayloadBytes -= payloadBytes(existing);
|
|
3813
|
+
cache3.delete(hash4);
|
|
3814
|
+
}
|
|
3815
|
+
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
3816
|
+
cache3.set(hash4, value);
|
|
3817
|
+
cachePayloadBytes += incoming;
|
|
3818
|
+
if (dirty) diskCacheDirty2 = true;
|
|
3819
|
+
}
|
|
3820
|
+
async function readCacheStat() {
|
|
3821
|
+
try {
|
|
3822
|
+
const data = JSON.parse(await readFile2(cacheStatFile(), "utf-8"));
|
|
3823
|
+
if (typeof data.entryCount === "number" && Number.isFinite(data.entryCount) && data.entryCount >= 0) {
|
|
3824
|
+
return {
|
|
3825
|
+
version: 1,
|
|
3826
|
+
entryCount: Math.floor(data.entryCount),
|
|
3827
|
+
dimensions: isValidDimension(data.dimensions) ? data.dimensions : null
|
|
3828
|
+
};
|
|
3829
|
+
}
|
|
3830
|
+
} catch {
|
|
3831
|
+
}
|
|
3832
|
+
return null;
|
|
3833
|
+
}
|
|
3834
|
+
async function writeCacheStat(stat5) {
|
|
3835
|
+
try {
|
|
3836
|
+
await mkdir2(cacheDir(), { recursive: true });
|
|
3837
|
+
await writeFile2(cacheStatFile(), JSON.stringify(stat5));
|
|
3838
|
+
} catch {
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3734
3841
|
function normalizeText(text2) {
|
|
3735
3842
|
return text2.replace(/\s+/g, " ").trim().slice(0, MAX_INPUT_CHARS);
|
|
3736
3843
|
}
|
|
@@ -3816,29 +3923,300 @@ function toProviderInput(input, baseUrl) {
|
|
|
3816
3923
|
}
|
|
3817
3924
|
return { type: input.modality, url: input.url };
|
|
3818
3925
|
}
|
|
3926
|
+
function parseCacheJsonInWorker(filePath) {
|
|
3927
|
+
return new Promise((resolve2, reject) => {
|
|
3928
|
+
void import("worker_threads").then(({ Worker }) => {
|
|
3929
|
+
const worker = new Worker(
|
|
3930
|
+
`
|
|
3931
|
+
const { parentPort, workerData } = require('node:worker_threads');
|
|
3932
|
+
const { readFileSync } = require('node:fs');
|
|
3933
|
+
try {
|
|
3934
|
+
const raw = readFileSync(workerData.filePath, 'utf8');
|
|
3935
|
+
parentPort.postMessage({ ok: true, entries: JSON.parse(raw) });
|
|
3936
|
+
} catch (err) {
|
|
3937
|
+
parentPort.postMessage({
|
|
3938
|
+
ok: false,
|
|
3939
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
`,
|
|
3943
|
+
{ eval: true, workerData: { filePath } }
|
|
3944
|
+
);
|
|
3945
|
+
worker.once("message", (msg) => {
|
|
3946
|
+
void worker.terminate();
|
|
3947
|
+
if (msg?.ok && Array.isArray(msg.entries)) {
|
|
3948
|
+
resolve2(msg.entries);
|
|
3949
|
+
return;
|
|
3950
|
+
}
|
|
3951
|
+
reject(new Error(msg?.error || "embedding cache worker parse failed"));
|
|
3952
|
+
});
|
|
3953
|
+
worker.once("error", reject);
|
|
3954
|
+
}).catch(reject);
|
|
3955
|
+
});
|
|
3956
|
+
}
|
|
3957
|
+
function findJsonValueEnd(source) {
|
|
3958
|
+
let i2 = 0;
|
|
3959
|
+
while (i2 < source.length && /\s/.test(source[i2])) i2 += 1;
|
|
3960
|
+
if (i2 >= source.length) return -1;
|
|
3961
|
+
const start = source[i2];
|
|
3962
|
+
if (start === '"') {
|
|
3963
|
+
i2 += 1;
|
|
3964
|
+
while (i2 < source.length) {
|
|
3965
|
+
if (source[i2] === "\\") {
|
|
3966
|
+
i2 += 2;
|
|
3967
|
+
continue;
|
|
3968
|
+
}
|
|
3969
|
+
if (source[i2] === '"') return i2 + 1;
|
|
3970
|
+
i2 += 1;
|
|
3971
|
+
}
|
|
3972
|
+
return -1;
|
|
3973
|
+
}
|
|
3974
|
+
if (start === "{" || start === "[") {
|
|
3975
|
+
const close = start === "{" ? "}" : "]";
|
|
3976
|
+
let depth = 0;
|
|
3977
|
+
let inString = false;
|
|
3978
|
+
for (; i2 < source.length; i2 += 1) {
|
|
3979
|
+
const ch = source[i2];
|
|
3980
|
+
if (inString) {
|
|
3981
|
+
if (ch === "\\") {
|
|
3982
|
+
i2 += 1;
|
|
3983
|
+
continue;
|
|
3984
|
+
}
|
|
3985
|
+
if (ch === '"') inString = false;
|
|
3986
|
+
continue;
|
|
3987
|
+
}
|
|
3988
|
+
if (ch === '"') {
|
|
3989
|
+
inString = true;
|
|
3990
|
+
continue;
|
|
3991
|
+
}
|
|
3992
|
+
if (ch === start) depth += 1;
|
|
3993
|
+
else if (ch === close) {
|
|
3994
|
+
depth -= 1;
|
|
3995
|
+
if (depth === 0) return i2 + 1;
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
return -1;
|
|
3999
|
+
}
|
|
4000
|
+
const rest = source.slice(i2);
|
|
4001
|
+
const match2 = rest.match(/^(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/);
|
|
4002
|
+
return match2 ? i2 + match2[0].length : -1;
|
|
4003
|
+
}
|
|
4004
|
+
async function streamJsonArrayToJsonl(filePath, tmpPath) {
|
|
4005
|
+
const input = createReadStream(filePath, { encoding: "utf8" });
|
|
4006
|
+
const out = createWriteStream(tmpPath);
|
|
4007
|
+
let buf = "";
|
|
4008
|
+
let started = false;
|
|
4009
|
+
let count2 = 0;
|
|
4010
|
+
const writeLine = async (line) => {
|
|
4011
|
+
if (!out.write(line)) {
|
|
4012
|
+
await new Promise((resolve2, reject) => {
|
|
4013
|
+
out.once("drain", resolve2);
|
|
4014
|
+
out.once("error", reject);
|
|
4015
|
+
});
|
|
4016
|
+
}
|
|
4017
|
+
};
|
|
4018
|
+
try {
|
|
4019
|
+
for await (const chunk of input) {
|
|
4020
|
+
buf += chunk;
|
|
4021
|
+
if (!started) {
|
|
4022
|
+
const idx = buf.search(/\S/);
|
|
4023
|
+
if (idx < 0) continue;
|
|
4024
|
+
if (buf[idx] !== "[") throw new Error("embedding cache is not a JSON array");
|
|
4025
|
+
buf = buf.slice(idx + 1);
|
|
4026
|
+
started = true;
|
|
4027
|
+
}
|
|
4028
|
+
while (true) {
|
|
4029
|
+
buf = buf.replace(/^\s*,?\s*/, "");
|
|
4030
|
+
if (!buf) break;
|
|
4031
|
+
if (buf[0] === "]") {
|
|
4032
|
+
buf = "";
|
|
4033
|
+
break;
|
|
4034
|
+
}
|
|
4035
|
+
const end = findJsonValueEnd(buf);
|
|
4036
|
+
if (end < 0) break;
|
|
4037
|
+
const value = JSON.parse(buf.slice(0, end));
|
|
4038
|
+
buf = buf.slice(end);
|
|
4039
|
+
const row = parseCacheRow(value);
|
|
4040
|
+
if (row) {
|
|
4041
|
+
await writeLine(`${JSON.stringify({ h: row.hash, v: row.vector })}
|
|
4042
|
+
`);
|
|
4043
|
+
count2 += 1;
|
|
4044
|
+
if (count2 % 50 === 0) {
|
|
4045
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
if (buf.length > MAX_MIGRATION_VALUE_BYTES) {
|
|
4050
|
+
throw new Error("embedding cache entry too large to migrate safely");
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
} finally {
|
|
4054
|
+
await new Promise((resolve2, reject) => {
|
|
4055
|
+
out.end(() => resolve2());
|
|
4056
|
+
out.once("error", reject);
|
|
4057
|
+
});
|
|
4058
|
+
}
|
|
4059
|
+
return count2;
|
|
4060
|
+
}
|
|
4061
|
+
async function migrateJsonArrayCacheToJsonl(filePath, jsonlPath) {
|
|
4062
|
+
const tmpPath = `${jsonlPath}.tmp`;
|
|
4063
|
+
try {
|
|
4064
|
+
const count2 = await streamJsonArrayToJsonl(filePath, tmpPath);
|
|
4065
|
+
await rename(tmpPath, jsonlPath);
|
|
4066
|
+
diskCacheEntryCount = count2;
|
|
4067
|
+
await writeCacheStat({
|
|
4068
|
+
version: 1,
|
|
4069
|
+
entryCount: count2,
|
|
4070
|
+
dimensions: cacheDimensions
|
|
4071
|
+
});
|
|
4072
|
+
return count2;
|
|
4073
|
+
} catch (err) {
|
|
4074
|
+
await unlink(tmpPath).catch(() => void 0);
|
|
4075
|
+
throw err;
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
function convertArrayCacheToJsonl(filePath, jsonlPath) {
|
|
4079
|
+
return migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
|
|
4080
|
+
}
|
|
4081
|
+
async function loadCacheJsonl(filePath) {
|
|
4082
|
+
const rl = createInterface({
|
|
4083
|
+
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
4084
|
+
crlfDelay: Infinity
|
|
4085
|
+
});
|
|
4086
|
+
let loaded = 0;
|
|
4087
|
+
let onDiskCount = 0;
|
|
4088
|
+
for await (const line of rl) {
|
|
4089
|
+
const trimmed = line.trim();
|
|
4090
|
+
if (!trimmed) continue;
|
|
4091
|
+
try {
|
|
4092
|
+
const row = parseCacheRow(JSON.parse(trimmed));
|
|
4093
|
+
if (!row) continue;
|
|
4094
|
+
onDiskCount += 1;
|
|
4095
|
+
cacheInsert(row.hash, row.vector, false);
|
|
4096
|
+
loaded = cache3.size;
|
|
4097
|
+
} catch {
|
|
4098
|
+
}
|
|
4099
|
+
if (onDiskCount % 250 === 0) {
|
|
4100
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
diskCacheEntryCount = onDiskCount;
|
|
4104
|
+
await writeCacheStat({
|
|
4105
|
+
version: 1,
|
|
4106
|
+
entryCount: onDiskCount,
|
|
4107
|
+
dimensions: cacheDimensions
|
|
4108
|
+
});
|
|
4109
|
+
return loaded;
|
|
4110
|
+
}
|
|
4111
|
+
async function countJsonlLines(filePath) {
|
|
4112
|
+
jsonlLineCountCalls += 1;
|
|
4113
|
+
try {
|
|
4114
|
+
const rl = createInterface({
|
|
4115
|
+
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
4116
|
+
crlfDelay: Infinity
|
|
4117
|
+
});
|
|
4118
|
+
let count2 = 0;
|
|
4119
|
+
for await (const line of rl) {
|
|
4120
|
+
if (line.trim()) count2 += 1;
|
|
4121
|
+
}
|
|
4122
|
+
return count2;
|
|
4123
|
+
} catch {
|
|
4124
|
+
return 0;
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
async function resolveOnDiskCount(jsonlPath) {
|
|
4128
|
+
if (diskCacheEntryCount > 0) return diskCacheEntryCount;
|
|
4129
|
+
const sidecar = await readCacheStat();
|
|
4130
|
+
if (sidecar) {
|
|
4131
|
+
diskCacheEntryCount = sidecar.entryCount;
|
|
4132
|
+
if (sidecar.dimensions && cacheDimensions === null) cacheDimensions = sidecar.dimensions;
|
|
4133
|
+
return sidecar.entryCount;
|
|
4134
|
+
}
|
|
4135
|
+
try {
|
|
4136
|
+
await access(jsonlPath, fsConstants.R_OK);
|
|
4137
|
+
} catch {
|
|
4138
|
+
return 0;
|
|
4139
|
+
}
|
|
4140
|
+
const counted = await countJsonlLines(jsonlPath);
|
|
4141
|
+
diskCacheEntryCount = counted;
|
|
4142
|
+
await writeCacheStat({
|
|
4143
|
+
version: 1,
|
|
4144
|
+
entryCount: counted,
|
|
4145
|
+
dimensions: cacheDimensions
|
|
4146
|
+
});
|
|
4147
|
+
return counted;
|
|
4148
|
+
}
|
|
3819
4149
|
async function loadDiskCache2() {
|
|
3820
|
-
if (diskCacheLoaded) return;
|
|
4150
|
+
if (diskCacheLoaded) return cache3.size;
|
|
4151
|
+
let loaded = 0;
|
|
3821
4152
|
try {
|
|
3822
|
-
const
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
4153
|
+
const jsonlPath = cacheJsonlFile();
|
|
4154
|
+
let hasJsonl = false;
|
|
4155
|
+
try {
|
|
4156
|
+
await access(jsonlPath, fsConstants.R_OK);
|
|
4157
|
+
hasJsonl = true;
|
|
4158
|
+
} catch {
|
|
4159
|
+
hasJsonl = false;
|
|
4160
|
+
}
|
|
4161
|
+
if (hasJsonl) {
|
|
4162
|
+
loaded = await loadCacheJsonl(jsonlPath);
|
|
4163
|
+
} else {
|
|
4164
|
+
const filePath = cacheFile();
|
|
4165
|
+
await stat(filePath);
|
|
4166
|
+
await migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
|
|
4167
|
+
loaded = await loadCacheJsonl(jsonlPath);
|
|
4168
|
+
}
|
|
4169
|
+
diskCacheLoadCount += 1;
|
|
4170
|
+
console.error(`[memorix] Loaded ${loaded} cached API embeddings from disk`);
|
|
3826
4171
|
} catch {
|
|
3827
4172
|
}
|
|
3828
4173
|
diskCacheLoaded = true;
|
|
4174
|
+
return loaded;
|
|
3829
4175
|
}
|
|
3830
4176
|
function startDiskCacheLoad() {
|
|
3831
4177
|
if (diskCacheLoaded || diskCacheLoadPromise) return;
|
|
3832
|
-
diskCacheLoadPromise = loadDiskCache2().catch(() => {
|
|
4178
|
+
diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
|
|
3833
4179
|
});
|
|
3834
4180
|
}
|
|
3835
4181
|
async function ensureDiskCacheLoaded() {
|
|
3836
|
-
if (diskCacheLoaded) return;
|
|
3837
|
-
if (diskCacheLoadPromise) {
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
}
|
|
3841
|
-
await
|
|
4182
|
+
if (diskCacheLoaded) return cache3.size;
|
|
4183
|
+
if (!diskCacheLoadPromise) {
|
|
4184
|
+
diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
|
|
4185
|
+
});
|
|
4186
|
+
}
|
|
4187
|
+
await diskCacheLoadPromise;
|
|
4188
|
+
return cache3.size;
|
|
4189
|
+
}
|
|
4190
|
+
function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
4191
|
+
return diskCacheLoadCount;
|
|
4192
|
+
}
|
|
4193
|
+
function resetApiEmbeddingCacheForTests() {
|
|
4194
|
+
cache3.clear();
|
|
4195
|
+
cachePayloadBytes = 0;
|
|
4196
|
+
cacheDimensions = null;
|
|
4197
|
+
diskCacheEntryCount = 0;
|
|
4198
|
+
diskCacheLoaded = false;
|
|
4199
|
+
diskCacheLoadPromise = null;
|
|
4200
|
+
diskCacheLoadCount = 0;
|
|
4201
|
+
diskCacheDirty2 = false;
|
|
4202
|
+
jsonlLineCountCalls = 0;
|
|
4203
|
+
}
|
|
4204
|
+
function seedApiEmbeddingCacheForTests(entries) {
|
|
4205
|
+
cache3.clear();
|
|
4206
|
+
cachePayloadBytes = 0;
|
|
4207
|
+
cacheDimensions = null;
|
|
4208
|
+
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
4209
|
+
diskCacheLoaded = true;
|
|
4210
|
+
diskCacheDirty2 = true;
|
|
4211
|
+
}
|
|
4212
|
+
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
4213
|
+
return cachePayloadBytes;
|
|
4214
|
+
}
|
|
4215
|
+
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
4216
|
+
return jsonlLineCountCalls;
|
|
4217
|
+
}
|
|
4218
|
+
function getApiEmbeddingMaxEntriesForDimensionsForTests(dimensions) {
|
|
4219
|
+
return maxEntriesForDimensions(dimensions);
|
|
3842
4220
|
}
|
|
3843
4221
|
function dimsCacheKey(config) {
|
|
3844
4222
|
return [
|
|
@@ -3954,8 +4332,46 @@ async function saveDiskCacheNow() {
|
|
|
3954
4332
|
if (!diskCacheDirty2) return;
|
|
3955
4333
|
try {
|
|
3956
4334
|
await mkdir2(cacheDir(), { recursive: true });
|
|
3957
|
-
const
|
|
3958
|
-
await
|
|
4335
|
+
const jsonlPath = cacheJsonlFile();
|
|
4336
|
+
const existing = await resolveOnDiskCount(jsonlPath);
|
|
4337
|
+
if (existing > 0 && cache3.size < Math.ceil(existing * 0.5)) {
|
|
4338
|
+
console.error(
|
|
4339
|
+
`[memorix] Refusing to overwrite embedding cache (${existing} on disk vs ${cache3.size} in memory)`
|
|
4340
|
+
);
|
|
4341
|
+
diskCacheDirty2 = false;
|
|
4342
|
+
return;
|
|
4343
|
+
}
|
|
4344
|
+
const tmpPath = `${jsonlPath}.tmp`;
|
|
4345
|
+
await new Promise((resolve2, reject) => {
|
|
4346
|
+
const out = createWriteStream(tmpPath);
|
|
4347
|
+
const entries = cache3.entries();
|
|
4348
|
+
const writeBatch = () => {
|
|
4349
|
+
for (let i2 = 0; i2 < 50; i2++) {
|
|
4350
|
+
const next = entries.next();
|
|
4351
|
+
if (next.done) {
|
|
4352
|
+
out.end();
|
|
4353
|
+
return;
|
|
4354
|
+
}
|
|
4355
|
+
const [hash4, vector] = next.value;
|
|
4356
|
+
if (!out.write(`${JSON.stringify({ h: hash4, v: vector })}
|
|
4357
|
+
`)) {
|
|
4358
|
+
out.once("drain", writeBatch);
|
|
4359
|
+
return;
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
setImmediate(writeBatch);
|
|
4363
|
+
};
|
|
4364
|
+
out.on("finish", resolve2);
|
|
4365
|
+
out.on("error", reject);
|
|
4366
|
+
writeBatch();
|
|
4367
|
+
});
|
|
4368
|
+
await rename(tmpPath, jsonlPath);
|
|
4369
|
+
diskCacheEntryCount = cache3.size;
|
|
4370
|
+
await writeCacheStat({
|
|
4371
|
+
version: 1,
|
|
4372
|
+
entryCount: cache3.size,
|
|
4373
|
+
dimensions: cacheDimensions
|
|
4374
|
+
});
|
|
3959
4375
|
diskCacheDirty2 = false;
|
|
3960
4376
|
} catch {
|
|
3961
4377
|
}
|
|
@@ -3969,12 +4385,7 @@ function scheduleDiskSave() {
|
|
|
3969
4385
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
3970
4386
|
}
|
|
3971
4387
|
function cacheSet(hash4, value) {
|
|
3972
|
-
|
|
3973
|
-
const firstKey = cache3.keys().next().value;
|
|
3974
|
-
if (firstKey !== void 0) cache3.delete(firstKey);
|
|
3975
|
-
}
|
|
3976
|
-
cache3.set(hash4, value);
|
|
3977
|
-
diskCacheDirty2 = true;
|
|
4388
|
+
cacheInsert(hash4, value, true);
|
|
3978
4389
|
}
|
|
3979
4390
|
function resolveEnvEmbeddingApiKey() {
|
|
3980
4391
|
return process.env.MEMORIX_EMBEDDING_API_KEY;
|
|
@@ -4093,18 +4504,27 @@ async function waitForRetry(waitMs, signal) {
|
|
|
4093
4504
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
4094
4505
|
});
|
|
4095
4506
|
}
|
|
4096
|
-
var cache3,
|
|
4507
|
+
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
|
|
4097
4508
|
var init_api_provider = __esm({
|
|
4098
4509
|
"src/embedding/api-provider.ts"() {
|
|
4099
4510
|
"use strict";
|
|
4100
4511
|
init_esm_shims();
|
|
4101
4512
|
init_provider();
|
|
4102
4513
|
cache3 = /* @__PURE__ */ new Map();
|
|
4103
|
-
|
|
4514
|
+
MAX_CACHE_ENTRIES = 2e5;
|
|
4515
|
+
MAX_CACHE_PAYLOAD_BYTES = 256 * 1024 * 1024;
|
|
4516
|
+
BYTES_PER_DIM = 8;
|
|
4517
|
+
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
4518
|
+
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
4519
|
+
cachePayloadBytes = 0;
|
|
4520
|
+
cacheDimensions = null;
|
|
4521
|
+
diskCacheEntryCount = 0;
|
|
4104
4522
|
diskCacheDirty2 = false;
|
|
4105
4523
|
diskSaveTimer = null;
|
|
4106
4524
|
diskCacheLoaded = false;
|
|
4107
4525
|
diskCacheLoadPromise = null;
|
|
4526
|
+
diskCacheLoadCount = 0;
|
|
4527
|
+
jsonlLineCountCalls = 0;
|
|
4108
4528
|
MAX_INPUT_CHARS = 32e3;
|
|
4109
4529
|
MAX_CONCURRENCY = 4;
|
|
4110
4530
|
DISK_SAVE_DEBOUNCE_MS = 5e3;
|
|
@@ -4162,7 +4582,9 @@ var init_api_provider = __esm({
|
|
|
4162
4582
|
if (config.requestedDimensions) {
|
|
4163
4583
|
console.error(`[memorix] Dimension shortening: ${config.requestedDimensions}d requested`);
|
|
4164
4584
|
}
|
|
4165
|
-
|
|
4585
|
+
if (allowNetworkProbe) {
|
|
4586
|
+
startDiskCacheLoad();
|
|
4587
|
+
}
|
|
4166
4588
|
return new _APIEmbeddingProvider(config, probeDimensions);
|
|
4167
4589
|
}
|
|
4168
4590
|
static resolveConfig() {
|
|
@@ -4500,7 +4922,12 @@ function warnOnce(message) {
|
|
|
4500
4922
|
lastEmbeddingWarningAt = now3;
|
|
4501
4923
|
console.error(message);
|
|
4502
4924
|
}
|
|
4925
|
+
function embeddingModeToken() {
|
|
4926
|
+
return process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim() ?? "";
|
|
4927
|
+
}
|
|
4503
4928
|
function getEmbeddingMode2() {
|
|
4929
|
+
const token = embeddingModeToken();
|
|
4930
|
+
if (cachedEmbeddingMode && cachedEmbeddingModeToken === token) return cachedEmbeddingMode;
|
|
4504
4931
|
try {
|
|
4505
4932
|
let cfg;
|
|
4506
4933
|
try {
|
|
@@ -4509,10 +4936,17 @@ function getEmbeddingMode2() {
|
|
|
4509
4936
|
cfg = (init_config(), __toCommonJS(config_exports));
|
|
4510
4937
|
}
|
|
4511
4938
|
const { getEmbeddingMode: cfgMode } = cfg;
|
|
4512
|
-
|
|
4939
|
+
cachedEmbeddingMode = cfgMode();
|
|
4940
|
+
cachedEmbeddingModeToken = token;
|
|
4941
|
+
return cachedEmbeddingMode;
|
|
4513
4942
|
} catch {
|
|
4514
|
-
|
|
4515
|
-
|
|
4943
|
+
if (token === "fastembed" || token === "transformers" || token === "api" || token === "auto") {
|
|
4944
|
+
cachedEmbeddingMode = token;
|
|
4945
|
+
cachedEmbeddingModeToken = token;
|
|
4946
|
+
return token;
|
|
4947
|
+
}
|
|
4948
|
+
cachedEmbeddingMode = "off";
|
|
4949
|
+
cachedEmbeddingModeToken = token;
|
|
4516
4950
|
return "off";
|
|
4517
4951
|
}
|
|
4518
4952
|
}
|
|
@@ -4768,13 +5202,15 @@ function isEmbeddingExplicitlyDisabled() {
|
|
|
4768
5202
|
function resetProvider() {
|
|
4769
5203
|
provider = null;
|
|
4770
5204
|
initPromise = null;
|
|
5205
|
+
cachedEmbeddingMode = null;
|
|
5206
|
+
cachedEmbeddingModeToken = null;
|
|
4771
5207
|
lastInitWasTemporaryFailure = false;
|
|
4772
5208
|
lastFailureTimestamp = 0;
|
|
4773
5209
|
lastEmbeddingFailure = null;
|
|
4774
5210
|
lastEmbeddingWarning = "";
|
|
4775
5211
|
lastEmbeddingWarningAt = 0;
|
|
4776
5212
|
}
|
|
4777
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
5213
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, cachedEmbeddingMode, cachedEmbeddingModeToken, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4778
5214
|
var init_provider = __esm({
|
|
4779
5215
|
"src/embedding/provider.ts"() {
|
|
4780
5216
|
"use strict";
|
|
@@ -4798,6 +5234,8 @@ var init_provider = __esm({
|
|
|
4798
5234
|
MAX_INLINE_EMBEDDING_BYTES = 5 * 1024 * 1024;
|
|
4799
5235
|
provider = null;
|
|
4800
5236
|
initPromise = null;
|
|
5237
|
+
cachedEmbeddingMode = null;
|
|
5238
|
+
cachedEmbeddingModeToken = null;
|
|
4801
5239
|
lastInitWasTemporaryFailure = false;
|
|
4802
5240
|
lastEmbeddingFailure = null;
|
|
4803
5241
|
lastEmbeddingWarning = "";
|
|
@@ -6555,6 +6993,9 @@ async function attachCachedVectors(database, candidates) {
|
|
|
6555
6993
|
await update(database, candidates[index].id, { ...existing, embedding: vector });
|
|
6556
6994
|
} catch {
|
|
6557
6995
|
}
|
|
6996
|
+
if (index % 50 === 0) {
|
|
6997
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
6998
|
+
}
|
|
6558
6999
|
}
|
|
6559
7000
|
}
|
|
6560
7001
|
async function hydrateIndex(observations2, options = {}) {
|
|
@@ -6605,17 +7046,24 @@ async function hydrateIndex(observations2, options = {}) {
|
|
|
6605
7046
|
await insert2(database, doc);
|
|
6606
7047
|
rememberObservationDoc(doc);
|
|
6607
7048
|
inserted++;
|
|
7049
|
+
if (inserted % 50 === 0) {
|
|
7050
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
7051
|
+
}
|
|
7052
|
+
if (inserted % 200 === 0) {
|
|
7053
|
+
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
7054
|
+
}
|
|
6608
7055
|
} catch {
|
|
6609
7056
|
}
|
|
6610
7057
|
}
|
|
6611
|
-
deferredCachedVectorHydration = deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
|
|
7058
|
+
deferredCachedVectorHydration = options.skipCachedVectors ? null : deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
|
|
6612
7059
|
}) : null;
|
|
6613
7060
|
return inserted;
|
|
6614
7061
|
}
|
|
6615
|
-
async function hydrateIndexForStartup(observations2) {
|
|
7062
|
+
async function hydrateIndexForStartup(observations2, options = {}) {
|
|
6616
7063
|
return hydrateIndex(observations2, {
|
|
6617
7064
|
allowNetworkProbe: false,
|
|
6618
|
-
deferCachedVectors: true
|
|
7065
|
+
deferCachedVectors: true,
|
|
7066
|
+
skipCachedVectors: options.skipCachedVectors
|
|
6619
7067
|
});
|
|
6620
7068
|
}
|
|
6621
7069
|
function getDeferredCachedVectorHydration() {
|
|
@@ -9938,7 +10386,7 @@ __export(asset_store_exports, {
|
|
|
9938
10386
|
removeMediaAsset: () => removeMediaAsset
|
|
9939
10387
|
});
|
|
9940
10388
|
import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
|
|
9941
|
-
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename, rm, stat, writeFile as writeFile3 } from "fs/promises";
|
|
10389
|
+
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
9942
10390
|
import path13 from "path";
|
|
9943
10391
|
function mediaRoot(dataDir) {
|
|
9944
10392
|
return path13.resolve(dataDir, "media");
|
|
@@ -10028,7 +10476,7 @@ async function persistFile(source, destination) {
|
|
|
10028
10476
|
const temporary = `${destination}.${randomUUID5()}.tmp`;
|
|
10029
10477
|
try {
|
|
10030
10478
|
await copyFile(source, temporary);
|
|
10031
|
-
await
|
|
10479
|
+
await rename2(temporary, destination);
|
|
10032
10480
|
return true;
|
|
10033
10481
|
} catch (error) {
|
|
10034
10482
|
if (error?.code === "EEXIST" && await destinationExists(destination)) return false;
|
|
@@ -10044,7 +10492,7 @@ async function persistBuffer(bytes, destination) {
|
|
|
10044
10492
|
const temporary = `${destination}.${randomUUID5()}.tmp`;
|
|
10045
10493
|
try {
|
|
10046
10494
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
10047
|
-
await
|
|
10495
|
+
await rename2(temporary, destination);
|
|
10048
10496
|
return true;
|
|
10049
10497
|
} catch (error) {
|
|
10050
10498
|
if (error?.code === "EEXIST" && await destinationExists(destination)) return false;
|
|
@@ -10084,11 +10532,11 @@ async function importKnownMedia(input) {
|
|
|
10084
10532
|
async function importMediaFile(input) {
|
|
10085
10533
|
const maxBytes = input.maxBytes ?? DEFAULT_MAX_MEDIA_BYTES;
|
|
10086
10534
|
const source = path13.resolve(input.filePath);
|
|
10087
|
-
const
|
|
10088
|
-
if (
|
|
10089
|
-
if (!
|
|
10090
|
-
if (
|
|
10091
|
-
if (
|
|
10535
|
+
const stat5 = await lstat(source);
|
|
10536
|
+
if (stat5.isSymbolicLink()) throw new Error("Media import does not follow symbolic links");
|
|
10537
|
+
if (!stat5.isFile()) throw new Error("Media import accepts regular files only");
|
|
10538
|
+
if (stat5.size <= 0) throw new Error("Media import rejects empty files");
|
|
10539
|
+
if (stat5.size > maxBytes) throw new Error(`Media file is too large (${stat5.size} bytes; limit ${maxBytes})`);
|
|
10092
10540
|
const header = await readHeader(source);
|
|
10093
10541
|
const detected = detectMedia(header);
|
|
10094
10542
|
const sha256 = await sha256File(source);
|
|
@@ -10096,7 +10544,7 @@ async function importMediaFile(input) {
|
|
|
10096
10544
|
dataDir: input.dataDir,
|
|
10097
10545
|
projectId: input.projectId,
|
|
10098
10546
|
sha256,
|
|
10099
|
-
bytes:
|
|
10547
|
+
bytes: stat5.size,
|
|
10100
10548
|
detected,
|
|
10101
10549
|
persist: (destination) => persistFile(source, destination),
|
|
10102
10550
|
sourceKind: input.sourceKind ?? "import",
|
|
@@ -10143,13 +10591,13 @@ async function removeMediaAsset(input) {
|
|
|
10143
10591
|
const assetPath = getMediaAssetPath(input.dataDir, asset);
|
|
10144
10592
|
const stagedPath = deletionStagingPath(mediaRoot(input.dataDir), asset.id);
|
|
10145
10593
|
await mkdir3(path13.dirname(stagedPath), { recursive: true });
|
|
10146
|
-
await
|
|
10594
|
+
await rename2(assetPath, stagedPath);
|
|
10147
10595
|
let detachedLinks;
|
|
10148
10596
|
try {
|
|
10149
10597
|
({ detachedLinks } = store.removeAssetMetadata(input.projectId, asset.id, { force: input.force }));
|
|
10150
10598
|
} catch (error) {
|
|
10151
10599
|
try {
|
|
10152
|
-
await
|
|
10600
|
+
await rename2(stagedPath, assetPath);
|
|
10153
10601
|
} catch (restoreError) {
|
|
10154
10602
|
const original = error instanceof Error ? error.message : String(error);
|
|
10155
10603
|
const restore = restoreError instanceof Error ? restoreError.message : String(restoreError);
|
|
@@ -10185,7 +10633,7 @@ async function cleanupMediaTrash(dataDir) {
|
|
|
10185
10633
|
} catch (error) {
|
|
10186
10634
|
if (error?.code === "ENOENT") continue;
|
|
10187
10635
|
try {
|
|
10188
|
-
pendingBytes += (await
|
|
10636
|
+
pendingBytes += (await stat2(candidate)).size;
|
|
10189
10637
|
} catch {
|
|
10190
10638
|
}
|
|
10191
10639
|
pendingFiles += 1;
|
|
@@ -61267,9 +61715,9 @@ var require_node_domexception = __commonJS({
|
|
|
61267
61715
|
});
|
|
61268
61716
|
|
|
61269
61717
|
// node_modules/fetch-blob/from.js
|
|
61270
|
-
import { statSync as statSync2, createReadStream, promises as fs10 } from "fs";
|
|
61718
|
+
import { statSync as statSync2, createReadStream as createReadStream2, promises as fs10 } from "fs";
|
|
61271
61719
|
import { basename } from "path";
|
|
61272
|
-
var import_node_domexception,
|
|
61720
|
+
var import_node_domexception, stat3, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
|
|
61273
61721
|
var init_from = __esm({
|
|
61274
61722
|
"node_modules/fetch-blob/from.js"() {
|
|
61275
61723
|
"use strict";
|
|
@@ -61277,23 +61725,23 @@ var init_from = __esm({
|
|
|
61277
61725
|
import_node_domexception = __toESM(require_node_domexception(), 1);
|
|
61278
61726
|
init_file();
|
|
61279
61727
|
init_fetch_blob();
|
|
61280
|
-
({ stat:
|
|
61728
|
+
({ stat: stat3 } = fs10);
|
|
61281
61729
|
blobFromSync = (path37, type) => fromBlob(statSync2(path37), path37, type);
|
|
61282
|
-
blobFrom = (path37, type) =>
|
|
61283
|
-
fileFrom = (path37, type) =>
|
|
61730
|
+
blobFrom = (path37, type) => stat3(path37).then((stat5) => fromBlob(stat5, path37, type));
|
|
61731
|
+
fileFrom = (path37, type) => stat3(path37).then((stat5) => fromFile(stat5, path37, type));
|
|
61284
61732
|
fileFromSync = (path37, type) => fromFile(statSync2(path37), path37, type);
|
|
61285
|
-
fromBlob = (
|
|
61733
|
+
fromBlob = (stat5, path37, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
61286
61734
|
path: path37,
|
|
61287
|
-
size:
|
|
61288
|
-
lastModified:
|
|
61735
|
+
size: stat5.size,
|
|
61736
|
+
lastModified: stat5.mtimeMs,
|
|
61289
61737
|
start: 0
|
|
61290
61738
|
})], { type });
|
|
61291
|
-
fromFile = (
|
|
61739
|
+
fromFile = (stat5, path37, type = "") => new file_default([new BlobDataItem({
|
|
61292
61740
|
path: path37,
|
|
61293
|
-
size:
|
|
61294
|
-
lastModified:
|
|
61741
|
+
size: stat5.size,
|
|
61742
|
+
lastModified: stat5.mtimeMs,
|
|
61295
61743
|
start: 0
|
|
61296
|
-
})], basename(path37), { type, lastModified:
|
|
61744
|
+
})], basename(path37), { type, lastModified: stat5.mtimeMs });
|
|
61297
61745
|
BlobDataItem = class _BlobDataItem {
|
|
61298
61746
|
#path;
|
|
61299
61747
|
#start;
|
|
@@ -61316,11 +61764,11 @@ var init_from = __esm({
|
|
|
61316
61764
|
});
|
|
61317
61765
|
}
|
|
61318
61766
|
async *stream() {
|
|
61319
|
-
const { mtimeMs } = await
|
|
61767
|
+
const { mtimeMs } = await stat3(this.#path);
|
|
61320
61768
|
if (mtimeMs > this.lastModified) {
|
|
61321
61769
|
throw new import_node_domexception.default("The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.", "NotReadableError");
|
|
61322
61770
|
}
|
|
61323
|
-
yield*
|
|
61771
|
+
yield* createReadStream2(this.#path, {
|
|
61324
61772
|
start: this.#start,
|
|
61325
61773
|
end: this.#start + this.size - 1
|
|
61326
61774
|
});
|
|
@@ -76950,7 +77398,7 @@ var init_wrapper = __esm({
|
|
|
76950
77398
|
});
|
|
76951
77399
|
|
|
76952
77400
|
// node_modules/@google/genai/dist/node/index.mjs
|
|
76953
|
-
import { createWriteStream } from "fs";
|
|
77401
|
+
import { createWriteStream as createWriteStream2 } from "fs";
|
|
76954
77402
|
import * as fs11 from "fs/promises";
|
|
76955
77403
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
76956
77404
|
import { Readable } from "stream";
|
|
@@ -94230,7 +94678,7 @@ ${underline}`);
|
|
|
94230
94678
|
if (params.downloadPath) {
|
|
94231
94679
|
const response = await downloadFile(params, apiClient);
|
|
94232
94680
|
if (response instanceof HttpResponse) {
|
|
94233
|
-
const writer =
|
|
94681
|
+
const writer = createWriteStream2(params.downloadPath);
|
|
94234
94682
|
const body = Readable.fromWeb(response.responseInternal.body);
|
|
94235
94683
|
body.pipe(writer);
|
|
94236
94684
|
await finished(writer);
|
|
@@ -144264,7 +144712,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
144264
144712
|
};
|
|
144265
144713
|
}
|
|
144266
144714
|
function toRetentionDocument(obs, accessMap) {
|
|
144267
|
-
const
|
|
144715
|
+
const access3 = accessMap?.get(obs.id);
|
|
144268
144716
|
return {
|
|
144269
144717
|
id: `obs-${obs.id}`,
|
|
144270
144718
|
observationId: obs.id,
|
|
@@ -144278,8 +144726,8 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
144278
144726
|
tokens: obs.tokens,
|
|
144279
144727
|
createdAt: obs.createdAt,
|
|
144280
144728
|
projectId: obs.projectId,
|
|
144281
|
-
accessCount:
|
|
144282
|
-
lastAccessedAt:
|
|
144729
|
+
accessCount: access3?.accessCount ?? 0,
|
|
144730
|
+
lastAccessedAt: access3?.lastAccessedAt ?? "",
|
|
144283
144731
|
status: obs.status ?? "active",
|
|
144284
144732
|
source: obs.source ?? "agent",
|
|
144285
144733
|
sourceDetail: obs.sourceDetail ?? "",
|
|
@@ -146393,7 +146841,7 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
146393
146841
|
const rel = normalizeCodePath(relative(projectRoot, abs));
|
|
146394
146842
|
try {
|
|
146395
146843
|
const text2 = readFileSync6(abs, "utf-8");
|
|
146396
|
-
const
|
|
146844
|
+
const stat5 = fileStat ?? statSync3(abs);
|
|
146397
146845
|
const file = {
|
|
146398
146846
|
id: makeCodeFileId(projectId, rel),
|
|
146399
146847
|
projectId,
|
|
@@ -146402,8 +146850,8 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
146402
146850
|
contentHash: hashText(text2),
|
|
146403
146851
|
// Preserve filesystem precision. Rounding here made same-size edits in
|
|
146404
146852
|
// a short Windows timestamp window indistinguishable to refresh.
|
|
146405
|
-
mtimeMs: Number(
|
|
146406
|
-
sizeBytes: Number(
|
|
146853
|
+
mtimeMs: Number(stat5.mtimeMs),
|
|
146854
|
+
sizeBytes: Number(stat5.size),
|
|
146407
146855
|
indexedAt
|
|
146408
146856
|
};
|
|
146409
146857
|
return {
|
|
@@ -146430,18 +146878,18 @@ async function indexProjectLite(options) {
|
|
|
146430
146878
|
let skippedOversizedFiles = 0;
|
|
146431
146879
|
let unreadableFiles = 0;
|
|
146432
146880
|
for (const abs of paths) {
|
|
146433
|
-
let
|
|
146881
|
+
let stat5;
|
|
146434
146882
|
try {
|
|
146435
|
-
|
|
146883
|
+
stat5 = statSync3(abs);
|
|
146436
146884
|
} catch {
|
|
146437
146885
|
unreadableFiles++;
|
|
146438
146886
|
continue;
|
|
146439
146887
|
}
|
|
146440
|
-
if (Number(
|
|
146888
|
+
if (Number(stat5.size) > maxFileBytes) {
|
|
146441
146889
|
skippedOversizedFiles++;
|
|
146442
146890
|
continue;
|
|
146443
146891
|
}
|
|
146444
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
146892
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
146445
146893
|
if (!attempt.delta) {
|
|
146446
146894
|
if (attempt.unreadable) unreadableFiles++;
|
|
146447
146895
|
continue;
|
|
@@ -146469,16 +146917,16 @@ async function refreshProjectLite(store, options) {
|
|
|
146469
146917
|
for (const abs of paths) {
|
|
146470
146918
|
const rel = normalizeCodePath(relative(options.projectRoot, abs));
|
|
146471
146919
|
seenPaths.add(rel);
|
|
146472
|
-
let
|
|
146920
|
+
let stat5;
|
|
146473
146921
|
try {
|
|
146474
|
-
|
|
146922
|
+
stat5 = statSync3(abs);
|
|
146475
146923
|
} catch {
|
|
146476
146924
|
unreadableFiles++;
|
|
146477
146925
|
continue;
|
|
146478
146926
|
}
|
|
146479
146927
|
const existing = existingByPath.get(rel);
|
|
146480
|
-
const mtimeMs = Number(
|
|
146481
|
-
const sizeBytes = Number(
|
|
146928
|
+
const mtimeMs = Number(stat5.mtimeMs);
|
|
146929
|
+
const sizeBytes = Number(stat5.size);
|
|
146482
146930
|
if (sizeBytes > maxFileBytes) {
|
|
146483
146931
|
skippedOversizedFiles++;
|
|
146484
146932
|
if (existing) oversizedExistingFileIds.add(existing.id);
|
|
@@ -146488,7 +146936,7 @@ async function refreshProjectLite(store, options) {
|
|
|
146488
146936
|
unchangedFiles++;
|
|
146489
146937
|
continue;
|
|
146490
146938
|
}
|
|
146491
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
146939
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
146492
146940
|
if (!attempt.delta) {
|
|
146493
146941
|
if (attempt.unreadable) unreadableFiles++;
|
|
146494
146942
|
continue;
|
|
@@ -150236,12 +150684,25 @@ __export(observations_exports, {
|
|
|
150236
150684
|
prepareSearchIndex: () => prepareSearchIndex,
|
|
150237
150685
|
probeSearchIndex: () => probeSearchIndex,
|
|
150238
150686
|
reindexObservations: () => reindexObservations,
|
|
150687
|
+
resetObservationRuntime: () => resetObservationRuntime,
|
|
150239
150688
|
resolveObservations: () => resolveObservations,
|
|
150240
150689
|
storeObservation: () => storeObservation,
|
|
150241
150690
|
suggestTopicKey: () => suggestTopicKey,
|
|
150242
150691
|
updateObservationAdmission: () => updateObservationAdmission,
|
|
150243
150692
|
withFreshObservations: () => withFreshObservations
|
|
150244
150693
|
});
|
|
150694
|
+
function resetObservationRuntime() {
|
|
150695
|
+
observations = [];
|
|
150696
|
+
nextId = 1;
|
|
150697
|
+
projectDir = null;
|
|
150698
|
+
searchIndexPrepared = false;
|
|
150699
|
+
corpusLoaded = false;
|
|
150700
|
+
loadedObservationStore = null;
|
|
150701
|
+
embeddingWriteMode = "background";
|
|
150702
|
+
embeddingWorkerProjectRoot = void 0;
|
|
150703
|
+
vectorMissingIds.clear();
|
|
150704
|
+
vectorSchemaUpgradePromise = null;
|
|
150705
|
+
}
|
|
150245
150706
|
function logEmbeddingFailureOnce(key, message) {
|
|
150246
150707
|
const now3 = Date.now();
|
|
150247
150708
|
const last = embeddingFailureLogTimestamps.get(key) ?? 0;
|
|
@@ -150350,23 +150811,33 @@ async function upgradeVectorSchemaAfterFirstEmbedding(embedding) {
|
|
|
150350
150811
|
async function initObservations(dir, options = {}) {
|
|
150351
150812
|
embeddingWriteMode = options.embeddingWriteMode ?? "background";
|
|
150352
150813
|
embeddingWorkerProjectRoot = options.projectRoot;
|
|
150353
|
-
if (projectDir === dir) return;
|
|
150354
150814
|
await initObservationStore(dir);
|
|
150355
150815
|
const store = getObservationStore();
|
|
150356
|
-
|
|
150816
|
+
if (projectDir === dir && loadedObservationStore === store) {
|
|
150817
|
+
if (options.skipCorpusLoad || corpusLoaded) return;
|
|
150818
|
+
}
|
|
150357
150819
|
nextId = await store.loadIdCounter();
|
|
150358
150820
|
projectDir = dir;
|
|
150359
150821
|
searchIndexPrepared = false;
|
|
150360
150822
|
vectorSchemaUpgradePromise = null;
|
|
150823
|
+
if (options.skipCorpusLoad) {
|
|
150824
|
+
observations = [];
|
|
150825
|
+
corpusLoaded = false;
|
|
150826
|
+
loadedObservationStore = store;
|
|
150827
|
+
return;
|
|
150828
|
+
}
|
|
150829
|
+
observations = await store.loadAll();
|
|
150830
|
+
corpusLoaded = true;
|
|
150831
|
+
loadedObservationStore = store;
|
|
150361
150832
|
}
|
|
150362
150833
|
function scheduleObservationEmbedding(input) {
|
|
150363
150834
|
const { observationId: observationId2, projectId, searchableText, doc } = input;
|
|
150364
150835
|
vectorMissingIds.add(observationId2);
|
|
150836
|
+
if (isEmbeddingExplicitlyDisabled()) {
|
|
150837
|
+
vectorMissingIds.delete(observationId2);
|
|
150838
|
+
return;
|
|
150839
|
+
}
|
|
150365
150840
|
if (embeddingWriteMode === "deferred") {
|
|
150366
|
-
if (isEmbeddingExplicitlyDisabled()) {
|
|
150367
|
-
vectorMissingIds.delete(observationId2);
|
|
150368
|
-
return;
|
|
150369
|
-
}
|
|
150370
150841
|
queueVectorBackfill(projectId, {
|
|
150371
150842
|
detachedWorker: true,
|
|
150372
150843
|
projectRoot: embeddingWorkerProjectRoot
|
|
@@ -150413,7 +150884,7 @@ function scheduleObservationEmbedding(input) {
|
|
|
150413
150884
|
});
|
|
150414
150885
|
}
|
|
150415
150886
|
async function ensureFreshObservations() {
|
|
150416
|
-
if (!projectDir) return false;
|
|
150887
|
+
if (!projectDir || !corpusLoaded) return false;
|
|
150417
150888
|
try {
|
|
150418
150889
|
const store = getObservationStore();
|
|
150419
150890
|
const wasStale = await store.ensureFresh();
|
|
@@ -150454,7 +150925,7 @@ async function storeObservation(input) {
|
|
|
150454
150925
|
});
|
|
150455
150926
|
if (safeAttachments) input = { ...input, attachments: safeAttachments };
|
|
150456
150927
|
await ensureFreshObservations();
|
|
150457
|
-
if (input.topicKey) {
|
|
150928
|
+
if (input.topicKey && corpusLoaded) {
|
|
150458
150929
|
const existing = observations.find(
|
|
150459
150930
|
(o) => o.topicKey === input.topicKey && o.projectId === input.projectId
|
|
150460
150931
|
);
|
|
@@ -150551,13 +151022,17 @@ async function storeObservation(input) {
|
|
|
150551
151022
|
});
|
|
150552
151023
|
observation.writeGeneration = store.getGeneration();
|
|
150553
151024
|
if (upsertedInsideLock || reloadCacheAfterCommit) {
|
|
150554
|
-
|
|
150555
|
-
|
|
150556
|
-
|
|
150557
|
-
|
|
151025
|
+
if (corpusLoaded) {
|
|
151026
|
+
observations = await store.loadAll();
|
|
151027
|
+
nextId = await store.loadIdCounter();
|
|
151028
|
+
if (upsertedInsideLock) {
|
|
151029
|
+
observation = observations.find((candidate) => candidate.id === observation.id) ?? observation;
|
|
151030
|
+
}
|
|
151031
|
+
} else {
|
|
151032
|
+
nextId = await store.loadIdCounter();
|
|
150558
151033
|
}
|
|
150559
151034
|
} else {
|
|
150560
|
-
observations.push(observation);
|
|
151035
|
+
if (corpusLoaded) observations.push(observation);
|
|
150561
151036
|
nextId = observation.id + 1;
|
|
150562
151037
|
}
|
|
150563
151038
|
if (upsertedInsideLock) return;
|
|
@@ -150625,7 +151100,9 @@ async function storeObservation(input) {
|
|
|
150625
151100
|
createdByAgentId: input.createdByAgentId ?? "",
|
|
150626
151101
|
sharedWithAgentIds: JSON.stringify(input.sharedWithAgentIds ?? [])
|
|
150627
151102
|
};
|
|
150628
|
-
|
|
151103
|
+
if (corpusLoaded) {
|
|
151104
|
+
await insertObservation(doc);
|
|
151105
|
+
}
|
|
150629
151106
|
};
|
|
150630
151107
|
await assignAndPersist();
|
|
150631
151108
|
if (upsertedInsideLock) {
|
|
@@ -150987,9 +151464,11 @@ async function reindexObservations() {
|
|
|
150987
151464
|
searchIndexPrepared = true;
|
|
150988
151465
|
return count2;
|
|
150989
151466
|
}
|
|
150990
|
-
async function prepareSearchIndex() {
|
|
151467
|
+
async function prepareSearchIndex(options = {}) {
|
|
150991
151468
|
if (searchIndexPrepared) return 0;
|
|
150992
|
-
const count2 = await hydrateIndexForStartup(observations
|
|
151469
|
+
const count2 = await hydrateIndexForStartup(observations, {
|
|
151470
|
+
skipCachedVectors: options.skipCachedVectors
|
|
151471
|
+
});
|
|
150993
151472
|
if (count2 === 0) {
|
|
150994
151473
|
searchIndexPrepared = true;
|
|
150995
151474
|
return 0;
|
|
@@ -151181,7 +151660,7 @@ async function backfillVectorEmbeddings(options = {}) {
|
|
|
151181
151660
|
...lastFailure ? { lastError: lastFailure } : {}
|
|
151182
151661
|
};
|
|
151183
151662
|
}
|
|
151184
|
-
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
151663
|
+
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, corpusLoaded, loadedObservationStore, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
151185
151664
|
var init_observations = __esm({
|
|
151186
151665
|
"src/memory/observations.ts"() {
|
|
151187
151666
|
"use strict";
|
|
@@ -151200,6 +151679,8 @@ var init_observations = __esm({
|
|
|
151200
151679
|
projectDir = null;
|
|
151201
151680
|
searchIndexPrepared = false;
|
|
151202
151681
|
embeddingWriteMode = "background";
|
|
151682
|
+
corpusLoaded = false;
|
|
151683
|
+
loadedObservationStore = null;
|
|
151203
151684
|
vectorMissingIds = /* @__PURE__ */ new Set();
|
|
151204
151685
|
vectorBackfillRunning = false;
|
|
151205
151686
|
vectorSchemaUpgradePromise = null;
|
|
@@ -153788,8 +154269,8 @@ var init_syncer = __esm({
|
|
|
153788
154269
|
const dir = path25.dirname(pattern);
|
|
153789
154270
|
const fileGlob = path25.basename(pattern);
|
|
153790
154271
|
try {
|
|
153791
|
-
const
|
|
153792
|
-
if (!
|
|
154272
|
+
const stat5 = await fs17.stat(dir);
|
|
154273
|
+
if (!stat5.isDirectory()) {
|
|
153793
154274
|
try {
|
|
153794
154275
|
await fs17.access(pattern);
|
|
153795
154276
|
return [pattern];
|
|
@@ -159380,9 +159861,9 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
159380
159861
|
const absolute = path28.join(rootPath, candidate);
|
|
159381
159862
|
try {
|
|
159382
159863
|
if (!existsSync16(absolute)) continue;
|
|
159383
|
-
const
|
|
159384
|
-
if (
|
|
159385
|
-
if (
|
|
159864
|
+
const stat5 = statSync4(absolute);
|
|
159865
|
+
if (stat5.isFile()) out.push(candidate);
|
|
159866
|
+
if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
|
|
159386
159867
|
} catch {
|
|
159387
159868
|
}
|
|
159388
159869
|
}
|
|
@@ -165202,13 +165683,13 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
165202
165683
|
const agentPrev = prevFiles.filter((e2) => e2.agent === agent);
|
|
165203
165684
|
for (const entry of agentPrev) {
|
|
165204
165685
|
try {
|
|
165205
|
-
const { access:
|
|
165206
|
-
await
|
|
165686
|
+
const { access: access3, unlink: unlink3 } = await import("fs/promises");
|
|
165687
|
+
await access3(entry.path);
|
|
165207
165688
|
const basename5 = path32.basename(entry.path);
|
|
165208
165689
|
if (basename5 === "AGENTS.md" || basename5 === "GEMINI.md" || basename5 === "CONTEXT.md") {
|
|
165209
165690
|
continue;
|
|
165210
165691
|
}
|
|
165211
|
-
await
|
|
165692
|
+
await unlink3(entry.path);
|
|
165212
165693
|
await removeFile2(projectRoot, entry.path);
|
|
165213
165694
|
} catch {
|
|
165214
165695
|
}
|
|
@@ -165728,11 +166209,11 @@ import path33 from "path";
|
|
|
165728
166209
|
function resolveGitDir(projectRoot) {
|
|
165729
166210
|
const dotGit = path33.join(projectRoot, ".git");
|
|
165730
166211
|
if (!existsSync19(dotGit)) return null;
|
|
165731
|
-
const
|
|
165732
|
-
if (
|
|
166212
|
+
const stat5 = statSync5(dotGit);
|
|
166213
|
+
if (stat5.isDirectory()) {
|
|
165733
166214
|
return dotGit;
|
|
165734
166215
|
}
|
|
165735
|
-
if (
|
|
166216
|
+
if (stat5.isFile()) {
|
|
165736
166217
|
try {
|
|
165737
166218
|
const content = readFileSync13(dotGit, "utf-8").trim();
|
|
165738
166219
|
const match2 = content.match(/^gitdir:\s*(.+)$/);
|
|
@@ -166143,7 +166624,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
166143
166624
|
};
|
|
166144
166625
|
const server = existingServer ?? new McpServer({
|
|
166145
166626
|
name: "memorix",
|
|
166146
|
-
version: true ? "1.6.
|
|
166627
|
+
version: true ? "1.6.2" : "1.0.1"
|
|
166147
166628
|
});
|
|
166148
166629
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
166149
166630
|
server.registerTool = ((name, ...args) => {
|
|
@@ -170549,7 +171030,7 @@ var init_serve_shared = __esm({
|
|
|
170549
171030
|
|
|
170550
171031
|
// src/cli/version.ts
|
|
170551
171032
|
function getCliVersion() {
|
|
170552
|
-
return true ? "1.6.
|
|
171033
|
+
return true ? "1.6.2" : pkg.version;
|
|
170553
171034
|
}
|
|
170554
171035
|
var init_version3 = __esm({
|
|
170555
171036
|
"src/cli/version.ts"() {
|