memorix 1.5.0 → 1.6.0
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 +37 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/cli/index.js +452 -109
- package/dist/index.js +376 -87
- package/dist/maintenance-runner.js +174 -41
- package/dist/media-audio-runner.js +174 -41
- package/dist/media-video-runner.js +174 -41
- package/dist/memcode-runtime/CHANGELOG.md +37 -0
- package/dist/sdk.js +375 -86
- package/dist/types.d.ts +2 -0
- package/dist/vector-backfill-runner.js +174 -41
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/API_REFERENCE.md +1 -1
- package/docs/DEVELOPMENT.md +5 -3
- 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/cli/commands/codegraph.ts +48 -5
- package/src/cli/commands/context.ts +20 -4
- package/src/cli/commands/resume.ts +4 -0
- package/src/codegraph/auto-context.ts +4 -1
- package/src/codegraph/context-pack.ts +3 -1
- package/src/codegraph/external-provider.ts +93 -0
- package/src/embedding/api-provider.ts +105 -22
- package/src/embedding/provider.ts +2 -0
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/official-skills.ts +3 -3
- package/src/hooks/rules/memorix-agent-rules.md +1 -1
- package/src/knowledge/context-receipt.ts +41 -0
- package/src/knowledge/workflows.ts +6 -3
- package/src/knowledge/workset.ts +56 -2
- package/src/llm/provider.ts +17 -8
- 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/long-term.ts +7 -1
- package/src/server.ts +29 -13
- package/src/store/orama-store.ts +6 -4
- package/src/timeout.ts +67 -0
- package/src/types.ts +2 -0
|
@@ -2755,6 +2755,8 @@ function getPreferredBatchSize(config) {
|
|
|
2755
2755
|
}
|
|
2756
2756
|
function parseBatchLimit(error) {
|
|
2757
2757
|
if (!(error instanceof Error)) return null;
|
|
2758
|
+
const status = error instanceof EmbeddingAPIError ? error.status : Number(error.message.match(/Embedding API error \((\d{3})\)/i)?.[1] ?? 0);
|
|
2759
|
+
if (status > 0 && status !== 400) return null;
|
|
2758
2760
|
const explicit = error.message.match(/should not be larger than\s+(\d+)/i);
|
|
2759
2761
|
if (explicit) return parseInt(explicit[1], 10);
|
|
2760
2762
|
if (/batch size/i.test(error.message)) {
|
|
@@ -2767,37 +2769,99 @@ async function fetchWithRetry(url, apiKey, body, options = {}, attempt = 0, nati
|
|
|
2767
2769
|
const controller = new AbortController();
|
|
2768
2770
|
const timeoutMs = typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs) ? Math.max(100, Math.min(Math.floor(options.timeoutMs), 6e4)) : 1e4;
|
|
2769
2771
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
2772
|
+
const signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal;
|
|
2770
2773
|
let response;
|
|
2771
2774
|
try {
|
|
2772
2775
|
response = await fetch(url, {
|
|
2773
2776
|
method: "POST",
|
|
2774
2777
|
headers: nativeGemini ? { "Content-Type": "application/json", "x-goog-api-key": apiKey } : { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}` },
|
|
2775
2778
|
body: JSON.stringify(body),
|
|
2776
|
-
signal
|
|
2779
|
+
signal
|
|
2777
2780
|
});
|
|
2778
2781
|
} catch (err) {
|
|
2779
2782
|
clearTimeout(timeout);
|
|
2780
|
-
if (err instanceof Error && err.name === "AbortError") {
|
|
2783
|
+
if (err instanceof Error && (err.name === "AbortError" || controller.signal.aborted || options.signal?.aborted)) {
|
|
2781
2784
|
throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url}`);
|
|
2782
2785
|
}
|
|
2783
2786
|
throw err;
|
|
2784
2787
|
}
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
+
try {
|
|
2789
|
+
if (response.ok) {
|
|
2790
|
+
return await raceWithAbort(
|
|
2791
|
+
response.json(),
|
|
2792
|
+
signal
|
|
2793
|
+
);
|
|
2794
|
+
}
|
|
2795
|
+
if (options.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
|
|
2796
|
+
const delay2 = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
2797
|
+
const retryAfter = response.headers.get("retry-after");
|
|
2798
|
+
const parsedRetryAfter = retryAfter ? parseInt(retryAfter, 10) * 1e3 : NaN;
|
|
2799
|
+
const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter : delay2;
|
|
2800
|
+
console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
|
|
2801
|
+
await waitForRetry(waitMs, options.signal);
|
|
2802
|
+
return fetchWithRetry(url, apiKey, body, options, attempt + 1, nativeGemini);
|
|
2803
|
+
}
|
|
2804
|
+
const errorText2 = await raceWithAbort(
|
|
2805
|
+
response.text().catch(() => "unknown error"),
|
|
2806
|
+
signal
|
|
2807
|
+
);
|
|
2808
|
+
throw new EmbeddingAPIError(response.status, errorText2);
|
|
2809
|
+
} catch (err) {
|
|
2810
|
+
if (err instanceof Error && (err.name === "AbortError" || controller.signal.aborted || options.signal?.aborted)) {
|
|
2811
|
+
throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url}`);
|
|
2812
|
+
}
|
|
2813
|
+
throw err;
|
|
2814
|
+
} finally {
|
|
2815
|
+
clearTimeout(timeout);
|
|
2788
2816
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2817
|
+
}
|
|
2818
|
+
function abortError() {
|
|
2819
|
+
const error = new Error("Embedding API request aborted");
|
|
2820
|
+
error.name = "AbortError";
|
|
2821
|
+
return error;
|
|
2822
|
+
}
|
|
2823
|
+
function raceWithAbort(promise, signal) {
|
|
2824
|
+
if (signal.aborted) return Promise.reject(abortError());
|
|
2825
|
+
return new Promise((resolve, reject) => {
|
|
2826
|
+
const onAbort = () => {
|
|
2827
|
+
signal.removeEventListener("abort", onAbort);
|
|
2828
|
+
reject(abortError());
|
|
2829
|
+
};
|
|
2830
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2831
|
+
promise.then(
|
|
2832
|
+
(value) => {
|
|
2833
|
+
signal.removeEventListener("abort", onAbort);
|
|
2834
|
+
resolve(value);
|
|
2835
|
+
},
|
|
2836
|
+
(error) => {
|
|
2837
|
+
signal.removeEventListener("abort", onAbort);
|
|
2838
|
+
reject(error);
|
|
2839
|
+
}
|
|
2840
|
+
);
|
|
2841
|
+
});
|
|
2842
|
+
}
|
|
2843
|
+
async function waitForRetry(waitMs, signal) {
|
|
2844
|
+
if (!signal) {
|
|
2794
2845
|
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
2795
|
-
return
|
|
2846
|
+
return;
|
|
2796
2847
|
}
|
|
2797
|
-
const
|
|
2798
|
-
throw new Error(
|
|
2848
|
+
const abortSignal = signal;
|
|
2849
|
+
if (abortSignal.aborted) throw new Error("Embedding API retry aborted");
|
|
2850
|
+
await new Promise((resolve, reject) => {
|
|
2851
|
+
const timer = setTimeout(done, waitMs);
|
|
2852
|
+
const onAbort = () => {
|
|
2853
|
+
clearTimeout(timer);
|
|
2854
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
2855
|
+
reject(new Error("Embedding API retry aborted"));
|
|
2856
|
+
};
|
|
2857
|
+
function done() {
|
|
2858
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
2859
|
+
resolve();
|
|
2860
|
+
}
|
|
2861
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
2862
|
+
});
|
|
2799
2863
|
}
|
|
2800
|
-
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;
|
|
2864
|
+
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;
|
|
2801
2865
|
var init_api_provider = __esm({
|
|
2802
2866
|
"src/embedding/api-provider.ts"() {
|
|
2803
2867
|
"use strict";
|
|
@@ -2816,6 +2880,14 @@ var init_api_provider = __esm({
|
|
|
2816
2880
|
DASHSCOPE_MAX_BATCH_SIZE = 10;
|
|
2817
2881
|
MAX_RETRIES2 = 3;
|
|
2818
2882
|
BASE_DELAY_MS = 500;
|
|
2883
|
+
EmbeddingAPIError = class extends Error {
|
|
2884
|
+
status;
|
|
2885
|
+
constructor(status, detail) {
|
|
2886
|
+
super(`Embedding API error (${status}): ${detail}`);
|
|
2887
|
+
this.name = "EmbeddingAPIError";
|
|
2888
|
+
this.status = status;
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2819
2891
|
APIEmbeddingProvider = class _APIEmbeddingProvider {
|
|
2820
2892
|
name;
|
|
2821
2893
|
dimensions;
|
|
@@ -3027,15 +3099,14 @@ var init_api_provider = __esm({
|
|
|
3027
3099
|
}
|
|
3028
3100
|
} catch (error) {
|
|
3029
3101
|
const providerLimit = parseBatchLimit(error);
|
|
3030
|
-
|
|
3031
|
-
if (chunkTexts.length > 1 && fallbackSize < chunkTexts.length) {
|
|
3102
|
+
if (providerLimit !== null && chunkTexts.length > 1 && providerLimit < chunkTexts.length) {
|
|
3032
3103
|
console.error(
|
|
3033
|
-
`[memorix] Embedding batch too large for provider, retrying in chunks of ${
|
|
3104
|
+
`[memorix] Embedding batch too large for provider, retrying in chunks of ${providerLimit}`
|
|
3034
3105
|
);
|
|
3035
|
-
for (let start = 0; start < chunkTexts.length; start +=
|
|
3106
|
+
for (let start = 0; start < chunkTexts.length; start += providerLimit) {
|
|
3036
3107
|
await processChunk(
|
|
3037
|
-
chunkTexts.slice(start, start +
|
|
3038
|
-
chunkIndices.slice(start, start +
|
|
3108
|
+
chunkTexts.slice(start, start + providerLimit),
|
|
3109
|
+
chunkIndices.slice(start, start + providerLimit)
|
|
3039
3110
|
);
|
|
3040
3111
|
}
|
|
3041
3112
|
return;
|
|
@@ -3899,22 +3970,23 @@ function getLLMConfig() {
|
|
|
3899
3970
|
function setLLMConfig(config) {
|
|
3900
3971
|
currentConfig = config;
|
|
3901
3972
|
}
|
|
3902
|
-
async function callLLM(systemPrompt, userMessage) {
|
|
3973
|
+
async function callLLM(systemPrompt, userMessage, signal) {
|
|
3903
3974
|
if (!currentConfig) {
|
|
3904
3975
|
throw new Error("LLM not configured. Set MEMORIX_LLM_API_KEY or OPENAI_API_KEY.");
|
|
3905
3976
|
}
|
|
3906
3977
|
if (currentConfig.provider === "anthropic") {
|
|
3907
|
-
return callAnthropic(systemPrompt, userMessage);
|
|
3978
|
+
return callAnthropic(systemPrompt, userMessage, signal);
|
|
3908
3979
|
}
|
|
3909
|
-
return callOpenAICompatible(systemPrompt, userMessage);
|
|
3980
|
+
return callOpenAICompatible(systemPrompt, userMessage, signal);
|
|
3910
3981
|
}
|
|
3911
|
-
async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
3982
|
+
async function callOpenAICompatible(systemPrompt, userMessage, signal) {
|
|
3912
3983
|
const config = currentConfig;
|
|
3913
3984
|
let base = config.baseUrl.replace(/\/+$/, "");
|
|
3914
3985
|
if (!base.endsWith("/v1")) base += "/v1";
|
|
3915
3986
|
const url = `${base}/chat/completions`;
|
|
3987
|
+
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
3916
3988
|
const response = await fetch(url, {
|
|
3917
|
-
signal:
|
|
3989
|
+
signal: fetchSignal,
|
|
3918
3990
|
method: "POST",
|
|
3919
3991
|
headers: {
|
|
3920
3992
|
"Content-Type": "application/json",
|
|
@@ -3931,10 +4003,10 @@ async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
|
3931
4003
|
})
|
|
3932
4004
|
});
|
|
3933
4005
|
if (!response.ok) {
|
|
3934
|
-
const error = await readResponseText(response,
|
|
4006
|
+
const error = await readResponseText(response, signal, 64 * 1024).catch(() => "unknown error");
|
|
3935
4007
|
throw new Error(`LLM API error (${response.status}): ${error}`);
|
|
3936
4008
|
}
|
|
3937
|
-
const data = await readResponseJson(response);
|
|
4009
|
+
const data = await readResponseJson(response, signal);
|
|
3938
4010
|
return {
|
|
3939
4011
|
content: data.choices[0]?.message?.content ?? "",
|
|
3940
4012
|
usage: data.usage ? {
|
|
@@ -3943,11 +4015,12 @@ async function callOpenAICompatible(systemPrompt, userMessage) {
|
|
|
3943
4015
|
} : void 0
|
|
3944
4016
|
};
|
|
3945
4017
|
}
|
|
3946
|
-
async function callAnthropic(systemPrompt, userMessage) {
|
|
4018
|
+
async function callAnthropic(systemPrompt, userMessage, signal) {
|
|
3947
4019
|
const config = currentConfig;
|
|
3948
4020
|
const url = `${config.baseUrl}/messages`;
|
|
4021
|
+
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
3949
4022
|
const response = await fetch(url, {
|
|
3950
|
-
signal:
|
|
4023
|
+
signal: fetchSignal,
|
|
3951
4024
|
method: "POST",
|
|
3952
4025
|
headers: {
|
|
3953
4026
|
"Content-Type": "application/json",
|
|
@@ -3965,10 +4038,10 @@ async function callAnthropic(systemPrompt, userMessage) {
|
|
|
3965
4038
|
})
|
|
3966
4039
|
});
|
|
3967
4040
|
if (!response.ok) {
|
|
3968
|
-
const error = await readResponseText(response,
|
|
4041
|
+
const error = await readResponseText(response, signal, 64 * 1024).catch(() => "unknown error");
|
|
3969
4042
|
throw new Error(`Anthropic API error (${response.status}): ${error}`);
|
|
3970
4043
|
}
|
|
3971
|
-
const data = await readResponseJson(response);
|
|
4044
|
+
const data = await readResponseJson(response, signal);
|
|
3972
4045
|
return {
|
|
3973
4046
|
content: data.content[0]?.text ?? "",
|
|
3974
4047
|
usage: data.usage ? {
|
|
@@ -4473,6 +4546,57 @@ function withTimeout(promise, ms, label) {
|
|
|
4473
4546
|
);
|
|
4474
4547
|
});
|
|
4475
4548
|
}
|
|
4549
|
+
function withTimeoutSignal(operation, ms, label, parentSignal) {
|
|
4550
|
+
const controller = new AbortController();
|
|
4551
|
+
const signal = parentSignal ? AbortSignal.any([parentSignal, controller.signal]) : controller.signal;
|
|
4552
|
+
return new Promise((resolve, reject) => {
|
|
4553
|
+
let settled = false;
|
|
4554
|
+
let timedOut = false;
|
|
4555
|
+
let timer;
|
|
4556
|
+
const cleanup = () => {
|
|
4557
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
4558
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
4559
|
+
};
|
|
4560
|
+
const onParentAbort = () => {
|
|
4561
|
+
if (settled || timedOut) return;
|
|
4562
|
+
settled = true;
|
|
4563
|
+
cleanup();
|
|
4564
|
+
reject(parentSignal?.reason ?? new Error(`${label} aborted`));
|
|
4565
|
+
};
|
|
4566
|
+
parentSignal?.addEventListener("abort", onParentAbort, { once: true });
|
|
4567
|
+
timer = setTimeout(() => {
|
|
4568
|
+
if (settled) return;
|
|
4569
|
+
timedOut = true;
|
|
4570
|
+
controller.abort(new Error(`${label} timed out after ${ms}ms`));
|
|
4571
|
+
settled = true;
|
|
4572
|
+
cleanup();
|
|
4573
|
+
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
4574
|
+
}, ms);
|
|
4575
|
+
let pending;
|
|
4576
|
+
try {
|
|
4577
|
+
pending = operation(signal);
|
|
4578
|
+
} catch (error) {
|
|
4579
|
+
settled = true;
|
|
4580
|
+
cleanup();
|
|
4581
|
+
reject(error);
|
|
4582
|
+
return;
|
|
4583
|
+
}
|
|
4584
|
+
pending.then(
|
|
4585
|
+
(value) => {
|
|
4586
|
+
if (settled) return;
|
|
4587
|
+
settled = true;
|
|
4588
|
+
cleanup();
|
|
4589
|
+
resolve(value);
|
|
4590
|
+
},
|
|
4591
|
+
(error) => {
|
|
4592
|
+
if (settled) return;
|
|
4593
|
+
settled = true;
|
|
4594
|
+
cleanup();
|
|
4595
|
+
reject(timedOut ? new Error(`${label} timed out after ${ms}ms`) : error);
|
|
4596
|
+
}
|
|
4597
|
+
);
|
|
4598
|
+
});
|
|
4599
|
+
}
|
|
4476
4600
|
var init_timeout = __esm({
|
|
4477
4601
|
"src/timeout.ts"() {
|
|
4478
4602
|
"use strict";
|
|
@@ -5337,16 +5461,18 @@ async function searchObservations(options) {
|
|
|
5337
5461
|
);
|
|
5338
5462
|
} else {
|
|
5339
5463
|
const EMBEDDING_TIMEOUT_MS = 15e3;
|
|
5340
|
-
queryVector = await
|
|
5341
|
-
provider2.embedInput ? provider2.embedInput(
|
|
5464
|
+
queryVector = await withTimeoutSignal(
|
|
5465
|
+
(signal) => provider2.embedInput ? provider2.embedInput(
|
|
5342
5466
|
{ modality: "text", text: expandedEmbeddingQuery },
|
|
5343
|
-
{ intent: "query", timeoutMs: EMBEDDING_TIMEOUT_MS, retry: false }
|
|
5467
|
+
{ intent: "query", timeoutMs: EMBEDDING_TIMEOUT_MS, retry: false, signal }
|
|
5344
5468
|
) : provider2.embed(expandedEmbeddingQuery, {
|
|
5345
5469
|
timeoutMs: EMBEDDING_TIMEOUT_MS,
|
|
5346
|
-
retry: false
|
|
5470
|
+
retry: false,
|
|
5471
|
+
signal
|
|
5347
5472
|
}),
|
|
5348
5473
|
EMBEDDING_TIMEOUT_MS,
|
|
5349
|
-
"Embedding"
|
|
5474
|
+
"Embedding",
|
|
5475
|
+
options.signal
|
|
5350
5476
|
);
|
|
5351
5477
|
mark("embedding");
|
|
5352
5478
|
const cjkRatio = (originalQuery.match(/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g) || []).length / originalQuery.length;
|
|
@@ -143266,7 +143392,13 @@ async function maintainLongTermMemories(input) {
|
|
|
143266
143392
|
}
|
|
143267
143393
|
for (const group of groups.values()) {
|
|
143268
143394
|
if (group.length < 2) continue;
|
|
143269
|
-
group.sort((a, b) =>
|
|
143395
|
+
group.sort((a, b) => {
|
|
143396
|
+
const byCreatedAt = Date.parse(b.createdAt) - Date.parse(a.createdAt);
|
|
143397
|
+
if (byCreatedAt !== 0) return byCreatedAt;
|
|
143398
|
+
const byUpdatedAt = Date.parse(b.updatedAt) - Date.parse(a.updatedAt);
|
|
143399
|
+
if (byUpdatedAt !== 0) return byUpdatedAt;
|
|
143400
|
+
return b.id.localeCompare(a.id);
|
|
143401
|
+
});
|
|
143270
143402
|
const newest = group[0];
|
|
143271
143403
|
for (const older of group.slice(1)) {
|
|
143272
143404
|
try {
|
|
@@ -146658,6 +146790,7 @@ var init_task_lens = __esm({
|
|
|
146658
146790
|
var workflows_exports = {};
|
|
146659
146791
|
__export(workflows_exports, {
|
|
146660
146792
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
146793
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
146661
146794
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
146662
146795
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
146663
146796
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -146723,7 +146856,7 @@ function optionalStatus(data) {
|
|
|
146723
146856
|
return value;
|
|
146724
146857
|
}
|
|
146725
146858
|
function normalizeAgents(values) {
|
|
146726
|
-
const unknown3 = values.filter((value) => !
|
|
146859
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
146727
146860
|
if (unknown3.length > 0) {
|
|
146728
146861
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
146729
146862
|
}
|
|
@@ -146999,7 +147132,7 @@ function taskScore(workflow, task) {
|
|
|
146999
147132
|
return { score, reasons: [...new Set(reasons)] };
|
|
147000
147133
|
}
|
|
147001
147134
|
function selectWorkflows(input) {
|
|
147002
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
147135
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
147003
147136
|
const match2 = taskScore(workflow, input.task);
|
|
147004
147137
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
147005
147138
|
return {
|
|
@@ -147279,7 +147412,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
147279
147412
|
errors: synced.errors
|
|
147280
147413
|
};
|
|
147281
147414
|
}
|
|
147282
|
-
var
|
|
147415
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
147283
147416
|
var init_workflows2 = __esm({
|
|
147284
147417
|
"src/knowledge/workflows.ts"() {
|
|
147285
147418
|
"use strict";
|
|
@@ -147291,7 +147424,7 @@ var init_workflows2 = __esm({
|
|
|
147291
147424
|
init_workflow_store();
|
|
147292
147425
|
init_outcome_store();
|
|
147293
147426
|
init_task_lens();
|
|
147294
|
-
|
|
147427
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
147295
147428
|
"windsurf",
|
|
147296
147429
|
"cursor",
|
|
147297
147430
|
"claude-code",
|
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [1.6.0] - 2026-08-17
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **Bounded context receipts** -- `memorix context|resume --brief-json`,
|
|
11
|
+
`memorix codegraph context-pack --brief-json`, and MCP project-context
|
|
12
|
+
`format: "receipt"` return only the agent-ready brief, selection receipt,
|
|
13
|
+
CodeGraph quality, and optional Agent loadout. The detailed `--json` and
|
|
14
|
+
MCP `format: "json"` forms remain available for diagnostics.
|
|
15
|
+
- **Task-scoped Agent loadouts** -- `--agent <target>` selects only compatible
|
|
16
|
+
project workflows and reports their required context and workflow tools.
|
|
17
|
+
This is guidance, not a replacement for the host agent's authorization.
|
|
18
|
+
- **Explicit external CodeGraph lifecycle** -- `memorix codegraph init|sync`
|
|
19
|
+
manages an already installed local CodeGraph index. It never invokes
|
|
20
|
+
CodeGraph's agent installer or writes Agent configuration.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- **Honest CodeGraph status** -- Status now distinguishes the persistent Lite
|
|
24
|
+
Code State index from the provider actually usable for the current task.
|
|
25
|
+
A stale external graph falls back to Lite instead of being presented as fresh.
|
|
26
|
+
- **Bounded fallback guidance** -- Newly generated Agent rules teach
|
|
27
|
+
`--brief-json` for the one CLI fallback; `--json` is reserved for deliberate
|
|
28
|
+
detailed diagnostics.
|
|
29
|
+
|
|
30
|
+
## [1.5.1] - 2026-08-16
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **Bounded formation cancellation** -- Formation deadlines now abort the
|
|
34
|
+
LLM and vector-search work they started, including response-body reads and
|
|
35
|
+
retry waits. A provider that ignores cancellation still cannot hold the
|
|
36
|
+
caller past its deadline.
|
|
37
|
+
- **Embedding error classification** -- Only an explicit HTTP 400 batch-shape
|
|
38
|
+
error may trigger batch splitting. Authentication, billing, quota, and
|
|
39
|
+
upstream errors fail once instead of multiplying latency through recursive
|
|
40
|
+
retries.
|
|
41
|
+
|
|
5
42
|
## [1.5.0] - 2026-08-14
|
|
6
43
|
|
|
7
44
|
### Added
|