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.
Files changed (52) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +3 -3
  3. package/README.zh-CN.md +3 -3
  4. package/dist/cli/index.js +558 -102
  5. package/dist/cli/memcode.js +12 -1
  6. package/dist/index.js +221 -27
  7. package/dist/maintenance-runner.js +59 -11
  8. package/dist/media-audio-runner.js +59 -11
  9. package/dist/media-video-runner.js +59 -11
  10. package/dist/memcode-runtime/CHANGELOG.md +47 -0
  11. package/dist/sdk.js +220 -26
  12. package/dist/vector-backfill-runner.js +59 -11
  13. package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
  14. package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
  15. package/docs/API_REFERENCE.md +2 -2
  16. package/docs/DEVELOPMENT.md +5 -3
  17. package/docs/DOCKER.md +5 -1
  18. package/docs/PERFORMANCE.md +2 -2
  19. package/docs/README.md +3 -1
  20. package/docs/SETUP.md +8 -2
  21. package/package.json +1 -1
  22. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  23. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  24. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  25. package/plugins/copilot/memorix/plugin.json +1 -1
  26. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  27. package/plugins/omp/memorix/package.json +1 -1
  28. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  29. package/plugins/pi/memorix/package.json +1 -1
  30. package/server.json +2 -2
  31. package/src/cli/commands/agent-integrations.ts +9 -3
  32. package/src/cli/commands/codegraph.ts +48 -5
  33. package/src/cli/commands/context.ts +20 -4
  34. package/src/cli/commands/doctor.ts +46 -15
  35. package/src/cli/commands/hook.ts +13 -1
  36. package/src/cli/commands/resume.ts +4 -0
  37. package/src/cli/commands/serve-http.ts +68 -7
  38. package/src/cli/heap.ts +76 -0
  39. package/src/cli/invocation.ts +7 -4
  40. package/src/codegraph/auto-context.ts +4 -1
  41. package/src/codegraph/context-pack.ts +3 -1
  42. package/src/codegraph/external-provider.ts +93 -0
  43. package/src/embedding/provider.ts +76 -6
  44. package/src/hooks/handler.ts +9 -18
  45. package/src/hooks/installers/index.ts +1 -1
  46. package/src/hooks/lifecycle.ts +173 -0
  47. package/src/hooks/official-skills.ts +3 -3
  48. package/src/hooks/rules/memorix-agent-rules.md +1 -1
  49. package/src/knowledge/context-receipt.ts +41 -0
  50. package/src/knowledge/workflows.ts +6 -3
  51. package/src/knowledge/workset.ts +56 -2
  52. 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 temporarily unavailable at runtime: ${message}`);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(localFallback);
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) => !KNOWN_AGENTS.includes(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 KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
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
- KNOWN_AGENTS = [
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 temporarily unavailable at runtime: ${message}`);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(localFallback);
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) => !KNOWN_AGENTS.includes(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 KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
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
- KNOWN_AGENTS = [
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 temporarily unavailable at runtime: ${message}`);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(initialized);
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 = wrapProvider(localFallback);
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) => !KNOWN_AGENTS.includes(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 KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
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
- KNOWN_AGENTS = [
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