memorix 1.5.1 → 1.6.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 +47 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/cli/index.js +558 -102
- package/dist/cli/memcode.js +12 -1
- package/dist/index.js +221 -27
- package/dist/maintenance-runner.js +59 -11
- package/dist/media-audio-runner.js +59 -11
- package/dist/media-video-runner.js +59 -11
- package/dist/memcode-runtime/CHANGELOG.md +47 -0
- package/dist/sdk.js +220 -26
- package/dist/vector-backfill-runner.js +59 -11
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
- package/docs/API_REFERENCE.md +2 -2
- package/docs/DEVELOPMENT.md +5 -3
- package/docs/DOCKER.md +5 -1
- package/docs/PERFORMANCE.md +2 -2
- package/docs/README.md +3 -1
- package/docs/SETUP.md +8 -2
- 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/agent-integrations.ts +9 -3
- package/src/cli/commands/codegraph.ts +48 -5
- package/src/cli/commands/context.ts +20 -4
- package/src/cli/commands/doctor.ts +46 -15
- package/src/cli/commands/hook.ts +13 -1
- package/src/cli/commands/resume.ts +4 -0
- package/src/cli/commands/serve-http.ts +68 -7
- package/src/cli/heap.ts +76 -0
- package/src/cli/invocation.ts +7 -4
- 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/provider.ts +76 -6
- package/src/hooks/handler.ts +9 -18
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/lifecycle.ts +173 -0
- 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/server.ts +15 -3
|
@@ -4308,6 +4308,7 @@ __export(provider_exports2, {
|
|
|
4308
4308
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
4309
4309
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
4310
4310
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
4311
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
4311
4312
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
4312
4313
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
4313
4314
|
resetProvider: () => resetProvider,
|
|
@@ -4415,13 +4416,36 @@ function isTemporaryEmbeddingFailure(error) {
|
|
|
4415
4416
|
if (!(error instanceof Error)) return false;
|
|
4416
4417
|
return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
|
|
4417
4418
|
}
|
|
4419
|
+
function classifyEmbeddingFailure(error) {
|
|
4420
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4421
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
4422
|
+
return "authorization";
|
|
4423
|
+
}
|
|
4424
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
4425
|
+
return "billing";
|
|
4426
|
+
}
|
|
4427
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
4428
|
+
return "timeout";
|
|
4429
|
+
}
|
|
4430
|
+
return "upstream";
|
|
4431
|
+
}
|
|
4418
4432
|
function markTemporaryFailure(reason) {
|
|
4419
4433
|
provider = null;
|
|
4420
4434
|
initPromise = null;
|
|
4421
4435
|
lastInitWasTemporaryFailure = true;
|
|
4422
4436
|
lastFailureTimestamp = Date.now();
|
|
4437
|
+
lastEmbeddingFailure = {
|
|
4438
|
+
kind: classifyEmbeddingFailure(reason),
|
|
4439
|
+
occurredAt: lastFailureTimestamp
|
|
4440
|
+
};
|
|
4423
4441
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
4424
|
-
warnOnce(`[memorix] Embedding provider
|
|
4442
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
4443
|
+
}
|
|
4444
|
+
function markProviderReady(candidate) {
|
|
4445
|
+
provider = wrapProvider(candidate);
|
|
4446
|
+
lastInitWasTemporaryFailure = false;
|
|
4447
|
+
lastEmbeddingFailure = null;
|
|
4448
|
+
return provider;
|
|
4425
4449
|
}
|
|
4426
4450
|
async function createFastEmbedProvider() {
|
|
4427
4451
|
try {
|
|
@@ -4537,35 +4561,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
4537
4561
|
if (mode === "fastembed") {
|
|
4538
4562
|
const initialized = await createFastEmbedProvider();
|
|
4539
4563
|
if (!initialized) return null;
|
|
4540
|
-
provider =
|
|
4564
|
+
provider = markProviderReady(initialized);
|
|
4541
4565
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4542
4566
|
return provider;
|
|
4543
4567
|
}
|
|
4544
4568
|
if (mode === "transformers") {
|
|
4545
4569
|
const initialized = await createTransformersProvider();
|
|
4546
4570
|
if (!initialized) return null;
|
|
4547
|
-
provider =
|
|
4571
|
+
provider = markProviderReady(initialized);
|
|
4548
4572
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4549
4573
|
return provider;
|
|
4550
4574
|
}
|
|
4551
4575
|
if (mode === "api") {
|
|
4552
4576
|
const initialized = await createAPIProvider(options);
|
|
4553
4577
|
if (!initialized) return null;
|
|
4554
|
-
provider =
|
|
4578
|
+
provider = markProviderReady(initialized);
|
|
4555
4579
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4556
4580
|
return provider;
|
|
4557
4581
|
}
|
|
4558
4582
|
if (hasAPIEmbeddingConfig()) {
|
|
4559
4583
|
const initialized = await createAPIProvider(options);
|
|
4560
4584
|
if (initialized) {
|
|
4561
|
-
provider =
|
|
4585
|
+
provider = markProviderReady(initialized);
|
|
4562
4586
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4563
4587
|
return provider;
|
|
4564
4588
|
}
|
|
4565
4589
|
}
|
|
4566
4590
|
const localFallback = await createLocalFallbackProvider();
|
|
4567
4591
|
if (localFallback) {
|
|
4568
|
-
provider =
|
|
4592
|
+
provider = markProviderReady(localFallback);
|
|
4569
4593
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4570
4594
|
return provider;
|
|
4571
4595
|
}
|
|
@@ -4587,6 +4611,27 @@ async function isVectorSearchAvailable() {
|
|
|
4587
4611
|
const p = await getEmbeddingProvider();
|
|
4588
4612
|
return p !== null;
|
|
4589
4613
|
}
|
|
4614
|
+
function getEmbeddingRuntimeHealth() {
|
|
4615
|
+
const mode = getEmbeddingMode2();
|
|
4616
|
+
if (mode === "off") return { status: "disabled" };
|
|
4617
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
4618
|
+
return {
|
|
4619
|
+
status: "degraded",
|
|
4620
|
+
failure: {
|
|
4621
|
+
kind: lastEmbeddingFailure.kind,
|
|
4622
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
4623
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
4624
|
+
}
|
|
4625
|
+
};
|
|
4626
|
+
}
|
|
4627
|
+
if (provider) {
|
|
4628
|
+
return {
|
|
4629
|
+
status: "ready",
|
|
4630
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
4631
|
+
};
|
|
4632
|
+
}
|
|
4633
|
+
return { status: "uninitialized" };
|
|
4634
|
+
}
|
|
4590
4635
|
function isEmbeddingExplicitlyDisabled() {
|
|
4591
4636
|
return getEmbeddingMode2() === "off";
|
|
4592
4637
|
}
|
|
@@ -4595,10 +4640,11 @@ function resetProvider() {
|
|
|
4595
4640
|
initPromise = null;
|
|
4596
4641
|
lastInitWasTemporaryFailure = false;
|
|
4597
4642
|
lastFailureTimestamp = 0;
|
|
4643
|
+
lastEmbeddingFailure = null;
|
|
4598
4644
|
lastEmbeddingWarning = "";
|
|
4599
4645
|
lastEmbeddingWarningAt = 0;
|
|
4600
4646
|
}
|
|
4601
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4647
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4602
4648
|
var init_provider2 = __esm({
|
|
4603
4649
|
"src/embedding/provider.ts"() {
|
|
4604
4650
|
"use strict";
|
|
@@ -4623,6 +4669,7 @@ var init_provider2 = __esm({
|
|
|
4623
4669
|
provider = null;
|
|
4624
4670
|
initPromise = null;
|
|
4625
4671
|
lastInitWasTemporaryFailure = false;
|
|
4672
|
+
lastEmbeddingFailure = null;
|
|
4626
4673
|
lastEmbeddingWarning = "";
|
|
4627
4674
|
lastEmbeddingWarningAt = 0;
|
|
4628
4675
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -146819,6 +146866,7 @@ var init_task_lens = __esm({
|
|
|
146819
146866
|
var workflows_exports = {};
|
|
146820
146867
|
__export(workflows_exports, {
|
|
146821
146868
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
146869
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
146822
146870
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
146823
146871
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
146824
146872
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -146884,7 +146932,7 @@ function optionalStatus(data) {
|
|
|
146884
146932
|
return value;
|
|
146885
146933
|
}
|
|
146886
146934
|
function normalizeAgents(values) {
|
|
146887
|
-
const unknown3 = values.filter((value) => !
|
|
146935
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
146888
146936
|
if (unknown3.length > 0) {
|
|
146889
146937
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
146890
146938
|
}
|
|
@@ -147160,7 +147208,7 @@ function taskScore(workflow, task) {
|
|
|
147160
147208
|
return { score, reasons: [...new Set(reasons)] };
|
|
147161
147209
|
}
|
|
147162
147210
|
function selectWorkflows(input) {
|
|
147163
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
147211
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
147164
147212
|
const match2 = taskScore(workflow, input.task);
|
|
147165
147213
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
147166
147214
|
return {
|
|
@@ -147440,7 +147488,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
147440
147488
|
errors: synced.errors
|
|
147441
147489
|
};
|
|
147442
147490
|
}
|
|
147443
|
-
var
|
|
147491
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
147444
147492
|
var init_workflows2 = __esm({
|
|
147445
147493
|
"src/knowledge/workflows.ts"() {
|
|
147446
147494
|
"use strict";
|
|
@@ -147452,7 +147500,7 @@ var init_workflows2 = __esm({
|
|
|
147452
147500
|
init_workflow_store();
|
|
147453
147501
|
init_outcome_store();
|
|
147454
147502
|
init_task_lens();
|
|
147455
|
-
|
|
147503
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
147456
147504
|
"windsurf",
|
|
147457
147505
|
"cursor",
|
|
147458
147506
|
"claude-code",
|
|
@@ -4189,6 +4189,7 @@ __export(provider_exports, {
|
|
|
4189
4189
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
4190
4190
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
4191
4191
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
4192
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
4192
4193
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
4193
4194
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
4194
4195
|
resetProvider: () => resetProvider,
|
|
@@ -4296,13 +4297,36 @@ function isTemporaryEmbeddingFailure(error) {
|
|
|
4296
4297
|
if (!(error instanceof Error)) return false;
|
|
4297
4298
|
return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
|
|
4298
4299
|
}
|
|
4300
|
+
function classifyEmbeddingFailure(error) {
|
|
4301
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4302
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
4303
|
+
return "authorization";
|
|
4304
|
+
}
|
|
4305
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
4306
|
+
return "billing";
|
|
4307
|
+
}
|
|
4308
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
4309
|
+
return "timeout";
|
|
4310
|
+
}
|
|
4311
|
+
return "upstream";
|
|
4312
|
+
}
|
|
4299
4313
|
function markTemporaryFailure(reason) {
|
|
4300
4314
|
provider = null;
|
|
4301
4315
|
initPromise = null;
|
|
4302
4316
|
lastInitWasTemporaryFailure = true;
|
|
4303
4317
|
lastFailureTimestamp = Date.now();
|
|
4318
|
+
lastEmbeddingFailure = {
|
|
4319
|
+
kind: classifyEmbeddingFailure(reason),
|
|
4320
|
+
occurredAt: lastFailureTimestamp
|
|
4321
|
+
};
|
|
4304
4322
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
4305
|
-
warnOnce(`[memorix] Embedding provider
|
|
4323
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
4324
|
+
}
|
|
4325
|
+
function markProviderReady(candidate) {
|
|
4326
|
+
provider = wrapProvider(candidate);
|
|
4327
|
+
lastInitWasTemporaryFailure = false;
|
|
4328
|
+
lastEmbeddingFailure = null;
|
|
4329
|
+
return provider;
|
|
4306
4330
|
}
|
|
4307
4331
|
async function createFastEmbedProvider() {
|
|
4308
4332
|
try {
|
|
@@ -4418,35 +4442,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
4418
4442
|
if (mode === "fastembed") {
|
|
4419
4443
|
const initialized = await createFastEmbedProvider();
|
|
4420
4444
|
if (!initialized) return null;
|
|
4421
|
-
provider =
|
|
4445
|
+
provider = markProviderReady(initialized);
|
|
4422
4446
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4423
4447
|
return provider;
|
|
4424
4448
|
}
|
|
4425
4449
|
if (mode === "transformers") {
|
|
4426
4450
|
const initialized = await createTransformersProvider();
|
|
4427
4451
|
if (!initialized) return null;
|
|
4428
|
-
provider =
|
|
4452
|
+
provider = markProviderReady(initialized);
|
|
4429
4453
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4430
4454
|
return provider;
|
|
4431
4455
|
}
|
|
4432
4456
|
if (mode === "api") {
|
|
4433
4457
|
const initialized = await createAPIProvider(options);
|
|
4434
4458
|
if (!initialized) return null;
|
|
4435
|
-
provider =
|
|
4459
|
+
provider = markProviderReady(initialized);
|
|
4436
4460
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4437
4461
|
return provider;
|
|
4438
4462
|
}
|
|
4439
4463
|
if (hasAPIEmbeddingConfig()) {
|
|
4440
4464
|
const initialized = await createAPIProvider(options);
|
|
4441
4465
|
if (initialized) {
|
|
4442
|
-
provider =
|
|
4466
|
+
provider = markProviderReady(initialized);
|
|
4443
4467
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4444
4468
|
return provider;
|
|
4445
4469
|
}
|
|
4446
4470
|
}
|
|
4447
4471
|
const localFallback = await createLocalFallbackProvider();
|
|
4448
4472
|
if (localFallback) {
|
|
4449
|
-
provider =
|
|
4473
|
+
provider = markProviderReady(localFallback);
|
|
4450
4474
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
4451
4475
|
return provider;
|
|
4452
4476
|
}
|
|
@@ -4468,6 +4492,27 @@ async function isVectorSearchAvailable() {
|
|
|
4468
4492
|
const p = await getEmbeddingProvider();
|
|
4469
4493
|
return p !== null;
|
|
4470
4494
|
}
|
|
4495
|
+
function getEmbeddingRuntimeHealth() {
|
|
4496
|
+
const mode = getEmbeddingMode2();
|
|
4497
|
+
if (mode === "off") return { status: "disabled" };
|
|
4498
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
4499
|
+
return {
|
|
4500
|
+
status: "degraded",
|
|
4501
|
+
failure: {
|
|
4502
|
+
kind: lastEmbeddingFailure.kind,
|
|
4503
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
4504
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
4505
|
+
}
|
|
4506
|
+
};
|
|
4507
|
+
}
|
|
4508
|
+
if (provider) {
|
|
4509
|
+
return {
|
|
4510
|
+
status: "ready",
|
|
4511
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4514
|
+
return { status: "uninitialized" };
|
|
4515
|
+
}
|
|
4471
4516
|
function isEmbeddingExplicitlyDisabled() {
|
|
4472
4517
|
return getEmbeddingMode2() === "off";
|
|
4473
4518
|
}
|
|
@@ -4476,10 +4521,11 @@ function resetProvider() {
|
|
|
4476
4521
|
initPromise = null;
|
|
4477
4522
|
lastInitWasTemporaryFailure = false;
|
|
4478
4523
|
lastFailureTimestamp = 0;
|
|
4524
|
+
lastEmbeddingFailure = null;
|
|
4479
4525
|
lastEmbeddingWarning = "";
|
|
4480
4526
|
lastEmbeddingWarningAt = 0;
|
|
4481
4527
|
}
|
|
4482
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4528
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
4483
4529
|
var init_provider = __esm({
|
|
4484
4530
|
"src/embedding/provider.ts"() {
|
|
4485
4531
|
"use strict";
|
|
@@ -4504,6 +4550,7 @@ var init_provider = __esm({
|
|
|
4504
4550
|
provider = null;
|
|
4505
4551
|
initPromise = null;
|
|
4506
4552
|
lastInitWasTemporaryFailure = false;
|
|
4553
|
+
lastEmbeddingFailure = null;
|
|
4507
4554
|
lastEmbeddingWarning = "";
|
|
4508
4555
|
lastEmbeddingWarningAt = 0;
|
|
4509
4556
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -146451,6 +146498,7 @@ var init_task_lens = __esm({
|
|
|
146451
146498
|
var workflows_exports = {};
|
|
146452
146499
|
__export(workflows_exports, {
|
|
146453
146500
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
146501
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
146454
146502
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
146455
146503
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
146456
146504
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -146516,7 +146564,7 @@ function optionalStatus(data) {
|
|
|
146516
146564
|
return value;
|
|
146517
146565
|
}
|
|
146518
146566
|
function normalizeAgents(values) {
|
|
146519
|
-
const unknown3 = values.filter((value) => !
|
|
146567
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
146520
146568
|
if (unknown3.length > 0) {
|
|
146521
146569
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
146522
146570
|
}
|
|
@@ -146792,7 +146840,7 @@ function taskScore(workflow, task) {
|
|
|
146792
146840
|
return { score, reasons: [...new Set(reasons)] };
|
|
146793
146841
|
}
|
|
146794
146842
|
function selectWorkflows(input) {
|
|
146795
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
146843
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
146796
146844
|
const match2 = taskScore(workflow, input.task);
|
|
146797
146845
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
146798
146846
|
return {
|
|
@@ -147072,7 +147120,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
147072
147120
|
errors: synced.errors
|
|
147073
147121
|
};
|
|
147074
147122
|
}
|
|
147075
|
-
var
|
|
147123
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
147076
147124
|
var init_workflows2 = __esm({
|
|
147077
147125
|
"src/knowledge/workflows.ts"() {
|
|
147078
147126
|
"use strict";
|
|
@@ -147084,7 +147132,7 @@ var init_workflows2 = __esm({
|
|
|
147084
147132
|
init_workflow_store();
|
|
147085
147133
|
init_outcome_store();
|
|
147086
147134
|
init_task_lens();
|
|
147087
|
-
|
|
147135
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
147088
147136
|
"windsurf",
|
|
147089
147137
|
"cursor",
|
|
147090
147138
|
"claude-code",
|
|
@@ -3206,6 +3206,7 @@ __export(provider_exports, {
|
|
|
3206
3206
|
MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
|
|
3207
3207
|
UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
|
|
3208
3208
|
getEmbeddingProvider: () => getEmbeddingProvider,
|
|
3209
|
+
getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
|
|
3209
3210
|
isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
|
|
3210
3211
|
isVectorSearchAvailable: () => isVectorSearchAvailable,
|
|
3211
3212
|
resetProvider: () => resetProvider,
|
|
@@ -3313,13 +3314,36 @@ function isTemporaryEmbeddingFailure(error) {
|
|
|
3313
3314
|
if (!(error instanceof Error)) return false;
|
|
3314
3315
|
return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
|
|
3315
3316
|
}
|
|
3317
|
+
function classifyEmbeddingFailure(error) {
|
|
3318
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3319
|
+
if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
|
|
3320
|
+
return "authorization";
|
|
3321
|
+
}
|
|
3322
|
+
if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
|
|
3323
|
+
return "billing";
|
|
3324
|
+
}
|
|
3325
|
+
if (/embedding api timeout|abort/i.test(message)) {
|
|
3326
|
+
return "timeout";
|
|
3327
|
+
}
|
|
3328
|
+
return "upstream";
|
|
3329
|
+
}
|
|
3316
3330
|
function markTemporaryFailure(reason) {
|
|
3317
3331
|
provider = null;
|
|
3318
3332
|
initPromise = null;
|
|
3319
3333
|
lastInitWasTemporaryFailure = true;
|
|
3320
3334
|
lastFailureTimestamp = Date.now();
|
|
3335
|
+
lastEmbeddingFailure = {
|
|
3336
|
+
kind: classifyEmbeddingFailure(reason),
|
|
3337
|
+
occurredAt: lastFailureTimestamp
|
|
3338
|
+
};
|
|
3321
3339
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
3322
|
-
warnOnce(`[memorix] Embedding provider
|
|
3340
|
+
warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
|
|
3341
|
+
}
|
|
3342
|
+
function markProviderReady(candidate) {
|
|
3343
|
+
provider = wrapProvider(candidate);
|
|
3344
|
+
lastInitWasTemporaryFailure = false;
|
|
3345
|
+
lastEmbeddingFailure = null;
|
|
3346
|
+
return provider;
|
|
3323
3347
|
}
|
|
3324
3348
|
async function createFastEmbedProvider() {
|
|
3325
3349
|
try {
|
|
@@ -3435,35 +3459,35 @@ async function getEmbeddingProvider(options = {}) {
|
|
|
3435
3459
|
if (mode === "fastembed") {
|
|
3436
3460
|
const initialized = await createFastEmbedProvider();
|
|
3437
3461
|
if (!initialized) return null;
|
|
3438
|
-
provider =
|
|
3462
|
+
provider = markProviderReady(initialized);
|
|
3439
3463
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
3440
3464
|
return provider;
|
|
3441
3465
|
}
|
|
3442
3466
|
if (mode === "transformers") {
|
|
3443
3467
|
const initialized = await createTransformersProvider();
|
|
3444
3468
|
if (!initialized) return null;
|
|
3445
|
-
provider =
|
|
3469
|
+
provider = markProviderReady(initialized);
|
|
3446
3470
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
3447
3471
|
return provider;
|
|
3448
3472
|
}
|
|
3449
3473
|
if (mode === "api") {
|
|
3450
3474
|
const initialized = await createAPIProvider(options);
|
|
3451
3475
|
if (!initialized) return null;
|
|
3452
|
-
provider =
|
|
3476
|
+
provider = markProviderReady(initialized);
|
|
3453
3477
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
3454
3478
|
return provider;
|
|
3455
3479
|
}
|
|
3456
3480
|
if (hasAPIEmbeddingConfig()) {
|
|
3457
3481
|
const initialized = await createAPIProvider(options);
|
|
3458
3482
|
if (initialized) {
|
|
3459
|
-
provider =
|
|
3483
|
+
provider = markProviderReady(initialized);
|
|
3460
3484
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
3461
3485
|
return provider;
|
|
3462
3486
|
}
|
|
3463
3487
|
}
|
|
3464
3488
|
const localFallback = await createLocalFallbackProvider();
|
|
3465
3489
|
if (localFallback) {
|
|
3466
|
-
provider =
|
|
3490
|
+
provider = markProviderReady(localFallback);
|
|
3467
3491
|
warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
|
|
3468
3492
|
return provider;
|
|
3469
3493
|
}
|
|
@@ -3485,6 +3509,27 @@ async function isVectorSearchAvailable() {
|
|
|
3485
3509
|
const p = await getEmbeddingProvider();
|
|
3486
3510
|
return p !== null;
|
|
3487
3511
|
}
|
|
3512
|
+
function getEmbeddingRuntimeHealth() {
|
|
3513
|
+
const mode = getEmbeddingMode2();
|
|
3514
|
+
if (mode === "off") return { status: "disabled" };
|
|
3515
|
+
if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
|
|
3516
|
+
return {
|
|
3517
|
+
status: "degraded",
|
|
3518
|
+
failure: {
|
|
3519
|
+
kind: lastEmbeddingFailure.kind,
|
|
3520
|
+
occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
|
|
3521
|
+
retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
|
|
3522
|
+
}
|
|
3523
|
+
};
|
|
3524
|
+
}
|
|
3525
|
+
if (provider) {
|
|
3526
|
+
return {
|
|
3527
|
+
status: "ready",
|
|
3528
|
+
provider: { name: provider.name, dimensions: provider.dimensions }
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
return { status: "uninitialized" };
|
|
3532
|
+
}
|
|
3488
3533
|
function isEmbeddingExplicitlyDisabled() {
|
|
3489
3534
|
return getEmbeddingMode2() === "off";
|
|
3490
3535
|
}
|
|
@@ -3493,10 +3538,11 @@ function resetProvider() {
|
|
|
3493
3538
|
initPromise = null;
|
|
3494
3539
|
lastInitWasTemporaryFailure = false;
|
|
3495
3540
|
lastFailureTimestamp = 0;
|
|
3541
|
+
lastEmbeddingFailure = null;
|
|
3496
3542
|
lastEmbeddingWarning = "";
|
|
3497
3543
|
lastEmbeddingWarningAt = 0;
|
|
3498
3544
|
}
|
|
3499
|
-
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
3545
|
+
var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
|
|
3500
3546
|
var init_provider = __esm({
|
|
3501
3547
|
"src/embedding/provider.ts"() {
|
|
3502
3548
|
"use strict";
|
|
@@ -3521,6 +3567,7 @@ var init_provider = __esm({
|
|
|
3521
3567
|
provider = null;
|
|
3522
3568
|
initPromise = null;
|
|
3523
3569
|
lastInitWasTemporaryFailure = false;
|
|
3570
|
+
lastEmbeddingFailure = null;
|
|
3524
3571
|
lastEmbeddingWarning = "";
|
|
3525
3572
|
lastEmbeddingWarningAt = 0;
|
|
3526
3573
|
WARNING_COOLDOWN_MS = 3e4;
|
|
@@ -146790,6 +146837,7 @@ var init_task_lens = __esm({
|
|
|
146790
146837
|
var workflows_exports = {};
|
|
146791
146838
|
__export(workflows_exports, {
|
|
146792
146839
|
WORKFLOW_ADAPTER_TARGETS: () => WORKFLOW_ADAPTER_TARGETS,
|
|
146840
|
+
WORKFLOW_AGENT_TARGETS: () => WORKFLOW_AGENT_TARGETS,
|
|
146793
146841
|
applyWorkflowAdapter: () => applyWorkflowAdapter,
|
|
146794
146842
|
importWindsurfWorkflows: () => importWindsurfWorkflows,
|
|
146795
146843
|
parseWorkflowMarkdown: () => parseWorkflowMarkdown,
|
|
@@ -146855,7 +146903,7 @@ function optionalStatus(data) {
|
|
|
146855
146903
|
return value;
|
|
146856
146904
|
}
|
|
146857
146905
|
function normalizeAgents(values) {
|
|
146858
|
-
const unknown3 = values.filter((value) => !
|
|
146906
|
+
const unknown3 = values.filter((value) => !WORKFLOW_AGENT_TARGETS.includes(value));
|
|
146859
146907
|
if (unknown3.length > 0) {
|
|
146860
146908
|
throw new Error("workflow frontmatter has unsupported agent: " + unknown3[0]);
|
|
146861
146909
|
}
|
|
@@ -147131,7 +147179,7 @@ function taskScore(workflow, task) {
|
|
|
147131
147179
|
return { score, reasons: [...new Set(reasons)] };
|
|
147132
147180
|
}
|
|
147133
147181
|
function selectWorkflows(input) {
|
|
147134
|
-
const selected = input.workflows.filter((workflow) => workflow.status === "active").map((workflow) => {
|
|
147182
|
+
const selected = input.workflows.filter((workflow) => workflow.status === "active" && (!input.agent || workflow.compatibleAgents.includes(input.agent))).map((workflow) => {
|
|
147135
147183
|
const match2 = taskScore(workflow, input.task);
|
|
147136
147184
|
const cautions = input.store && input.projectId ? input.store.recentFailureCautions(input.projectId, workflow.id) : [];
|
|
147137
147185
|
return {
|
|
@@ -147411,7 +147459,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
147411
147459
|
errors: synced.errors
|
|
147412
147460
|
};
|
|
147413
147461
|
}
|
|
147414
|
-
var
|
|
147462
|
+
var WORKFLOW_AGENT_TARGETS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
147415
147463
|
var init_workflows2 = __esm({
|
|
147416
147464
|
"src/knowledge/workflows.ts"() {
|
|
147417
147465
|
"use strict";
|
|
@@ -147423,7 +147471,7 @@ var init_workflows2 = __esm({
|
|
|
147423
147471
|
init_workflow_store();
|
|
147424
147472
|
init_outcome_store();
|
|
147425
147473
|
init_task_lens();
|
|
147426
|
-
|
|
147474
|
+
WORKFLOW_AGENT_TARGETS = [
|
|
147427
147475
|
"windsurf",
|
|
147428
147476
|
"cursor",
|
|
147429
147477
|
"claude-code",
|
|
@@ -4,6 +4,53 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.6.1] - 2026-08-17
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **Bounded hook lifecycle on every desktop platform** -- `memorix hook` now
|
|
11
|
+
reads stdin with an idle bound, performs embedding writes in the deferred
|
|
12
|
+
lane, and has a hard process deadline. The hook-specific V8 heap is 512 MiB
|
|
13
|
+
instead of the control plane's 4 GiB. This prevents hung hook processes and
|
|
14
|
+
associated CPU or memory pressure on macOS, Windows, and Linux. The Windows
|
|
15
|
+
CLI heap restart also hides its child console window.
|
|
16
|
+
- **Recoverable HTTP MCP sessions** -- HTTP MCP sessions now default to a
|
|
17
|
+
12-hour idle window. An expired or unknown session receives a fast `404`
|
|
18
|
+
with a reinitialize hint instead of looking like a silent client hang. Set
|
|
19
|
+
`MEMORIX_SESSION_TIMEOUT_MS=0` only when the host owns lifecycle cleanup.
|
|
20
|
+
- **Truthful embedding diagnostics** -- the HTTP control plane exposes its
|
|
21
|
+
real runtime embedding state. `memorix doctor` reads that state instead of
|
|
22
|
+
reporting a fresh local probe as ready while the running service is degraded
|
|
23
|
+
by authorization, billing, timeout, or upstream failure.
|
|
24
|
+
- **Accurate doctor JSON health** -- a live PID with an unreachable HTTP
|
|
25
|
+
control plane now reports `healthy: false` rather than a false positive.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- **macOS release coverage** -- normal CI now runs the full build and test
|
|
29
|
+
suite on `macos-latest` in addition to Ubuntu and Windows.
|
|
30
|
+
|
|
31
|
+
## [1.6.0] - 2026-08-17
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
- **Bounded context receipts** -- `memorix context|resume --brief-json`,
|
|
35
|
+
`memorix codegraph context-pack --brief-json`, and MCP project-context
|
|
36
|
+
`format: "receipt"` return only the agent-ready brief, selection receipt,
|
|
37
|
+
CodeGraph quality, and optional Agent loadout. The detailed `--json` and
|
|
38
|
+
MCP `format: "json"` forms remain available for diagnostics.
|
|
39
|
+
- **Task-scoped Agent loadouts** -- `--agent <target>` selects only compatible
|
|
40
|
+
project workflows and reports their required context and workflow tools.
|
|
41
|
+
This is guidance, not a replacement for the host agent's authorization.
|
|
42
|
+
- **Explicit external CodeGraph lifecycle** -- `memorix codegraph init|sync`
|
|
43
|
+
manages an already installed local CodeGraph index. It never invokes
|
|
44
|
+
CodeGraph's agent installer or writes Agent configuration.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- **Honest CodeGraph status** -- Status now distinguishes the persistent Lite
|
|
48
|
+
Code State index from the provider actually usable for the current task.
|
|
49
|
+
A stale external graph falls back to Lite instead of being presented as fresh.
|
|
50
|
+
- **Bounded fallback guidance** -- Newly generated Agent rules teach
|
|
51
|
+
`--brief-json` for the one CLI fallback; `--json` is reserved for deliberate
|
|
52
|
+
detailed diagnostics.
|
|
53
|
+
|
|
7
54
|
## [1.5.1] - 2026-08-16
|
|
8
55
|
|
|
9
56
|
### Fixed
|