memorix 1.5.0 → 1.5.1
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 +14 -0
- package/TEAM.md +86 -86
- package/dist/cli/index.js +211 -69
- package/dist/cli/memcode.js +0 -0
- package/dist/index.js +211 -69
- package/dist/maintenance-runner.js +169 -37
- package/dist/media-audio-runner.js +169 -37
- package/dist/media-video-runner.js +169 -37
- package/dist/memcode-runtime/CHANGELOG.md +14 -0
- package/dist/sdk.js +210 -68
- package/dist/types.d.ts +2 -0
- package/dist/vector-backfill-runner.js +169 -37
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/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/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/poll.ts +58 -58
- package/src/cli/commands/reasoning.ts +118 -118
- 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 +105 -22
- package/src/embedding/provider.ts +2 -0
- package/src/git/hooks-path.ts +85 -85
- 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/provider.ts +17 -8
- 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/formation/extract.ts +6 -3
- package/src/memory/formation/index.ts +2 -1
- package/src/memory/formation/resolve.ts +10 -6
- package/src/memory/formation/types.ts +3 -1
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph.ts +197 -197
- package/src/memory/long-term.ts +7 -1
- 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/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +14 -10
- 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 +6 -4
- 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/timeout.ts +67 -0
- package/src/types.ts +2 -0
- 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/cli/index.js
CHANGED
|
@@ -3221,7 +3221,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3221
3221
|
|
|
3222
3222
|
// src/cli/version.ts
|
|
3223
3223
|
function getCliVersion() {
|
|
3224
|
-
return true ? "1.5.
|
|
3224
|
+
return true ? "1.5.1" : pkg.version;
|
|
3225
3225
|
}
|
|
3226
3226
|
var init_version = __esm({
|
|
3227
3227
|
"src/cli/version.ts"() {
|
|
@@ -22327,6 +22327,8 @@ function getPreferredBatchSize(config2) {
|
|
|
22327
22327
|
}
|
|
22328
22328
|
function parseBatchLimit(error40) {
|
|
22329
22329
|
if (!(error40 instanceof Error)) return null;
|
|
22330
|
+
const status = error40 instanceof EmbeddingAPIError ? error40.status : Number(error40.message.match(/Embedding API error \((\d{3})\)/i)?.[1] ?? 0);
|
|
22331
|
+
if (status > 0 && status !== 400) return null;
|
|
22330
22332
|
const explicit = error40.message.match(/should not be larger than\s+(\d+)/i);
|
|
22331
22333
|
if (explicit) return parseInt(explicit[1], 10);
|
|
22332
22334
|
if (/batch size/i.test(error40.message)) {
|
|
@@ -22339,37 +22341,99 @@ async function fetchWithRetry(url2, apiKey, body, options = {}, attempt = 0, nat
|
|
|
22339
22341
|
const controller = new AbortController();
|
|
22340
22342
|
const timeoutMs = typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs) ? Math.max(100, Math.min(Math.floor(options.timeoutMs), 6e4)) : 1e4;
|
|
22341
22343
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
22344
|
+
const signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal;
|
|
22342
22345
|
let response;
|
|
22343
22346
|
try {
|
|
22344
22347
|
response = await fetch(url2, {
|
|
22345
22348
|
method: "POST",
|
|
22346
22349
|
headers: nativeGemini ? { "Content-Type": "application/json", "x-goog-api-key": apiKey } : { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}` },
|
|
22347
22350
|
body: JSON.stringify(body),
|
|
22348
|
-
signal
|
|
22351
|
+
signal
|
|
22349
22352
|
});
|
|
22350
22353
|
} catch (err) {
|
|
22351
22354
|
clearTimeout(timeout);
|
|
22352
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
22355
|
+
if (err instanceof Error && (err.name === "AbortError" || controller.signal.aborted || options.signal?.aborted)) {
|
|
22353
22356
|
throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url2}`);
|
|
22354
22357
|
}
|
|
22355
22358
|
throw err;
|
|
22356
22359
|
}
|
|
22357
|
-
|
|
22358
|
-
|
|
22359
|
-
|
|
22360
|
+
try {
|
|
22361
|
+
if (response.ok) {
|
|
22362
|
+
return await raceWithAbort(
|
|
22363
|
+
response.json(),
|
|
22364
|
+
signal
|
|
22365
|
+
);
|
|
22366
|
+
}
|
|
22367
|
+
if (options.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
|
|
22368
|
+
const delay2 = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
22369
|
+
const retryAfter = response.headers.get("retry-after");
|
|
22370
|
+
const parsedRetryAfter = retryAfter ? parseInt(retryAfter, 10) * 1e3 : NaN;
|
|
22371
|
+
const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter : delay2;
|
|
22372
|
+
console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
|
|
22373
|
+
await waitForRetry(waitMs, options.signal);
|
|
22374
|
+
return fetchWithRetry(url2, apiKey, body, options, attempt + 1, nativeGemini);
|
|
22375
|
+
}
|
|
22376
|
+
const errorText2 = await raceWithAbort(
|
|
22377
|
+
response.text().catch(() => "unknown error"),
|
|
22378
|
+
signal
|
|
22379
|
+
);
|
|
22380
|
+
throw new EmbeddingAPIError(response.status, errorText2);
|
|
22381
|
+
} catch (err) {
|
|
22382
|
+
if (err instanceof Error && (err.name === "AbortError" || controller.signal.aborted || options.signal?.aborted)) {
|
|
22383
|
+
throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url2}`);
|
|
22384
|
+
}
|
|
22385
|
+
throw err;
|
|
22386
|
+
} finally {
|
|
22387
|
+
clearTimeout(timeout);
|
|
22360
22388
|
}
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
22389
|
+
}
|
|
22390
|
+
function abortError() {
|
|
22391
|
+
const error40 = new Error("Embedding API request aborted");
|
|
22392
|
+
error40.name = "AbortError";
|
|
22393
|
+
return error40;
|
|
22394
|
+
}
|
|
22395
|
+
function raceWithAbort(promise2, signal) {
|
|
22396
|
+
if (signal.aborted) return Promise.reject(abortError());
|
|
22397
|
+
return new Promise((resolve6, reject) => {
|
|
22398
|
+
const onAbort = () => {
|
|
22399
|
+
signal.removeEventListener("abort", onAbort);
|
|
22400
|
+
reject(abortError());
|
|
22401
|
+
};
|
|
22402
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
22403
|
+
promise2.then(
|
|
22404
|
+
(value) => {
|
|
22405
|
+
signal.removeEventListener("abort", onAbort);
|
|
22406
|
+
resolve6(value);
|
|
22407
|
+
},
|
|
22408
|
+
(error40) => {
|
|
22409
|
+
signal.removeEventListener("abort", onAbort);
|
|
22410
|
+
reject(error40);
|
|
22411
|
+
}
|
|
22412
|
+
);
|
|
22413
|
+
});
|
|
22414
|
+
}
|
|
22415
|
+
async function waitForRetry(waitMs, signal) {
|
|
22416
|
+
if (!signal) {
|
|
22366
22417
|
await new Promise((resolve6) => setTimeout(resolve6, waitMs));
|
|
22367
|
-
return
|
|
22418
|
+
return;
|
|
22368
22419
|
}
|
|
22369
|
-
const
|
|
22370
|
-
throw new Error(
|
|
22420
|
+
const abortSignal = signal;
|
|
22421
|
+
if (abortSignal.aborted) throw new Error("Embedding API retry aborted");
|
|
22422
|
+
await new Promise((resolve6, reject) => {
|
|
22423
|
+
const timer = setTimeout(done, waitMs);
|
|
22424
|
+
const onAbort = () => {
|
|
22425
|
+
clearTimeout(timer);
|
|
22426
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
22427
|
+
reject(new Error("Embedding API retry aborted"));
|
|
22428
|
+
};
|
|
22429
|
+
function done() {
|
|
22430
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
22431
|
+
resolve6();
|
|
22432
|
+
}
|
|
22433
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
22434
|
+
});
|
|
22371
22435
|
}
|
|
22372
|
-
var cache3, MAX_CACHE_SIZE3, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, APIEmbeddingProvider;
|
|
22436
|
+
var cache3, MAX_CACHE_SIZE3, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
|
|
22373
22437
|
var init_api_provider = __esm({
|
|
22374
22438
|
"src/embedding/api-provider.ts"() {
|
|
22375
22439
|
"use strict";
|
|
@@ -22388,6 +22452,14 @@ var init_api_provider = __esm({
|
|
|
22388
22452
|
DASHSCOPE_MAX_BATCH_SIZE = 10;
|
|
22389
22453
|
MAX_RETRIES2 = 3;
|
|
22390
22454
|
BASE_DELAY_MS = 500;
|
|
22455
|
+
EmbeddingAPIError = class extends Error {
|
|
22456
|
+
status;
|
|
22457
|
+
constructor(status, detail) {
|
|
22458
|
+
super(`Embedding API error (${status}): ${detail}`);
|
|
22459
|
+
this.name = "EmbeddingAPIError";
|
|
22460
|
+
this.status = status;
|
|
22461
|
+
}
|
|
22462
|
+
};
|
|
22391
22463
|
APIEmbeddingProvider = class _APIEmbeddingProvider {
|
|
22392
22464
|
name;
|
|
22393
22465
|
dimensions;
|
|
@@ -22599,15 +22671,14 @@ var init_api_provider = __esm({
|
|
|
22599
22671
|
}
|
|
22600
22672
|
} catch (error40) {
|
|
22601
22673
|
const providerLimit = parseBatchLimit(error40);
|
|
22602
|
-
|
|
22603
|
-
if (chunkTexts.length > 1 && fallbackSize < chunkTexts.length) {
|
|
22674
|
+
if (providerLimit !== null && chunkTexts.length > 1 && providerLimit < chunkTexts.length) {
|
|
22604
22675
|
console.error(
|
|
22605
|
-
`[memorix] Embedding batch too large for provider, retrying in chunks of ${
|
|
22676
|
+
`[memorix] Embedding batch too large for provider, retrying in chunks of ${providerLimit}`
|
|
22606
22677
|
);
|
|
22607
|
-
for (let start = 0; start < chunkTexts.length; start +=
|
|
22678
|
+
for (let start = 0; start < chunkTexts.length; start += providerLimit) {
|
|
22608
22679
|
await processChunk(
|
|
22609
|
-
chunkTexts.slice(start, start +
|
|
22610
|
-
chunkIndices.slice(start, start +
|
|
22680
|
+
chunkTexts.slice(start, start + providerLimit),
|
|
22681
|
+
chunkIndices.slice(start, start + providerLimit)
|
|
22611
22682
|
);
|
|
22612
22683
|
}
|
|
22613
22684
|
return;
|
|
@@ -23471,22 +23542,23 @@ function getLLMConfig() {
|
|
|
23471
23542
|
function setLLMConfig(config2) {
|
|
23472
23543
|
currentConfig = config2;
|
|
23473
23544
|
}
|
|
23474
|
-
async function callLLM(systemPrompt, userMessage) {
|
|
23545
|
+
async function callLLM(systemPrompt, userMessage, signal) {
|
|
23475
23546
|
if (!currentConfig) {
|
|
23476
23547
|
throw new Error("LLM not configured. Set MEMORIX_LLM_API_KEY or OPENAI_API_KEY.");
|
|
23477
23548
|
}
|
|
23478
23549
|
if (currentConfig.provider === "anthropic") {
|
|
23479
|
-
return callAnthropic(systemPrompt, userMessage);
|
|
23550
|
+
return callAnthropic(systemPrompt, userMessage, signal);
|
|
23480
23551
|
}
|
|
23481
|
-
return callOpenAICompatible(systemPrompt, userMessage);
|
|
23552
|
+
return callOpenAICompatible(systemPrompt, userMessage, signal);
|
|
23482
23553
|
}
|
|
23483
|
-
async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
23554
|
+
async function callOpenAICompatible(systemPrompt, userMessage, signal) {
|
|
23484
23555
|
const config2 = currentConfig;
|
|
23485
23556
|
let base = config2.baseUrl.replace(/\/+$/, "");
|
|
23486
23557
|
if (!base.endsWith("/v1")) base += "/v1";
|
|
23487
23558
|
const url2 = `${base}/chat/completions`;
|
|
23559
|
+
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
23488
23560
|
const response = await fetch(url2, {
|
|
23489
|
-
signal:
|
|
23561
|
+
signal: fetchSignal,
|
|
23490
23562
|
method: "POST",
|
|
23491
23563
|
headers: {
|
|
23492
23564
|
"Content-Type": "application/json",
|
|
@@ -23503,10 +23575,10 @@ async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
|
23503
23575
|
})
|
|
23504
23576
|
});
|
|
23505
23577
|
if (!response.ok) {
|
|
23506
|
-
const error40 = await readResponseText(response,
|
|
23578
|
+
const error40 = await readResponseText(response, signal, 64 * 1024).catch(() => "unknown error");
|
|
23507
23579
|
throw new Error(`LLM API error (${response.status}): ${error40}`);
|
|
23508
23580
|
}
|
|
23509
|
-
const data = await readResponseJson(response);
|
|
23581
|
+
const data = await readResponseJson(response, signal);
|
|
23510
23582
|
return {
|
|
23511
23583
|
content: data.choices[0]?.message?.content ?? "",
|
|
23512
23584
|
usage: data.usage ? {
|
|
@@ -23515,11 +23587,12 @@ async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
|
23515
23587
|
} : void 0
|
|
23516
23588
|
};
|
|
23517
23589
|
}
|
|
23518
|
-
async function callAnthropic(systemPrompt, userMessage) {
|
|
23590
|
+
async function callAnthropic(systemPrompt, userMessage, signal) {
|
|
23519
23591
|
const config2 = currentConfig;
|
|
23520
23592
|
const url2 = `${config2.baseUrl}/messages`;
|
|
23593
|
+
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
23521
23594
|
const response = await fetch(url2, {
|
|
23522
|
-
signal:
|
|
23595
|
+
signal: fetchSignal,
|
|
23523
23596
|
method: "POST",
|
|
23524
23597
|
headers: {
|
|
23525
23598
|
"Content-Type": "application/json",
|
|
@@ -23537,10 +23610,10 @@ async function callAnthropic(systemPrompt, userMessage) {
|
|
|
23537
23610
|
})
|
|
23538
23611
|
});
|
|
23539
23612
|
if (!response.ok) {
|
|
23540
|
-
const error40 = await readResponseText(response,
|
|
23613
|
+
const error40 = await readResponseText(response, signal, 64 * 1024).catch(() => "unknown error");
|
|
23541
23614
|
throw new Error(`Anthropic API error (${response.status}): ${error40}`);
|
|
23542
23615
|
}
|
|
23543
|
-
const data = await readResponseJson(response);
|
|
23616
|
+
const data = await readResponseJson(response, signal);
|
|
23544
23617
|
return {
|
|
23545
23618
|
content: data.content[0]?.text ?? "",
|
|
23546
23619
|
usage: data.usage ? {
|
|
@@ -24045,6 +24118,57 @@ function withTimeout(promise2, ms2, label) {
|
|
|
24045
24118
|
);
|
|
24046
24119
|
});
|
|
24047
24120
|
}
|
|
24121
|
+
function withTimeoutSignal(operation, ms2, label, parentSignal) {
|
|
24122
|
+
const controller = new AbortController();
|
|
24123
|
+
const signal = parentSignal ? AbortSignal.any([parentSignal, controller.signal]) : controller.signal;
|
|
24124
|
+
return new Promise((resolve6, reject) => {
|
|
24125
|
+
let settled = false;
|
|
24126
|
+
let timedOut = false;
|
|
24127
|
+
let timer;
|
|
24128
|
+
const cleanup = () => {
|
|
24129
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
24130
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
24131
|
+
};
|
|
24132
|
+
const onParentAbort = () => {
|
|
24133
|
+
if (settled || timedOut) return;
|
|
24134
|
+
settled = true;
|
|
24135
|
+
cleanup();
|
|
24136
|
+
reject(parentSignal?.reason ?? new Error(`${label} aborted`));
|
|
24137
|
+
};
|
|
24138
|
+
parentSignal?.addEventListener("abort", onParentAbort, { once: true });
|
|
24139
|
+
timer = setTimeout(() => {
|
|
24140
|
+
if (settled) return;
|
|
24141
|
+
timedOut = true;
|
|
24142
|
+
controller.abort(new Error(`${label} timed out after ${ms2}ms`));
|
|
24143
|
+
settled = true;
|
|
24144
|
+
cleanup();
|
|
24145
|
+
reject(new Error(`${label} timed out after ${ms2}ms`));
|
|
24146
|
+
}, ms2);
|
|
24147
|
+
let pending;
|
|
24148
|
+
try {
|
|
24149
|
+
pending = operation(signal);
|
|
24150
|
+
} catch (error40) {
|
|
24151
|
+
settled = true;
|
|
24152
|
+
cleanup();
|
|
24153
|
+
reject(error40);
|
|
24154
|
+
return;
|
|
24155
|
+
}
|
|
24156
|
+
pending.then(
|
|
24157
|
+
(value) => {
|
|
24158
|
+
if (settled) return;
|
|
24159
|
+
settled = true;
|
|
24160
|
+
cleanup();
|
|
24161
|
+
resolve6(value);
|
|
24162
|
+
},
|
|
24163
|
+
(error40) => {
|
|
24164
|
+
if (settled) return;
|
|
24165
|
+
settled = true;
|
|
24166
|
+
cleanup();
|
|
24167
|
+
reject(timedOut ? new Error(`${label} timed out after ${ms2}ms`) : error40);
|
|
24168
|
+
}
|
|
24169
|
+
);
|
|
24170
|
+
});
|
|
24171
|
+
}
|
|
24048
24172
|
var init_timeout = __esm({
|
|
24049
24173
|
"src/timeout.ts"() {
|
|
24050
24174
|
"use strict";
|
|
@@ -178220,7 +178344,13 @@ async function maintainLongTermMemories(input) {
|
|
|
178220
178344
|
}
|
|
178221
178345
|
for (const group of groups.values()) {
|
|
178222
178346
|
if (group.length < 2) continue;
|
|
178223
|
-
group.sort((a4, b4) =>
|
|
178347
|
+
group.sort((a4, b4) => {
|
|
178348
|
+
const byCreatedAt = Date.parse(b4.createdAt) - Date.parse(a4.createdAt);
|
|
178349
|
+
if (byCreatedAt !== 0) return byCreatedAt;
|
|
178350
|
+
const byUpdatedAt = Date.parse(b4.updatedAt) - Date.parse(a4.updatedAt);
|
|
178351
|
+
if (byUpdatedAt !== 0) return byUpdatedAt;
|
|
178352
|
+
return b4.id.localeCompare(a4.id);
|
|
178353
|
+
});
|
|
178224
178354
|
const newest = group[0];
|
|
178225
178355
|
for (const older of group.slice(1)) {
|
|
178226
178356
|
try {
|
|
@@ -184736,16 +184866,18 @@ async function searchObservations(options) {
|
|
|
184736
184866
|
);
|
|
184737
184867
|
} else {
|
|
184738
184868
|
const EMBEDDING_TIMEOUT_MS = 15e3;
|
|
184739
|
-
queryVector = await
|
|
184740
|
-
provider2.embedInput ? provider2.embedInput(
|
|
184869
|
+
queryVector = await withTimeoutSignal(
|
|
184870
|
+
(signal) => provider2.embedInput ? provider2.embedInput(
|
|
184741
184871
|
{ modality: "text", text: expandedEmbeddingQuery },
|
|
184742
|
-
{ intent: "query", timeoutMs: EMBEDDING_TIMEOUT_MS, retry: false }
|
|
184872
|
+
{ intent: "query", timeoutMs: EMBEDDING_TIMEOUT_MS, retry: false, signal }
|
|
184743
184873
|
) : provider2.embed(expandedEmbeddingQuery, {
|
|
184744
184874
|
timeoutMs: EMBEDDING_TIMEOUT_MS,
|
|
184745
|
-
retry: false
|
|
184875
|
+
retry: false,
|
|
184876
|
+
signal
|
|
184746
184877
|
}),
|
|
184747
184878
|
EMBEDDING_TIMEOUT_MS,
|
|
184748
|
-
"Embedding"
|
|
184879
|
+
"Embedding",
|
|
184880
|
+
options.signal
|
|
184749
184881
|
);
|
|
184750
184882
|
mark("embedding");
|
|
184751
184883
|
const cjkRatio = (originalQuery.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length / originalQuery.length;
|
|
@@ -199205,13 +199337,13 @@ function verifyType(declaredType, narrative, title) {
|
|
|
199205
199337
|
}
|
|
199206
199338
|
return { type: declaredType, corrected: false };
|
|
199207
199339
|
}
|
|
199208
|
-
async function extractFactsWithLLM(narrative, title, existingFacts) {
|
|
199340
|
+
async function extractFactsWithLLM(narrative, title, existingFacts, signal) {
|
|
199209
199341
|
try {
|
|
199210
199342
|
const { callLLM: callLLM2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
|
|
199211
199343
|
const input = `Title: ${title}
|
|
199212
199344
|
Content: ${narrative}${existingFacts.length > 0 ? `
|
|
199213
199345
|
Already known facts (don't repeat): ${existingFacts.join("; ")}` : ""}`;
|
|
199214
|
-
const response = await callLLM2(LLM_EXTRACT_PROMPT, input);
|
|
199346
|
+
const response = await callLLM2(LLM_EXTRACT_PROMPT, input, signal);
|
|
199215
199347
|
const text2 = response.content.trim();
|
|
199216
199348
|
const jsonMatch = text2.match(/\{[\s\S]*\}/);
|
|
199217
199349
|
if (!jsonMatch) return [];
|
|
@@ -199220,15 +199352,16 @@ Already known facts (don't repeat): ${existingFacts.join("; ")}` : ""}`;
|
|
|
199220
199352
|
if (!Array.isArray(facts)) return [];
|
|
199221
199353
|
const existingLower = new Set(existingFacts.map((f7) => f7.toLowerCase().trim()));
|
|
199222
199354
|
return facts.filter((f7) => typeof f7 === "string" && f7.length >= 5).filter((f7) => !existingLower.has(f7.toLowerCase().trim())).slice(0, 10);
|
|
199223
|
-
} catch {
|
|
199355
|
+
} catch (error40) {
|
|
199356
|
+
if (signal?.aborted) throw error40;
|
|
199224
199357
|
return [];
|
|
199225
199358
|
}
|
|
199226
199359
|
}
|
|
199227
|
-
async function runExtract(input, existingEntities, useLLM = false) {
|
|
199360
|
+
async function runExtract(input, existingEntities, useLLM = false, signal) {
|
|
199228
199361
|
const callerFacts = input.facts ?? [];
|
|
199229
199362
|
let extractedFacts;
|
|
199230
199363
|
if (useLLM) {
|
|
199231
|
-
extractedFacts = await extractFactsWithLLM(input.narrative, input.title, callerFacts);
|
|
199364
|
+
extractedFacts = await extractFactsWithLLM(input.narrative, input.title, callerFacts, signal);
|
|
199232
199365
|
if (extractedFacts.length === 0) {
|
|
199233
199366
|
extractedFacts = extractFacts2(input.narrative, callerFacts);
|
|
199234
199367
|
}
|
|
@@ -199448,7 +199581,7 @@ function mergeFacts2(oldFacts, newFacts) {
|
|
|
199448
199581
|
}
|
|
199449
199582
|
return merged;
|
|
199450
199583
|
}
|
|
199451
|
-
async function resolveWithLLM(extracted, hits, getObservation2) {
|
|
199584
|
+
async function resolveWithLLM(extracted, hits, getObservation2, signal) {
|
|
199452
199585
|
try {
|
|
199453
199586
|
const { callLLM: callLLM2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
|
|
199454
199587
|
const existingMemories = hits.slice(0, 5).map((h5, i4) => ({
|
|
@@ -199465,7 +199598,7 @@ Facts: ${extracted.facts.join("; ")}
|
|
|
199465
199598
|
|
|
199466
199599
|
EXISTING MEMORIES:
|
|
199467
199600
|
${existingMemories.map((m6) => `[ID:${m6.id}] ${m6.title} | ${m6.content} | Facts: ${m6.facts}`).join("\n")}`;
|
|
199468
|
-
const response = await callLLM2(LLM_RESOLVE_PROMPT, input);
|
|
199601
|
+
const response = await callLLM2(LLM_RESOLVE_PROMPT, input, signal);
|
|
199469
199602
|
const text2 = response.content.trim();
|
|
199470
199603
|
const jsonMatch = text2.match(/\{[\s\S]*\}/);
|
|
199471
199604
|
if (!jsonMatch) return null;
|
|
@@ -199502,7 +199635,8 @@ ${existingMemories.map((m6) => `[ID:${m6.id}] ${m6.title} | ${m6.content} | Fact
|
|
|
199502
199635
|
};
|
|
199503
199636
|
}
|
|
199504
199637
|
return null;
|
|
199505
|
-
} catch {
|
|
199638
|
+
} catch (error40) {
|
|
199639
|
+
if (signal?.aborted) throw error40;
|
|
199506
199640
|
return null;
|
|
199507
199641
|
}
|
|
199508
199642
|
}
|
|
@@ -199520,19 +199654,20 @@ function scoreCandidate(extracted, candidate2) {
|
|
|
199520
199654
|
const contradiction = hasContradiction(candidate2.narrative, extracted.narrative);
|
|
199521
199655
|
return { score, searchSimilarity, entityMatch, richer, contradiction };
|
|
199522
199656
|
}
|
|
199523
|
-
async function runResolve(extracted, projectId, searchMemories3, getObservation2, useLLM = false) {
|
|
199657
|
+
async function runResolve(extracted, projectId, searchMemories3, getObservation2, useLLM = false, signal) {
|
|
199524
199658
|
const query = `${extracted.title} ${extracted.narrative.substring(0, 200)}`;
|
|
199525
199659
|
let hits;
|
|
199526
199660
|
try {
|
|
199527
|
-
hits = await searchMemories3(query, 5, projectId);
|
|
199528
|
-
} catch {
|
|
199661
|
+
hits = await searchMemories3(query, 5, projectId, signal);
|
|
199662
|
+
} catch (error40) {
|
|
199663
|
+
if (signal?.aborted) throw error40;
|
|
199529
199664
|
return { action: "new", reason: "Search unavailable, defaulting to new" };
|
|
199530
199665
|
}
|
|
199531
199666
|
if (hits.length === 0) {
|
|
199532
199667
|
return { action: "new", reason: "No similar existing memories found" };
|
|
199533
199668
|
}
|
|
199534
199669
|
if (useLLM) {
|
|
199535
|
-
const llmResult = await resolveWithLLM(extracted, hits, getObservation2);
|
|
199670
|
+
const llmResult = await resolveWithLLM(extracted, hits, getObservation2, signal);
|
|
199536
199671
|
if (llmResult) return llmResult;
|
|
199537
199672
|
}
|
|
199538
199673
|
const scored = hits.map((hit) => ({
|
|
@@ -199954,7 +200089,7 @@ async function runFormation(input, config2) {
|
|
|
199954
200089
|
const existingEntities = config2.getEntityNames();
|
|
199955
200090
|
const extractStartTime = Date.now();
|
|
199956
200091
|
emitStageEvent("extract", "start");
|
|
199957
|
-
const extraction = await runExtract(input, existingEntities, config2.useLLM);
|
|
200092
|
+
const extraction = await runExtract(input, existingEntities, config2.useLLM, config2.signal);
|
|
199958
200093
|
stageDurationsMs.extract = Date.now() - extractStartTime;
|
|
199959
200094
|
emitStageEvent("extract", "success", stageDurationsMs.extract);
|
|
199960
200095
|
stagesCompleted = 1;
|
|
@@ -199974,7 +200109,8 @@ async function runFormation(input, config2) {
|
|
|
199974
200109
|
input.projectId,
|
|
199975
200110
|
config2.searchMemories,
|
|
199976
200111
|
config2.getObservation,
|
|
199977
|
-
config2.useLLM
|
|
200112
|
+
config2.useLLM,
|
|
200113
|
+
config2.signal
|
|
199978
200114
|
);
|
|
199979
200115
|
stageDurationsMs.resolve = Date.now() - resolveStartTime;
|
|
199980
200116
|
emitStageEvent("resolve", "success", stageDurationsMs.resolve);
|
|
@@ -258708,7 +258844,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
258708
258844
|
};
|
|
258709
258845
|
const server = existingServer ?? new McpServer({
|
|
258710
258846
|
name: "memorix",
|
|
258711
|
-
version: true ? "1.5.
|
|
258847
|
+
version: true ? "1.5.1" : "1.0.1"
|
|
258712
258848
|
});
|
|
258713
258849
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
258714
258850
|
server.registerTool = ((name, ...args) => {
|
|
@@ -258897,8 +259033,8 @@ The path should point to a directory containing a .git folder.`
|
|
|
258897
259033
|
mode: "active",
|
|
258898
259034
|
useLLM: isLLMEnabled(),
|
|
258899
259035
|
minValueScore: 0.3,
|
|
258900
|
-
searchMemories: async (q4, limit2, pid) => {
|
|
258901
|
-
const result = await compactSearch({ query: q4, limit: limit2, projectId: pid, status: "active", reader });
|
|
259036
|
+
searchMemories: async (q4, limit2, pid, signal) => {
|
|
259037
|
+
const result = await compactSearch({ query: q4, limit: limit2, projectId: pid, status: "active", reader, signal });
|
|
258902
259038
|
if (result.entries.length === 0) return [];
|
|
258903
259039
|
const details = await compactDetail(result.entries.map((e5) => e5.id), { reader });
|
|
258904
259040
|
return details.documents.map((d4, i4) => ({
|
|
@@ -258928,16 +259064,19 @@ The path should point to a directory containing a .git folder.`
|
|
|
258928
259064
|
getEntityNames: () => graphManager.getEntityNames(),
|
|
258929
259065
|
onStageEvent: onFormationStageEvent
|
|
258930
259066
|
};
|
|
258931
|
-
formationResult = await
|
|
258932
|
-
|
|
258933
|
-
|
|
258934
|
-
|
|
258935
|
-
|
|
258936
|
-
|
|
258937
|
-
|
|
258938
|
-
|
|
258939
|
-
|
|
258940
|
-
|
|
259067
|
+
formationResult = await withTimeoutSignal(
|
|
259068
|
+
async (signal) => {
|
|
259069
|
+
formationConfig.signal = signal;
|
|
259070
|
+
return runFormation({
|
|
259071
|
+
entityName,
|
|
259072
|
+
type,
|
|
259073
|
+
title,
|
|
259074
|
+
narrative,
|
|
259075
|
+
facts: safeFacts,
|
|
259076
|
+
projectId: project.id,
|
|
259077
|
+
source: "explicit"
|
|
259078
|
+
}, formationConfig);
|
|
259079
|
+
},
|
|
258941
259080
|
FORMATION_TIMEOUT_MS,
|
|
258942
259081
|
"Formation pipeline"
|
|
258943
259082
|
);
|
|
@@ -259287,8 +259426,8 @@ Auto-enriched: ${enrichmentParts.join(", ")}` : "";
|
|
|
259287
259426
|
mode: formationMode,
|
|
259288
259427
|
useLLM: isLLMEnabled(),
|
|
259289
259428
|
minValueScore: 0.3,
|
|
259290
|
-
searchMemories: async (q4, limit2, pid) => {
|
|
259291
|
-
const result = await compactSearch({ query: q4, limit: limit2, projectId: pid, status: "active", reader });
|
|
259429
|
+
searchMemories: async (q4, limit2, pid, signal) => {
|
|
259430
|
+
const result = await compactSearch({ query: q4, limit: limit2, projectId: pid, status: "active", reader, signal });
|
|
259292
259431
|
if (result.entries.length === 0) return [];
|
|
259293
259432
|
const details = await compactDetail(result.entries.map((e5) => e5.id), { reader });
|
|
259294
259433
|
return details.documents.map((d4, i4) => ({
|
|
@@ -259309,8 +259448,11 @@ Auto-enriched: ${enrichmentParts.join(", ")}` : "";
|
|
|
259309
259448
|
},
|
|
259310
259449
|
getEntityNames: () => graphManager.getEntityNames()
|
|
259311
259450
|
};
|
|
259312
|
-
const formed = await
|
|
259313
|
-
|
|
259451
|
+
const formed = await withTimeoutSignal(
|
|
259452
|
+
async (signal) => {
|
|
259453
|
+
formationConfig.signal = signal;
|
|
259454
|
+
return runFormation({ entityName, type, title, narrative, facts: safeFacts, projectId: project.id, source: "explicit", topicKey }, formationConfig);
|
|
259455
|
+
},
|
|
259314
259456
|
FORMATION_TIMEOUT_MS,
|
|
259315
259457
|
"Shadow formation"
|
|
259316
259458
|
);
|
package/dist/cli/memcode.js
CHANGED
|
File without changes
|