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/sdk.js
CHANGED
|
@@ -249,6 +249,14 @@ var init_bun_sqlite_compat = __esm({
|
|
|
249
249
|
});
|
|
250
250
|
|
|
251
251
|
// src/store/sqlite-db.ts
|
|
252
|
+
var sqlite_db_exports = {};
|
|
253
|
+
__export(sqlite_db_exports, {
|
|
254
|
+
closeAllDatabases: () => closeAllDatabases,
|
|
255
|
+
closeDatabase: () => closeDatabase,
|
|
256
|
+
getDatabase: () => getDatabase,
|
|
257
|
+
isSqliteAvailable: () => isSqliteAvailable,
|
|
258
|
+
loadBetterSqlite3: () => loadBetterSqlite3
|
|
259
|
+
});
|
|
252
260
|
import "module";
|
|
253
261
|
import path2 from "path";
|
|
254
262
|
import fs from "fs";
|
|
@@ -354,6 +362,17 @@ function getDatabase(dataDir) {
|
|
|
354
362
|
_dbCache.set(normalized, db2);
|
|
355
363
|
return db2;
|
|
356
364
|
}
|
|
365
|
+
function closeDatabase(dataDir) {
|
|
366
|
+
const normalized = path2.resolve(dataDir);
|
|
367
|
+
const db2 = _dbCache.get(normalized);
|
|
368
|
+
if (db2) {
|
|
369
|
+
try {
|
|
370
|
+
db2.close();
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
_dbCache.delete(normalized);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
357
376
|
function closeAllDatabases() {
|
|
358
377
|
for (const [key, db2] of _dbCache) {
|
|
359
378
|
try {
|
|
@@ -363,6 +382,14 @@ function closeAllDatabases() {
|
|
|
363
382
|
_dbCache.delete(key);
|
|
364
383
|
}
|
|
365
384
|
}
|
|
385
|
+
function isSqliteAvailable() {
|
|
386
|
+
try {
|
|
387
|
+
loadBetterSqlite3();
|
|
388
|
+
return true;
|
|
389
|
+
} catch {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
366
393
|
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
367
394
|
var init_sqlite_db = __esm({
|
|
368
395
|
"src/store/sqlite-db.ts"() {
|
|
@@ -1246,8 +1273,8 @@ async function acquireLock(lockPath) {
|
|
|
1246
1273
|
const code = err instanceof Error && "code" in err ? err.code : void 0;
|
|
1247
1274
|
if (code === "EEXIST" || code === "EPERM") {
|
|
1248
1275
|
try {
|
|
1249
|
-
const
|
|
1250
|
-
if (Date.now() -
|
|
1276
|
+
const stat5 = await fs2.stat(lockPath);
|
|
1277
|
+
if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
|
|
1251
1278
|
await fs2.unlink(lockPath).catch(() => {
|
|
1252
1279
|
});
|
|
1253
1280
|
continue;
|
|
@@ -3717,24 +3744,131 @@ var init_transformers_provider = __esm({
|
|
|
3717
3744
|
// src/embedding/api-provider.ts
|
|
3718
3745
|
var api_provider_exports = {};
|
|
3719
3746
|
__export(api_provider_exports, {
|
|
3720
|
-
APIEmbeddingProvider: () => APIEmbeddingProvider
|
|
3747
|
+
APIEmbeddingProvider: () => APIEmbeddingProvider,
|
|
3748
|
+
convertArrayCacheToJsonl: () => convertArrayCacheToJsonl,
|
|
3749
|
+
ensureDiskCacheLoaded: () => ensureDiskCacheLoaded,
|
|
3750
|
+
getApiEmbeddingCachePayloadBytesForTests: () => getApiEmbeddingCachePayloadBytesForTests,
|
|
3751
|
+
getApiEmbeddingDiskCacheLoadCountForTests: () => getApiEmbeddingDiskCacheLoadCountForTests,
|
|
3752
|
+
getApiEmbeddingJsonlLineCountCallsForTests: () => getApiEmbeddingJsonlLineCountCallsForTests,
|
|
3753
|
+
getApiEmbeddingMaxEntriesForDimensionsForTests: () => getApiEmbeddingMaxEntriesForDimensionsForTests,
|
|
3754
|
+
migrateJsonArrayCacheToJsonl: () => migrateJsonArrayCacheToJsonl,
|
|
3755
|
+
parseCacheJsonInWorker: () => parseCacheJsonInWorker,
|
|
3756
|
+
resetApiEmbeddingCacheForTests: () => resetApiEmbeddingCacheForTests,
|
|
3757
|
+
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
3758
|
+
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
3721
3759
|
});
|
|
3722
3760
|
import { createHash as createHash2 } from "crypto";
|
|
3723
|
-
import {
|
|
3761
|
+
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
3762
|
+
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
3724
3763
|
import { join as join3 } from "path";
|
|
3725
3764
|
import { homedir as homedir7 } from "os";
|
|
3765
|
+
import { createInterface } from "readline";
|
|
3726
3766
|
function cacheDir() {
|
|
3727
3767
|
return process.env.MEMORIX_DATA_DIR || join3(homedir7(), ".memorix", "data");
|
|
3728
3768
|
}
|
|
3729
3769
|
function cacheFile() {
|
|
3730
3770
|
return join3(cacheDir(), ".embedding-api-cache.json");
|
|
3731
3771
|
}
|
|
3772
|
+
function cacheJsonlFile() {
|
|
3773
|
+
return join3(cacheDir(), ".embedding-api-cache.jsonl");
|
|
3774
|
+
}
|
|
3732
3775
|
function dimsCacheFile() {
|
|
3733
3776
|
return join3(cacheDir(), ".embedding-dims-cache.json");
|
|
3734
3777
|
}
|
|
3735
3778
|
function cacheMetaFile() {
|
|
3736
3779
|
return join3(cacheDir(), ".embedding-api-cache-meta.json");
|
|
3737
3780
|
}
|
|
3781
|
+
function cacheStatFile() {
|
|
3782
|
+
return join3(cacheDir(), ".embedding-api-cache-stat.json");
|
|
3783
|
+
}
|
|
3784
|
+
function payloadBytes(vector) {
|
|
3785
|
+
return vector.length * BYTES_PER_DIM;
|
|
3786
|
+
}
|
|
3787
|
+
function maxCachePayloadBytes() {
|
|
3788
|
+
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
3789
|
+
if (raw) {
|
|
3790
|
+
const parsed = Number.parseInt(raw, 10);
|
|
3791
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
3792
|
+
}
|
|
3793
|
+
return MAX_CACHE_PAYLOAD_BYTES;
|
|
3794
|
+
}
|
|
3795
|
+
function maxEntriesForDimensions(dimensions) {
|
|
3796
|
+
const dim = Math.max(1, Math.floor(dimensions));
|
|
3797
|
+
const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
|
|
3798
|
+
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
3799
|
+
}
|
|
3800
|
+
function rememberDimensions(vector) {
|
|
3801
|
+
if (vector.length > 0 && (cacheDimensions === null || vector.length > cacheDimensions)) {
|
|
3802
|
+
cacheDimensions = vector.length;
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
function evictOldest() {
|
|
3806
|
+
const firstKey = cache3.keys().next().value;
|
|
3807
|
+
if (firstKey === void 0) return;
|
|
3808
|
+
const old = cache3.get(firstKey);
|
|
3809
|
+
cache3.delete(firstKey);
|
|
3810
|
+
if (old) cachePayloadBytes -= payloadBytes(old);
|
|
3811
|
+
}
|
|
3812
|
+
function evictToFit(incomingBytes, incomingDims) {
|
|
3813
|
+
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
3814
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
|
|
3815
|
+
evictOldest();
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
function isNumberArray(value) {
|
|
3819
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
3820
|
+
}
|
|
3821
|
+
function parseCacheRow(raw) {
|
|
3822
|
+
if (Array.isArray(raw)) {
|
|
3823
|
+
const hash4 = raw[0];
|
|
3824
|
+
const vector = raw[1];
|
|
3825
|
+
if (typeof hash4 === "string" && isNumberArray(vector)) {
|
|
3826
|
+
return { hash: hash4, vector };
|
|
3827
|
+
}
|
|
3828
|
+
return null;
|
|
3829
|
+
}
|
|
3830
|
+
if (raw && typeof raw === "object") {
|
|
3831
|
+
const row = raw;
|
|
3832
|
+
if (typeof row.h === "string" && isNumberArray(row.v)) {
|
|
3833
|
+
return { hash: row.h, vector: row.v };
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
return null;
|
|
3837
|
+
}
|
|
3838
|
+
function cacheInsert(hash4, value, dirty) {
|
|
3839
|
+
rememberDimensions(value);
|
|
3840
|
+
const incoming = payloadBytes(value);
|
|
3841
|
+
const existing = cache3.get(hash4);
|
|
3842
|
+
if (existing) {
|
|
3843
|
+
cachePayloadBytes -= payloadBytes(existing);
|
|
3844
|
+
cache3.delete(hash4);
|
|
3845
|
+
}
|
|
3846
|
+
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
3847
|
+
cache3.set(hash4, value);
|
|
3848
|
+
cachePayloadBytes += incoming;
|
|
3849
|
+
if (dirty) diskCacheDirty2 = true;
|
|
3850
|
+
}
|
|
3851
|
+
async function readCacheStat() {
|
|
3852
|
+
try {
|
|
3853
|
+
const data = JSON.parse(await readFile2(cacheStatFile(), "utf-8"));
|
|
3854
|
+
if (typeof data.entryCount === "number" && Number.isFinite(data.entryCount) && data.entryCount >= 0) {
|
|
3855
|
+
return {
|
|
3856
|
+
version: 1,
|
|
3857
|
+
entryCount: Math.floor(data.entryCount),
|
|
3858
|
+
dimensions: isValidDimension(data.dimensions) ? data.dimensions : null
|
|
3859
|
+
};
|
|
3860
|
+
}
|
|
3861
|
+
} catch {
|
|
3862
|
+
}
|
|
3863
|
+
return null;
|
|
3864
|
+
}
|
|
3865
|
+
async function writeCacheStat(stat5) {
|
|
3866
|
+
try {
|
|
3867
|
+
await mkdir2(cacheDir(), { recursive: true });
|
|
3868
|
+
await writeFile2(cacheStatFile(), JSON.stringify(stat5));
|
|
3869
|
+
} catch {
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3738
3872
|
function normalizeText(text2) {
|
|
3739
3873
|
return text2.replace(/\s+/g, " ").trim().slice(0, MAX_INPUT_CHARS);
|
|
3740
3874
|
}
|
|
@@ -3820,29 +3954,300 @@ function toProviderInput(input, baseUrl) {
|
|
|
3820
3954
|
}
|
|
3821
3955
|
return { type: input.modality, url: input.url };
|
|
3822
3956
|
}
|
|
3957
|
+
function parseCacheJsonInWorker(filePath) {
|
|
3958
|
+
return new Promise((resolve2, reject) => {
|
|
3959
|
+
void import("worker_threads").then(({ Worker }) => {
|
|
3960
|
+
const worker = new Worker(
|
|
3961
|
+
`
|
|
3962
|
+
const { parentPort, workerData } = require('node:worker_threads');
|
|
3963
|
+
const { readFileSync } = require('node:fs');
|
|
3964
|
+
try {
|
|
3965
|
+
const raw = readFileSync(workerData.filePath, 'utf8');
|
|
3966
|
+
parentPort.postMessage({ ok: true, entries: JSON.parse(raw) });
|
|
3967
|
+
} catch (err) {
|
|
3968
|
+
parentPort.postMessage({
|
|
3969
|
+
ok: false,
|
|
3970
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3971
|
+
});
|
|
3972
|
+
}
|
|
3973
|
+
`,
|
|
3974
|
+
{ eval: true, workerData: { filePath } }
|
|
3975
|
+
);
|
|
3976
|
+
worker.once("message", (msg) => {
|
|
3977
|
+
void worker.terminate();
|
|
3978
|
+
if (msg?.ok && Array.isArray(msg.entries)) {
|
|
3979
|
+
resolve2(msg.entries);
|
|
3980
|
+
return;
|
|
3981
|
+
}
|
|
3982
|
+
reject(new Error(msg?.error || "embedding cache worker parse failed"));
|
|
3983
|
+
});
|
|
3984
|
+
worker.once("error", reject);
|
|
3985
|
+
}).catch(reject);
|
|
3986
|
+
});
|
|
3987
|
+
}
|
|
3988
|
+
function findJsonValueEnd(source) {
|
|
3989
|
+
let i2 = 0;
|
|
3990
|
+
while (i2 < source.length && /\s/.test(source[i2])) i2 += 1;
|
|
3991
|
+
if (i2 >= source.length) return -1;
|
|
3992
|
+
const start = source[i2];
|
|
3993
|
+
if (start === '"') {
|
|
3994
|
+
i2 += 1;
|
|
3995
|
+
while (i2 < source.length) {
|
|
3996
|
+
if (source[i2] === "\\") {
|
|
3997
|
+
i2 += 2;
|
|
3998
|
+
continue;
|
|
3999
|
+
}
|
|
4000
|
+
if (source[i2] === '"') return i2 + 1;
|
|
4001
|
+
i2 += 1;
|
|
4002
|
+
}
|
|
4003
|
+
return -1;
|
|
4004
|
+
}
|
|
4005
|
+
if (start === "{" || start === "[") {
|
|
4006
|
+
const close = start === "{" ? "}" : "]";
|
|
4007
|
+
let depth = 0;
|
|
4008
|
+
let inString = false;
|
|
4009
|
+
for (; i2 < source.length; i2 += 1) {
|
|
4010
|
+
const ch = source[i2];
|
|
4011
|
+
if (inString) {
|
|
4012
|
+
if (ch === "\\") {
|
|
4013
|
+
i2 += 1;
|
|
4014
|
+
continue;
|
|
4015
|
+
}
|
|
4016
|
+
if (ch === '"') inString = false;
|
|
4017
|
+
continue;
|
|
4018
|
+
}
|
|
4019
|
+
if (ch === '"') {
|
|
4020
|
+
inString = true;
|
|
4021
|
+
continue;
|
|
4022
|
+
}
|
|
4023
|
+
if (ch === start) depth += 1;
|
|
4024
|
+
else if (ch === close) {
|
|
4025
|
+
depth -= 1;
|
|
4026
|
+
if (depth === 0) return i2 + 1;
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
return -1;
|
|
4030
|
+
}
|
|
4031
|
+
const rest = source.slice(i2);
|
|
4032
|
+
const match2 = rest.match(/^(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/);
|
|
4033
|
+
return match2 ? i2 + match2[0].length : -1;
|
|
4034
|
+
}
|
|
4035
|
+
async function streamJsonArrayToJsonl(filePath, tmpPath) {
|
|
4036
|
+
const input = createReadStream(filePath, { encoding: "utf8" });
|
|
4037
|
+
const out = createWriteStream(tmpPath);
|
|
4038
|
+
let buf = "";
|
|
4039
|
+
let started = false;
|
|
4040
|
+
let count2 = 0;
|
|
4041
|
+
const writeLine = async (line) => {
|
|
4042
|
+
if (!out.write(line)) {
|
|
4043
|
+
await new Promise((resolve2, reject) => {
|
|
4044
|
+
out.once("drain", resolve2);
|
|
4045
|
+
out.once("error", reject);
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
4048
|
+
};
|
|
4049
|
+
try {
|
|
4050
|
+
for await (const chunk of input) {
|
|
4051
|
+
buf += chunk;
|
|
4052
|
+
if (!started) {
|
|
4053
|
+
const idx = buf.search(/\S/);
|
|
4054
|
+
if (idx < 0) continue;
|
|
4055
|
+
if (buf[idx] !== "[") throw new Error("embedding cache is not a JSON array");
|
|
4056
|
+
buf = buf.slice(idx + 1);
|
|
4057
|
+
started = true;
|
|
4058
|
+
}
|
|
4059
|
+
while (true) {
|
|
4060
|
+
buf = buf.replace(/^\s*,?\s*/, "");
|
|
4061
|
+
if (!buf) break;
|
|
4062
|
+
if (buf[0] === "]") {
|
|
4063
|
+
buf = "";
|
|
4064
|
+
break;
|
|
4065
|
+
}
|
|
4066
|
+
const end = findJsonValueEnd(buf);
|
|
4067
|
+
if (end < 0) break;
|
|
4068
|
+
const value = JSON.parse(buf.slice(0, end));
|
|
4069
|
+
buf = buf.slice(end);
|
|
4070
|
+
const row = parseCacheRow(value);
|
|
4071
|
+
if (row) {
|
|
4072
|
+
await writeLine(`${JSON.stringify({ h: row.hash, v: row.vector })}
|
|
4073
|
+
`);
|
|
4074
|
+
count2 += 1;
|
|
4075
|
+
if (count2 % 50 === 0) {
|
|
4076
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
if (buf.length > MAX_MIGRATION_VALUE_BYTES) {
|
|
4081
|
+
throw new Error("embedding cache entry too large to migrate safely");
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
} finally {
|
|
4085
|
+
await new Promise((resolve2, reject) => {
|
|
4086
|
+
out.end(() => resolve2());
|
|
4087
|
+
out.once("error", reject);
|
|
4088
|
+
});
|
|
4089
|
+
}
|
|
4090
|
+
return count2;
|
|
4091
|
+
}
|
|
4092
|
+
async function migrateJsonArrayCacheToJsonl(filePath, jsonlPath) {
|
|
4093
|
+
const tmpPath = `${jsonlPath}.tmp`;
|
|
4094
|
+
try {
|
|
4095
|
+
const count2 = await streamJsonArrayToJsonl(filePath, tmpPath);
|
|
4096
|
+
await rename(tmpPath, jsonlPath);
|
|
4097
|
+
diskCacheEntryCount = count2;
|
|
4098
|
+
await writeCacheStat({
|
|
4099
|
+
version: 1,
|
|
4100
|
+
entryCount: count2,
|
|
4101
|
+
dimensions: cacheDimensions
|
|
4102
|
+
});
|
|
4103
|
+
return count2;
|
|
4104
|
+
} catch (err) {
|
|
4105
|
+
await unlink(tmpPath).catch(() => void 0);
|
|
4106
|
+
throw err;
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
function convertArrayCacheToJsonl(filePath, jsonlPath) {
|
|
4110
|
+
return migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
|
|
4111
|
+
}
|
|
4112
|
+
async function loadCacheJsonl(filePath) {
|
|
4113
|
+
const rl = createInterface({
|
|
4114
|
+
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
4115
|
+
crlfDelay: Infinity
|
|
4116
|
+
});
|
|
4117
|
+
let loaded = 0;
|
|
4118
|
+
let onDiskCount = 0;
|
|
4119
|
+
for await (const line of rl) {
|
|
4120
|
+
const trimmed = line.trim();
|
|
4121
|
+
if (!trimmed) continue;
|
|
4122
|
+
try {
|
|
4123
|
+
const row = parseCacheRow(JSON.parse(trimmed));
|
|
4124
|
+
if (!row) continue;
|
|
4125
|
+
onDiskCount += 1;
|
|
4126
|
+
cacheInsert(row.hash, row.vector, false);
|
|
4127
|
+
loaded = cache3.size;
|
|
4128
|
+
} catch {
|
|
4129
|
+
}
|
|
4130
|
+
if (onDiskCount % 250 === 0) {
|
|
4131
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
diskCacheEntryCount = onDiskCount;
|
|
4135
|
+
await writeCacheStat({
|
|
4136
|
+
version: 1,
|
|
4137
|
+
entryCount: onDiskCount,
|
|
4138
|
+
dimensions: cacheDimensions
|
|
4139
|
+
});
|
|
4140
|
+
return loaded;
|
|
4141
|
+
}
|
|
4142
|
+
async function countJsonlLines(filePath) {
|
|
4143
|
+
jsonlLineCountCalls += 1;
|
|
4144
|
+
try {
|
|
4145
|
+
const rl = createInterface({
|
|
4146
|
+
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
4147
|
+
crlfDelay: Infinity
|
|
4148
|
+
});
|
|
4149
|
+
let count2 = 0;
|
|
4150
|
+
for await (const line of rl) {
|
|
4151
|
+
if (line.trim()) count2 += 1;
|
|
4152
|
+
}
|
|
4153
|
+
return count2;
|
|
4154
|
+
} catch {
|
|
4155
|
+
return 0;
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
async function resolveOnDiskCount(jsonlPath) {
|
|
4159
|
+
if (diskCacheEntryCount > 0) return diskCacheEntryCount;
|
|
4160
|
+
const sidecar = await readCacheStat();
|
|
4161
|
+
if (sidecar) {
|
|
4162
|
+
diskCacheEntryCount = sidecar.entryCount;
|
|
4163
|
+
if (sidecar.dimensions && cacheDimensions === null) cacheDimensions = sidecar.dimensions;
|
|
4164
|
+
return sidecar.entryCount;
|
|
4165
|
+
}
|
|
4166
|
+
try {
|
|
4167
|
+
await access(jsonlPath, fsConstants.R_OK);
|
|
4168
|
+
} catch {
|
|
4169
|
+
return 0;
|
|
4170
|
+
}
|
|
4171
|
+
const counted = await countJsonlLines(jsonlPath);
|
|
4172
|
+
diskCacheEntryCount = counted;
|
|
4173
|
+
await writeCacheStat({
|
|
4174
|
+
version: 1,
|
|
4175
|
+
entryCount: counted,
|
|
4176
|
+
dimensions: cacheDimensions
|
|
4177
|
+
});
|
|
4178
|
+
return counted;
|
|
4179
|
+
}
|
|
3823
4180
|
async function loadDiskCache2() {
|
|
3824
|
-
if (diskCacheLoaded) return;
|
|
4181
|
+
if (diskCacheLoaded) return cache3.size;
|
|
4182
|
+
let loaded = 0;
|
|
3825
4183
|
try {
|
|
3826
|
-
const
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
4184
|
+
const jsonlPath = cacheJsonlFile();
|
|
4185
|
+
let hasJsonl = false;
|
|
4186
|
+
try {
|
|
4187
|
+
await access(jsonlPath, fsConstants.R_OK);
|
|
4188
|
+
hasJsonl = true;
|
|
4189
|
+
} catch {
|
|
4190
|
+
hasJsonl = false;
|
|
4191
|
+
}
|
|
4192
|
+
if (hasJsonl) {
|
|
4193
|
+
loaded = await loadCacheJsonl(jsonlPath);
|
|
4194
|
+
} else {
|
|
4195
|
+
const filePath = cacheFile();
|
|
4196
|
+
await stat(filePath);
|
|
4197
|
+
await migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
|
|
4198
|
+
loaded = await loadCacheJsonl(jsonlPath);
|
|
4199
|
+
}
|
|
4200
|
+
diskCacheLoadCount += 1;
|
|
4201
|
+
console.error(`[memorix] Loaded ${loaded} cached API embeddings from disk`);
|
|
3830
4202
|
} catch {
|
|
3831
4203
|
}
|
|
3832
4204
|
diskCacheLoaded = true;
|
|
4205
|
+
return loaded;
|
|
3833
4206
|
}
|
|
3834
4207
|
function startDiskCacheLoad() {
|
|
3835
4208
|
if (diskCacheLoaded || diskCacheLoadPromise) return;
|
|
3836
|
-
diskCacheLoadPromise = loadDiskCache2().catch(() => {
|
|
4209
|
+
diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
|
|
3837
4210
|
});
|
|
3838
4211
|
}
|
|
3839
4212
|
async function ensureDiskCacheLoaded() {
|
|
3840
|
-
if (diskCacheLoaded) return;
|
|
3841
|
-
if (diskCacheLoadPromise) {
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
}
|
|
3845
|
-
await
|
|
4213
|
+
if (diskCacheLoaded) return cache3.size;
|
|
4214
|
+
if (!diskCacheLoadPromise) {
|
|
4215
|
+
diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
|
|
4216
|
+
});
|
|
4217
|
+
}
|
|
4218
|
+
await diskCacheLoadPromise;
|
|
4219
|
+
return cache3.size;
|
|
4220
|
+
}
|
|
4221
|
+
function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
4222
|
+
return diskCacheLoadCount;
|
|
4223
|
+
}
|
|
4224
|
+
function resetApiEmbeddingCacheForTests() {
|
|
4225
|
+
cache3.clear();
|
|
4226
|
+
cachePayloadBytes = 0;
|
|
4227
|
+
cacheDimensions = null;
|
|
4228
|
+
diskCacheEntryCount = 0;
|
|
4229
|
+
diskCacheLoaded = false;
|
|
4230
|
+
diskCacheLoadPromise = null;
|
|
4231
|
+
diskCacheLoadCount = 0;
|
|
4232
|
+
diskCacheDirty2 = false;
|
|
4233
|
+
jsonlLineCountCalls = 0;
|
|
4234
|
+
}
|
|
4235
|
+
function seedApiEmbeddingCacheForTests(entries) {
|
|
4236
|
+
cache3.clear();
|
|
4237
|
+
cachePayloadBytes = 0;
|
|
4238
|
+
cacheDimensions = null;
|
|
4239
|
+
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
4240
|
+
diskCacheLoaded = true;
|
|
4241
|
+
diskCacheDirty2 = true;
|
|
4242
|
+
}
|
|
4243
|
+
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
4244
|
+
return cachePayloadBytes;
|
|
4245
|
+
}
|
|
4246
|
+
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
4247
|
+
return jsonlLineCountCalls;
|
|
4248
|
+
}
|
|
4249
|
+
function getApiEmbeddingMaxEntriesForDimensionsForTests(dimensions) {
|
|
4250
|
+
return maxEntriesForDimensions(dimensions);
|
|
3846
4251
|
}
|
|
3847
4252
|
function dimsCacheKey(config) {
|
|
3848
4253
|
return [
|
|
@@ -3958,8 +4363,46 @@ async function saveDiskCacheNow() {
|
|
|
3958
4363
|
if (!diskCacheDirty2) return;
|
|
3959
4364
|
try {
|
|
3960
4365
|
await mkdir2(cacheDir(), { recursive: true });
|
|
3961
|
-
const
|
|
3962
|
-
await
|
|
4366
|
+
const jsonlPath = cacheJsonlFile();
|
|
4367
|
+
const existing = await resolveOnDiskCount(jsonlPath);
|
|
4368
|
+
if (existing > 0 && cache3.size < Math.ceil(existing * 0.5)) {
|
|
4369
|
+
console.error(
|
|
4370
|
+
`[memorix] Refusing to overwrite embedding cache (${existing} on disk vs ${cache3.size} in memory)`
|
|
4371
|
+
);
|
|
4372
|
+
diskCacheDirty2 = false;
|
|
4373
|
+
return;
|
|
4374
|
+
}
|
|
4375
|
+
const tmpPath = `${jsonlPath}.tmp`;
|
|
4376
|
+
await new Promise((resolve2, reject) => {
|
|
4377
|
+
const out = createWriteStream(tmpPath);
|
|
4378
|
+
const entries = cache3.entries();
|
|
4379
|
+
const writeBatch = () => {
|
|
4380
|
+
for (let i2 = 0; i2 < 50; i2++) {
|
|
4381
|
+
const next = entries.next();
|
|
4382
|
+
if (next.done) {
|
|
4383
|
+
out.end();
|
|
4384
|
+
return;
|
|
4385
|
+
}
|
|
4386
|
+
const [hash4, vector] = next.value;
|
|
4387
|
+
if (!out.write(`${JSON.stringify({ h: hash4, v: vector })}
|
|
4388
|
+
`)) {
|
|
4389
|
+
out.once("drain", writeBatch);
|
|
4390
|
+
return;
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
setImmediate(writeBatch);
|
|
4394
|
+
};
|
|
4395
|
+
out.on("finish", resolve2);
|
|
4396
|
+
out.on("error", reject);
|
|
4397
|
+
writeBatch();
|
|
4398
|
+
});
|
|
4399
|
+
await rename(tmpPath, jsonlPath);
|
|
4400
|
+
diskCacheEntryCount = cache3.size;
|
|
4401
|
+
await writeCacheStat({
|
|
4402
|
+
version: 1,
|
|
4403
|
+
entryCount: cache3.size,
|
|
4404
|
+
dimensions: cacheDimensions
|
|
4405
|
+
});
|
|
3963
4406
|
diskCacheDirty2 = false;
|
|
3964
4407
|
} catch {
|
|
3965
4408
|
}
|
|
@@ -3973,12 +4416,7 @@ function scheduleDiskSave() {
|
|
|
3973
4416
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
3974
4417
|
}
|
|
3975
4418
|
function cacheSet(hash4, value) {
|
|
3976
|
-
|
|
3977
|
-
const firstKey = cache3.keys().next().value;
|
|
3978
|
-
if (firstKey !== void 0) cache3.delete(firstKey);
|
|
3979
|
-
}
|
|
3980
|
-
cache3.set(hash4, value);
|
|
3981
|
-
diskCacheDirty2 = true;
|
|
4419
|
+
cacheInsert(hash4, value, true);
|
|
3982
4420
|
}
|
|
3983
4421
|
function resolveEnvEmbeddingApiKey() {
|
|
3984
4422
|
return process.env.MEMORIX_EMBEDDING_API_KEY;
|
|
@@ -4097,18 +4535,27 @@ async function waitForRetry(waitMs, signal) {
|
|
|
4097
4535
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
4098
4536
|
});
|
|
4099
4537
|
}
|
|
4100
|
-
var cache3,
|
|
4538
|
+
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;
|
|
4101
4539
|
var init_api_provider = __esm({
|
|
4102
4540
|
"src/embedding/api-provider.ts"() {
|
|
4103
4541
|
"use strict";
|
|
4104
4542
|
init_esm_shims();
|
|
4105
4543
|
init_provider();
|
|
4106
4544
|
cache3 = /* @__PURE__ */ new Map();
|
|
4107
|
-
|
|
4545
|
+
MAX_CACHE_ENTRIES = 2e5;
|
|
4546
|
+
MAX_CACHE_PAYLOAD_BYTES = 256 * 1024 * 1024;
|
|
4547
|
+
BYTES_PER_DIM = 8;
|
|
4548
|
+
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
4549
|
+
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
4550
|
+
cachePayloadBytes = 0;
|
|
4551
|
+
cacheDimensions = null;
|
|
4552
|
+
diskCacheEntryCount = 0;
|
|
4108
4553
|
diskCacheDirty2 = false;
|
|
4109
4554
|
diskSaveTimer = null;
|
|
4110
4555
|
diskCacheLoaded = false;
|
|
4111
4556
|
diskCacheLoadPromise = null;
|
|
4557
|
+
diskCacheLoadCount = 0;
|
|
4558
|
+
jsonlLineCountCalls = 0;
|
|
4112
4559
|
MAX_INPUT_CHARS = 32e3;
|
|
4113
4560
|
MAX_CONCURRENCY = 4;
|
|
4114
4561
|
DISK_SAVE_DEBOUNCE_MS = 5e3;
|
|
@@ -4166,7 +4613,9 @@ var init_api_provider = __esm({
|
|
|
4166
4613
|
if (config.requestedDimensions) {
|
|
4167
4614
|
console.error(`[memorix] Dimension shortening: ${config.requestedDimensions}d requested`);
|
|
4168
4615
|
}
|
|
4169
|
-
|
|
4616
|
+
if (allowNetworkProbe) {
|
|
4617
|
+
startDiskCacheLoad();
|
|
4618
|
+
}
|
|
4170
4619
|
return new _APIEmbeddingProvider(config, probeDimensions);
|
|
4171
4620
|
}
|
|
4172
4621
|
static resolveConfig() {
|
|
@@ -4504,7 +4953,12 @@ function warnOnce(message) {
|
|
|
4504
4953
|
lastEmbeddingWarningAt = now3;
|
|
4505
4954
|
console.error(message);
|
|
4506
4955
|
}
|
|
4956
|
+
function embeddingModeToken() {
|
|
4957
|
+
return process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim() ?? "";
|
|
4958
|
+
}
|
|
4507
4959
|
function getEmbeddingMode2() {
|
|
4960
|
+
const token = embeddingModeToken();
|
|
4961
|
+
if (cachedEmbeddingMode && cachedEmbeddingModeToken === token) return cachedEmbeddingMode;
|
|
4508
4962
|
try {
|
|
4509
4963
|
let cfg;
|
|
4510
4964
|
try {
|
|
@@ -4513,10 +4967,17 @@ function getEmbeddingMode2() {
|
|
|
4513
4967
|
cfg = (init_config(), __toCommonJS(config_exports));
|
|
4514
4968
|
}
|
|
4515
4969
|
const { getEmbeddingMode: cfgMode } = cfg;
|
|
4516
|
-
|
|
4970
|
+
cachedEmbeddingMode = cfgMode();
|
|
4971
|
+
cachedEmbeddingModeToken = token;
|
|
4972
|
+
return cachedEmbeddingMode;
|
|
4517
4973
|
} catch {
|
|
4518
|
-
|
|
4519
|
-
|
|
4974
|
+
if (token === "fastembed" || token === "transformers" || token === "api" || token === "auto") {
|
|
4975
|
+
cachedEmbeddingMode = token;
|
|
4976
|
+
cachedEmbeddingModeToken = token;
|
|
4977
|
+
return token;
|
|
4978
|
+
}
|
|
4979
|
+
cachedEmbeddingMode = "off";
|
|
4980
|
+
cachedEmbeddingModeToken = token;
|
|
4520
4981
|
return "off";
|
|
4521
4982
|
}
|
|
4522
4983
|
}
|
|
@@ -4772,13 +5233,15 @@ function isEmbeddingExplicitlyDisabled() {
|
|
|
4772
5233
|
function resetProvider() {
|
|
4773
5234
|
provider = null;
|
|
4774
5235
|
initPromise = null;
|
|
5236
|
+
cachedEmbeddingMode = null;
|
|
5237
|
+
cachedEmbeddingModeToken = null;
|
|
4775
5238
|
lastInitWasTemporaryFailure = false;
|
|
4776
5239
|
lastFailureTimestamp = 0;
|
|
4777
5240
|
lastEmbeddingFailure = null;
|
|
4778
5241
|
lastEmbeddingWarning = "";
|
|
4779
5242
|
lastEmbeddingWarningAt = 0;
|
|
4780
5243
|
}
|
|
4781
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
5244
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, cachedEmbeddingMode, cachedEmbeddingModeToken, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4782
5245
|
var init_provider = __esm({
|
|
4783
5246
|
"src/embedding/provider.ts"() {
|
|
4784
5247
|
"use strict";
|
|
@@ -4802,6 +5265,8 @@ var init_provider = __esm({
|
|
|
4802
5265
|
MAX_INLINE_EMBEDDING_BYTES = 5 * 1024 * 1024;
|
|
4803
5266
|
provider = null;
|
|
4804
5267
|
initPromise = null;
|
|
5268
|
+
cachedEmbeddingMode = null;
|
|
5269
|
+
cachedEmbeddingModeToken = null;
|
|
4805
5270
|
lastInitWasTemporaryFailure = false;
|
|
4806
5271
|
lastEmbeddingFailure = null;
|
|
4807
5272
|
lastEmbeddingWarning = "";
|
|
@@ -6559,6 +7024,9 @@ async function attachCachedVectors(database, candidates) {
|
|
|
6559
7024
|
await update(database, candidates[index].id, { ...existing, embedding: vector });
|
|
6560
7025
|
} catch {
|
|
6561
7026
|
}
|
|
7027
|
+
if (index % 50 === 0) {
|
|
7028
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
7029
|
+
}
|
|
6562
7030
|
}
|
|
6563
7031
|
}
|
|
6564
7032
|
async function hydrateIndex(observations2, options = {}) {
|
|
@@ -6609,17 +7077,24 @@ async function hydrateIndex(observations2, options = {}) {
|
|
|
6609
7077
|
await insert2(database, doc);
|
|
6610
7078
|
rememberObservationDoc(doc);
|
|
6611
7079
|
inserted++;
|
|
7080
|
+
if (inserted % 50 === 0) {
|
|
7081
|
+
await new Promise((resolve2) => setImmediate(resolve2));
|
|
7082
|
+
}
|
|
7083
|
+
if (inserted % 200 === 0) {
|
|
7084
|
+
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
7085
|
+
}
|
|
6612
7086
|
} catch {
|
|
6613
7087
|
}
|
|
6614
7088
|
}
|
|
6615
|
-
deferredCachedVectorHydration = deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
|
|
7089
|
+
deferredCachedVectorHydration = options.skipCachedVectors ? null : deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
|
|
6616
7090
|
}) : null;
|
|
6617
7091
|
return inserted;
|
|
6618
7092
|
}
|
|
6619
|
-
async function hydrateIndexForStartup(observations2) {
|
|
7093
|
+
async function hydrateIndexForStartup(observations2, options = {}) {
|
|
6620
7094
|
return hydrateIndex(observations2, {
|
|
6621
7095
|
allowNetworkProbe: false,
|
|
6622
|
-
deferCachedVectors: true
|
|
7096
|
+
deferCachedVectors: true,
|
|
7097
|
+
skipCachedVectors: options.skipCachedVectors
|
|
6623
7098
|
});
|
|
6624
7099
|
}
|
|
6625
7100
|
function getDeferredCachedVectorHydration() {
|
|
@@ -9942,7 +10417,7 @@ __export(asset_store_exports, {
|
|
|
9942
10417
|
removeMediaAsset: () => removeMediaAsset
|
|
9943
10418
|
});
|
|
9944
10419
|
import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
|
|
9945
|
-
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename, rm, stat, writeFile as writeFile3 } from "fs/promises";
|
|
10420
|
+
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
9946
10421
|
import path13 from "path";
|
|
9947
10422
|
function mediaRoot(dataDir) {
|
|
9948
10423
|
return path13.resolve(dataDir, "media");
|
|
@@ -10032,7 +10507,7 @@ async function persistFile(source, destination) {
|
|
|
10032
10507
|
const temporary = `${destination}.${randomUUID5()}.tmp`;
|
|
10033
10508
|
try {
|
|
10034
10509
|
await copyFile(source, temporary);
|
|
10035
|
-
await
|
|
10510
|
+
await rename2(temporary, destination);
|
|
10036
10511
|
return true;
|
|
10037
10512
|
} catch (error) {
|
|
10038
10513
|
if (error?.code === "EEXIST" && await destinationExists(destination)) return false;
|
|
@@ -10048,7 +10523,7 @@ async function persistBuffer(bytes, destination) {
|
|
|
10048
10523
|
const temporary = `${destination}.${randomUUID5()}.tmp`;
|
|
10049
10524
|
try {
|
|
10050
10525
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
10051
|
-
await
|
|
10526
|
+
await rename2(temporary, destination);
|
|
10052
10527
|
return true;
|
|
10053
10528
|
} catch (error) {
|
|
10054
10529
|
if (error?.code === "EEXIST" && await destinationExists(destination)) return false;
|
|
@@ -10088,11 +10563,11 @@ async function importKnownMedia(input) {
|
|
|
10088
10563
|
async function importMediaFile(input) {
|
|
10089
10564
|
const maxBytes = input.maxBytes ?? DEFAULT_MAX_MEDIA_BYTES;
|
|
10090
10565
|
const source = path13.resolve(input.filePath);
|
|
10091
|
-
const
|
|
10092
|
-
if (
|
|
10093
|
-
if (!
|
|
10094
|
-
if (
|
|
10095
|
-
if (
|
|
10566
|
+
const stat5 = await lstat(source);
|
|
10567
|
+
if (stat5.isSymbolicLink()) throw new Error("Media import does not follow symbolic links");
|
|
10568
|
+
if (!stat5.isFile()) throw new Error("Media import accepts regular files only");
|
|
10569
|
+
if (stat5.size <= 0) throw new Error("Media import rejects empty files");
|
|
10570
|
+
if (stat5.size > maxBytes) throw new Error(`Media file is too large (${stat5.size} bytes; limit ${maxBytes})`);
|
|
10096
10571
|
const header = await readHeader(source);
|
|
10097
10572
|
const detected = detectMedia(header);
|
|
10098
10573
|
const sha256 = await sha256File(source);
|
|
@@ -10100,7 +10575,7 @@ async function importMediaFile(input) {
|
|
|
10100
10575
|
dataDir: input.dataDir,
|
|
10101
10576
|
projectId: input.projectId,
|
|
10102
10577
|
sha256,
|
|
10103
|
-
bytes:
|
|
10578
|
+
bytes: stat5.size,
|
|
10104
10579
|
detected,
|
|
10105
10580
|
persist: (destination) => persistFile(source, destination),
|
|
10106
10581
|
sourceKind: input.sourceKind ?? "import",
|
|
@@ -10147,13 +10622,13 @@ async function removeMediaAsset(input) {
|
|
|
10147
10622
|
const assetPath = getMediaAssetPath(input.dataDir, asset);
|
|
10148
10623
|
const stagedPath = deletionStagingPath(mediaRoot(input.dataDir), asset.id);
|
|
10149
10624
|
await mkdir3(path13.dirname(stagedPath), { recursive: true });
|
|
10150
|
-
await
|
|
10625
|
+
await rename2(assetPath, stagedPath);
|
|
10151
10626
|
let detachedLinks;
|
|
10152
10627
|
try {
|
|
10153
10628
|
({ detachedLinks } = store.removeAssetMetadata(input.projectId, asset.id, { force: input.force }));
|
|
10154
10629
|
} catch (error) {
|
|
10155
10630
|
try {
|
|
10156
|
-
await
|
|
10631
|
+
await rename2(stagedPath, assetPath);
|
|
10157
10632
|
} catch (restoreError) {
|
|
10158
10633
|
const original = error instanceof Error ? error.message : String(error);
|
|
10159
10634
|
const restore = restoreError instanceof Error ? restoreError.message : String(restoreError);
|
|
@@ -10189,7 +10664,7 @@ async function cleanupMediaTrash(dataDir) {
|
|
|
10189
10664
|
} catch (error) {
|
|
10190
10665
|
if (error?.code === "ENOENT") continue;
|
|
10191
10666
|
try {
|
|
10192
|
-
pendingBytes += (await
|
|
10667
|
+
pendingBytes += (await stat2(candidate)).size;
|
|
10193
10668
|
} catch {
|
|
10194
10669
|
}
|
|
10195
10670
|
pendingFiles += 1;
|
|
@@ -61271,9 +61746,9 @@ var require_node_domexception = __commonJS({
|
|
|
61271
61746
|
});
|
|
61272
61747
|
|
|
61273
61748
|
// node_modules/fetch-blob/from.js
|
|
61274
|
-
import { statSync as statSync2, createReadStream, promises as fs10 } from "fs";
|
|
61749
|
+
import { statSync as statSync2, createReadStream as createReadStream2, promises as fs10 } from "fs";
|
|
61275
61750
|
import { basename } from "path";
|
|
61276
|
-
var import_node_domexception,
|
|
61751
|
+
var import_node_domexception, stat3, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
|
|
61277
61752
|
var init_from = __esm({
|
|
61278
61753
|
"node_modules/fetch-blob/from.js"() {
|
|
61279
61754
|
"use strict";
|
|
@@ -61281,23 +61756,23 @@ var init_from = __esm({
|
|
|
61281
61756
|
import_node_domexception = __toESM(require_node_domexception(), 1);
|
|
61282
61757
|
init_file();
|
|
61283
61758
|
init_fetch_blob();
|
|
61284
|
-
({ stat:
|
|
61759
|
+
({ stat: stat3 } = fs10);
|
|
61285
61760
|
blobFromSync = (path34, type) => fromBlob(statSync2(path34), path34, type);
|
|
61286
|
-
blobFrom = (path34, type) =>
|
|
61287
|
-
fileFrom = (path34, type) =>
|
|
61761
|
+
blobFrom = (path34, type) => stat3(path34).then((stat5) => fromBlob(stat5, path34, type));
|
|
61762
|
+
fileFrom = (path34, type) => stat3(path34).then((stat5) => fromFile(stat5, path34, type));
|
|
61288
61763
|
fileFromSync = (path34, type) => fromFile(statSync2(path34), path34, type);
|
|
61289
|
-
fromBlob = (
|
|
61764
|
+
fromBlob = (stat5, path34, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
61290
61765
|
path: path34,
|
|
61291
|
-
size:
|
|
61292
|
-
lastModified:
|
|
61766
|
+
size: stat5.size,
|
|
61767
|
+
lastModified: stat5.mtimeMs,
|
|
61293
61768
|
start: 0
|
|
61294
61769
|
})], { type });
|
|
61295
|
-
fromFile = (
|
|
61770
|
+
fromFile = (stat5, path34, type = "") => new file_default([new BlobDataItem({
|
|
61296
61771
|
path: path34,
|
|
61297
|
-
size:
|
|
61298
|
-
lastModified:
|
|
61772
|
+
size: stat5.size,
|
|
61773
|
+
lastModified: stat5.mtimeMs,
|
|
61299
61774
|
start: 0
|
|
61300
|
-
})], basename(path34), { type, lastModified:
|
|
61775
|
+
})], basename(path34), { type, lastModified: stat5.mtimeMs });
|
|
61301
61776
|
BlobDataItem = class _BlobDataItem {
|
|
61302
61777
|
#path;
|
|
61303
61778
|
#start;
|
|
@@ -61320,11 +61795,11 @@ var init_from = __esm({
|
|
|
61320
61795
|
});
|
|
61321
61796
|
}
|
|
61322
61797
|
async *stream() {
|
|
61323
|
-
const { mtimeMs } = await
|
|
61798
|
+
const { mtimeMs } = await stat3(this.#path);
|
|
61324
61799
|
if (mtimeMs > this.lastModified) {
|
|
61325
61800
|
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");
|
|
61326
61801
|
}
|
|
61327
|
-
yield*
|
|
61802
|
+
yield* createReadStream2(this.#path, {
|
|
61328
61803
|
start: this.#start,
|
|
61329
61804
|
end: this.#start + this.size - 1
|
|
61330
61805
|
});
|
|
@@ -76954,7 +77429,7 @@ var init_wrapper = __esm({
|
|
|
76954
77429
|
});
|
|
76955
77430
|
|
|
76956
77431
|
// node_modules/@google/genai/dist/node/index.mjs
|
|
76957
|
-
import { createWriteStream } from "fs";
|
|
77432
|
+
import { createWriteStream as createWriteStream2 } from "fs";
|
|
76958
77433
|
import * as fs11 from "fs/promises";
|
|
76959
77434
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
76960
77435
|
import { Readable } from "stream";
|
|
@@ -94234,7 +94709,7 @@ ${underline}`);
|
|
|
94234
94709
|
if (params.downloadPath) {
|
|
94235
94710
|
const response = await downloadFile(params, apiClient);
|
|
94236
94711
|
if (response instanceof HttpResponse) {
|
|
94237
|
-
const writer =
|
|
94712
|
+
const writer = createWriteStream2(params.downloadPath);
|
|
94238
94713
|
const body = Readable.fromWeb(response.responseInternal.body);
|
|
94239
94714
|
body.pipe(writer);
|
|
94240
94715
|
await finished(writer);
|
|
@@ -144268,7 +144743,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
144268
144743
|
};
|
|
144269
144744
|
}
|
|
144270
144745
|
function toRetentionDocument(obs, accessMap) {
|
|
144271
|
-
const
|
|
144746
|
+
const access3 = accessMap?.get(obs.id);
|
|
144272
144747
|
return {
|
|
144273
144748
|
id: `obs-${obs.id}`,
|
|
144274
144749
|
observationId: obs.id,
|
|
@@ -144282,8 +144757,8 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
144282
144757
|
tokens: obs.tokens,
|
|
144283
144758
|
createdAt: obs.createdAt,
|
|
144284
144759
|
projectId: obs.projectId,
|
|
144285
|
-
accessCount:
|
|
144286
|
-
lastAccessedAt:
|
|
144760
|
+
accessCount: access3?.accessCount ?? 0,
|
|
144761
|
+
lastAccessedAt: access3?.lastAccessedAt ?? "",
|
|
144287
144762
|
status: obs.status ?? "active",
|
|
144288
144763
|
source: obs.source ?? "agent",
|
|
144289
144764
|
sourceDetail: obs.sourceDetail ?? "",
|
|
@@ -146397,7 +146872,7 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
146397
146872
|
const rel = normalizeCodePath(relative(projectRoot, abs));
|
|
146398
146873
|
try {
|
|
146399
146874
|
const text2 = readFileSync6(abs, "utf-8");
|
|
146400
|
-
const
|
|
146875
|
+
const stat5 = fileStat ?? statSync3(abs);
|
|
146401
146876
|
const file = {
|
|
146402
146877
|
id: makeCodeFileId(projectId, rel),
|
|
146403
146878
|
projectId,
|
|
@@ -146406,8 +146881,8 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
|
|
|
146406
146881
|
contentHash: hashText(text2),
|
|
146407
146882
|
// Preserve filesystem precision. Rounding here made same-size edits in
|
|
146408
146883
|
// a short Windows timestamp window indistinguishable to refresh.
|
|
146409
|
-
mtimeMs: Number(
|
|
146410
|
-
sizeBytes: Number(
|
|
146884
|
+
mtimeMs: Number(stat5.mtimeMs),
|
|
146885
|
+
sizeBytes: Number(stat5.size),
|
|
146411
146886
|
indexedAt
|
|
146412
146887
|
};
|
|
146413
146888
|
return {
|
|
@@ -146434,18 +146909,18 @@ async function indexProjectLite(options) {
|
|
|
146434
146909
|
let skippedOversizedFiles = 0;
|
|
146435
146910
|
let unreadableFiles = 0;
|
|
146436
146911
|
for (const abs of paths) {
|
|
146437
|
-
let
|
|
146912
|
+
let stat5;
|
|
146438
146913
|
try {
|
|
146439
|
-
|
|
146914
|
+
stat5 = statSync3(abs);
|
|
146440
146915
|
} catch {
|
|
146441
146916
|
unreadableFiles++;
|
|
146442
146917
|
continue;
|
|
146443
146918
|
}
|
|
146444
|
-
if (Number(
|
|
146919
|
+
if (Number(stat5.size) > maxFileBytes) {
|
|
146445
146920
|
skippedOversizedFiles++;
|
|
146446
146921
|
continue;
|
|
146447
146922
|
}
|
|
146448
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
146923
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
146449
146924
|
if (!attempt.delta) {
|
|
146450
146925
|
if (attempt.unreadable) unreadableFiles++;
|
|
146451
146926
|
continue;
|
|
@@ -146473,16 +146948,16 @@ async function refreshProjectLite(store, options) {
|
|
|
146473
146948
|
for (const abs of paths) {
|
|
146474
146949
|
const rel = normalizeCodePath(relative(options.projectRoot, abs));
|
|
146475
146950
|
seenPaths.add(rel);
|
|
146476
|
-
let
|
|
146951
|
+
let stat5;
|
|
146477
146952
|
try {
|
|
146478
|
-
|
|
146953
|
+
stat5 = statSync3(abs);
|
|
146479
146954
|
} catch {
|
|
146480
146955
|
unreadableFiles++;
|
|
146481
146956
|
continue;
|
|
146482
146957
|
}
|
|
146483
146958
|
const existing = existingByPath.get(rel);
|
|
146484
|
-
const mtimeMs = Number(
|
|
146485
|
-
const sizeBytes = Number(
|
|
146959
|
+
const mtimeMs = Number(stat5.mtimeMs);
|
|
146960
|
+
const sizeBytes = Number(stat5.size);
|
|
146486
146961
|
if (sizeBytes > maxFileBytes) {
|
|
146487
146962
|
skippedOversizedFiles++;
|
|
146488
146963
|
if (existing) oversizedExistingFileIds.add(existing.id);
|
|
@@ -146492,7 +146967,7 @@ async function refreshProjectLite(store, options) {
|
|
|
146492
146967
|
unchangedFiles++;
|
|
146493
146968
|
continue;
|
|
146494
146969
|
}
|
|
146495
|
-
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt,
|
|
146970
|
+
const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
|
|
146496
146971
|
if (!attempt.delta) {
|
|
146497
146972
|
if (attempt.unreadable) unreadableFiles++;
|
|
146498
146973
|
continue;
|
|
@@ -150240,12 +150715,25 @@ __export(observations_exports, {
|
|
|
150240
150715
|
prepareSearchIndex: () => prepareSearchIndex,
|
|
150241
150716
|
probeSearchIndex: () => probeSearchIndex,
|
|
150242
150717
|
reindexObservations: () => reindexObservations,
|
|
150718
|
+
resetObservationRuntime: () => resetObservationRuntime,
|
|
150243
150719
|
resolveObservations: () => resolveObservations,
|
|
150244
150720
|
storeObservation: () => storeObservation,
|
|
150245
150721
|
suggestTopicKey: () => suggestTopicKey,
|
|
150246
150722
|
updateObservationAdmission: () => updateObservationAdmission,
|
|
150247
150723
|
withFreshObservations: () => withFreshObservations
|
|
150248
150724
|
});
|
|
150725
|
+
function resetObservationRuntime() {
|
|
150726
|
+
observations = [];
|
|
150727
|
+
nextId = 1;
|
|
150728
|
+
projectDir = null;
|
|
150729
|
+
searchIndexPrepared = false;
|
|
150730
|
+
corpusLoaded = false;
|
|
150731
|
+
loadedObservationStore = null;
|
|
150732
|
+
embeddingWriteMode = "background";
|
|
150733
|
+
embeddingWorkerProjectRoot = void 0;
|
|
150734
|
+
vectorMissingIds.clear();
|
|
150735
|
+
vectorSchemaUpgradePromise = null;
|
|
150736
|
+
}
|
|
150249
150737
|
function logEmbeddingFailureOnce(key, message) {
|
|
150250
150738
|
const now3 = Date.now();
|
|
150251
150739
|
const last = embeddingFailureLogTimestamps.get(key) ?? 0;
|
|
@@ -150354,23 +150842,33 @@ async function upgradeVectorSchemaAfterFirstEmbedding(embedding) {
|
|
|
150354
150842
|
async function initObservations(dir, options = {}) {
|
|
150355
150843
|
embeddingWriteMode = options.embeddingWriteMode ?? "background";
|
|
150356
150844
|
embeddingWorkerProjectRoot = options.projectRoot;
|
|
150357
|
-
if (projectDir === dir) return;
|
|
150358
150845
|
await initObservationStore(dir);
|
|
150359
150846
|
const store = getObservationStore();
|
|
150360
|
-
|
|
150847
|
+
if (projectDir === dir && loadedObservationStore === store) {
|
|
150848
|
+
if (options.skipCorpusLoad || corpusLoaded) return;
|
|
150849
|
+
}
|
|
150361
150850
|
nextId = await store.loadIdCounter();
|
|
150362
150851
|
projectDir = dir;
|
|
150363
150852
|
searchIndexPrepared = false;
|
|
150364
150853
|
vectorSchemaUpgradePromise = null;
|
|
150854
|
+
if (options.skipCorpusLoad) {
|
|
150855
|
+
observations = [];
|
|
150856
|
+
corpusLoaded = false;
|
|
150857
|
+
loadedObservationStore = store;
|
|
150858
|
+
return;
|
|
150859
|
+
}
|
|
150860
|
+
observations = await store.loadAll();
|
|
150861
|
+
corpusLoaded = true;
|
|
150862
|
+
loadedObservationStore = store;
|
|
150365
150863
|
}
|
|
150366
150864
|
function scheduleObservationEmbedding(input) {
|
|
150367
150865
|
const { observationId: observationId2, projectId, searchableText, doc } = input;
|
|
150368
150866
|
vectorMissingIds.add(observationId2);
|
|
150867
|
+
if (isEmbeddingExplicitlyDisabled()) {
|
|
150868
|
+
vectorMissingIds.delete(observationId2);
|
|
150869
|
+
return;
|
|
150870
|
+
}
|
|
150369
150871
|
if (embeddingWriteMode === "deferred") {
|
|
150370
|
-
if (isEmbeddingExplicitlyDisabled()) {
|
|
150371
|
-
vectorMissingIds.delete(observationId2);
|
|
150372
|
-
return;
|
|
150373
|
-
}
|
|
150374
150872
|
queueVectorBackfill(projectId, {
|
|
150375
150873
|
detachedWorker: true,
|
|
150376
150874
|
projectRoot: embeddingWorkerProjectRoot
|
|
@@ -150417,7 +150915,7 @@ function scheduleObservationEmbedding(input) {
|
|
|
150417
150915
|
});
|
|
150418
150916
|
}
|
|
150419
150917
|
async function ensureFreshObservations() {
|
|
150420
|
-
if (!projectDir) return false;
|
|
150918
|
+
if (!projectDir || !corpusLoaded) return false;
|
|
150421
150919
|
try {
|
|
150422
150920
|
const store = getObservationStore();
|
|
150423
150921
|
const wasStale = await store.ensureFresh();
|
|
@@ -150458,7 +150956,7 @@ async function storeObservation(input) {
|
|
|
150458
150956
|
});
|
|
150459
150957
|
if (safeAttachments) input = { ...input, attachments: safeAttachments };
|
|
150460
150958
|
await ensureFreshObservations();
|
|
150461
|
-
if (input.topicKey) {
|
|
150959
|
+
if (input.topicKey && corpusLoaded) {
|
|
150462
150960
|
const existing = observations.find(
|
|
150463
150961
|
(o) => o.topicKey === input.topicKey && o.projectId === input.projectId
|
|
150464
150962
|
);
|
|
@@ -150555,13 +151053,17 @@ async function storeObservation(input) {
|
|
|
150555
151053
|
});
|
|
150556
151054
|
observation.writeGeneration = store.getGeneration();
|
|
150557
151055
|
if (upsertedInsideLock || reloadCacheAfterCommit) {
|
|
150558
|
-
|
|
150559
|
-
|
|
150560
|
-
|
|
150561
|
-
|
|
151056
|
+
if (corpusLoaded) {
|
|
151057
|
+
observations = await store.loadAll();
|
|
151058
|
+
nextId = await store.loadIdCounter();
|
|
151059
|
+
if (upsertedInsideLock) {
|
|
151060
|
+
observation = observations.find((candidate) => candidate.id === observation.id) ?? observation;
|
|
151061
|
+
}
|
|
151062
|
+
} else {
|
|
151063
|
+
nextId = await store.loadIdCounter();
|
|
150562
151064
|
}
|
|
150563
151065
|
} else {
|
|
150564
|
-
observations.push(observation);
|
|
151066
|
+
if (corpusLoaded) observations.push(observation);
|
|
150565
151067
|
nextId = observation.id + 1;
|
|
150566
151068
|
}
|
|
150567
151069
|
if (upsertedInsideLock) return;
|
|
@@ -150629,7 +151131,9 @@ async function storeObservation(input) {
|
|
|
150629
151131
|
createdByAgentId: input.createdByAgentId ?? "",
|
|
150630
151132
|
sharedWithAgentIds: JSON.stringify(input.sharedWithAgentIds ?? [])
|
|
150631
151133
|
};
|
|
150632
|
-
|
|
151134
|
+
if (corpusLoaded) {
|
|
151135
|
+
await insertObservation(doc);
|
|
151136
|
+
}
|
|
150633
151137
|
};
|
|
150634
151138
|
await assignAndPersist();
|
|
150635
151139
|
if (upsertedInsideLock) {
|
|
@@ -150991,9 +151495,11 @@ async function reindexObservations() {
|
|
|
150991
151495
|
searchIndexPrepared = true;
|
|
150992
151496
|
return count2;
|
|
150993
151497
|
}
|
|
150994
|
-
async function prepareSearchIndex() {
|
|
151498
|
+
async function prepareSearchIndex(options = {}) {
|
|
150995
151499
|
if (searchIndexPrepared) return 0;
|
|
150996
|
-
const count2 = await hydrateIndexForStartup(observations
|
|
151500
|
+
const count2 = await hydrateIndexForStartup(observations, {
|
|
151501
|
+
skipCachedVectors: options.skipCachedVectors
|
|
151502
|
+
});
|
|
150997
151503
|
if (count2 === 0) {
|
|
150998
151504
|
searchIndexPrepared = true;
|
|
150999
151505
|
return 0;
|
|
@@ -151185,7 +151691,7 @@ async function backfillVectorEmbeddings(options = {}) {
|
|
|
151185
151691
|
...lastFailure ? { lastError: lastFailure } : {}
|
|
151186
151692
|
};
|
|
151187
151693
|
}
|
|
151188
|
-
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
151694
|
+
var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, corpusLoaded, loadedObservationStore, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
|
|
151189
151695
|
var init_observations = __esm({
|
|
151190
151696
|
"src/memory/observations.ts"() {
|
|
151191
151697
|
"use strict";
|
|
@@ -151204,6 +151710,8 @@ var init_observations = __esm({
|
|
|
151204
151710
|
projectDir = null;
|
|
151205
151711
|
searchIndexPrepared = false;
|
|
151206
151712
|
embeddingWriteMode = "background";
|
|
151713
|
+
corpusLoaded = false;
|
|
151714
|
+
loadedObservationStore = null;
|
|
151207
151715
|
vectorMissingIds = /* @__PURE__ */ new Set();
|
|
151208
151716
|
vectorBackfillRunning = false;
|
|
151209
151717
|
vectorSchemaUpgradePromise = null;
|
|
@@ -155399,9 +155907,9 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
155399
155907
|
const absolute = path28.join(rootPath, candidate);
|
|
155400
155908
|
try {
|
|
155401
155909
|
if (!existsSync16(absolute)) continue;
|
|
155402
|
-
const
|
|
155403
|
-
if (
|
|
155404
|
-
if (
|
|
155910
|
+
const stat5 = statSync4(absolute);
|
|
155911
|
+
if (stat5.isFile()) out.push(candidate);
|
|
155912
|
+
if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
|
|
155405
155913
|
} catch {
|
|
155406
155914
|
}
|
|
155407
155915
|
}
|
|
@@ -161221,13 +161729,13 @@ async function installHooks(agent, projectRoot, global2 = false) {
|
|
|
161221
161729
|
const agentPrev = prevFiles.filter((e2) => e2.agent === agent);
|
|
161222
161730
|
for (const entry of agentPrev) {
|
|
161223
161731
|
try {
|
|
161224
|
-
const { access:
|
|
161225
|
-
await
|
|
161732
|
+
const { access: access3, unlink: unlink3 } = await import("fs/promises");
|
|
161733
|
+
await access3(entry.path);
|
|
161226
161734
|
const basename5 = path32.basename(entry.path);
|
|
161227
161735
|
if (basename5 === "AGENTS.md" || basename5 === "GEMINI.md" || basename5 === "CONTEXT.md") {
|
|
161228
161736
|
continue;
|
|
161229
161737
|
}
|
|
161230
|
-
await
|
|
161738
|
+
await unlink3(entry.path);
|
|
161231
161739
|
await removeFile2(projectRoot, entry.path);
|
|
161232
161740
|
} catch {
|
|
161233
161741
|
}
|
|
@@ -161747,11 +162255,11 @@ import path33 from "path";
|
|
|
161747
162255
|
function resolveGitDir(projectRoot) {
|
|
161748
162256
|
const dotGit = path33.join(projectRoot, ".git");
|
|
161749
162257
|
if (!existsSync19(dotGit)) return null;
|
|
161750
|
-
const
|
|
161751
|
-
if (
|
|
162258
|
+
const stat5 = statSync5(dotGit);
|
|
162259
|
+
if (stat5.isDirectory()) {
|
|
161752
162260
|
return dotGit;
|
|
161753
162261
|
}
|
|
161754
|
-
if (
|
|
162262
|
+
if (stat5.isFile()) {
|
|
161755
162263
|
try {
|
|
161756
162264
|
const content = readFileSync13(dotGit, "utf-8").trim();
|
|
161757
162265
|
const match2 = content.match(/^gitdir:\s*(.+)$/);
|
|
@@ -163895,8 +164403,8 @@ var RulesSyncer = class {
|
|
|
163895
164403
|
const dir = path25.dirname(pattern);
|
|
163896
164404
|
const fileGlob = path25.basename(pattern);
|
|
163897
164405
|
try {
|
|
163898
|
-
const
|
|
163899
|
-
if (!
|
|
164406
|
+
const stat5 = await fs17.stat(dir);
|
|
164407
|
+
if (!stat5.isDirectory()) {
|
|
163900
164408
|
try {
|
|
163901
164409
|
await fs17.access(pattern);
|
|
163902
164410
|
return [pattern];
|
|
@@ -165951,7 +166459,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
165951
166459
|
};
|
|
165952
166460
|
const server = existingServer ?? new McpServer({
|
|
165953
166461
|
name: "memorix",
|
|
165954
|
-
version: true ? "1.6.
|
|
166462
|
+
version: true ? "1.6.2" : "1.0.1"
|
|
165955
166463
|
});
|
|
165956
166464
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
165957
166465
|
server.registerTool = ((name, ...args) => {
|
|
@@ -170379,6 +170887,11 @@ var MemoryClient = class {
|
|
|
170379
170887
|
await this._oramaStore.resetDb();
|
|
170380
170888
|
} catch {
|
|
170381
170889
|
}
|
|
170890
|
+
try {
|
|
170891
|
+
const { closeDatabase: closeDatabase3 } = await Promise.resolve().then(() => (init_sqlite_db(), sqlite_db_exports));
|
|
170892
|
+
closeDatabase3(this._dataDir);
|
|
170893
|
+
} catch {
|
|
170894
|
+
}
|
|
170382
170895
|
}
|
|
170383
170896
|
};
|
|
170384
170897
|
async function createMemoryClient(options) {
|
|
@@ -170390,11 +170903,8 @@ async function createMemoryClient(options) {
|
|
|
170390
170903
|
`[memorix-sdk] No Git repository found at "${projectRoot}". Memorix requires a Git-tracked project for identity resolution.`
|
|
170391
170904
|
);
|
|
170392
170905
|
}
|
|
170393
|
-
const
|
|
170394
|
-
const
|
|
170395
|
-
const dataDir = path34.join(os4.homedir(), ".memorix", "data", project.id.replace(/\//g, path34.sep));
|
|
170396
|
-
const fs22 = await import("fs");
|
|
170397
|
-
fs22.mkdirSync(dataDir, { recursive: true });
|
|
170906
|
+
const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
170907
|
+
const dataDir = await getProjectDataDir2(project.id);
|
|
170398
170908
|
const client = new MemoryClient(project.id, projectRoot, dataDir);
|
|
170399
170909
|
await client._init(silent);
|
|
170400
170910
|
return client;
|