memorix 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/CLAUDE.md +9 -9
  3. package/README.md +7 -2
  4. package/README.zh-CN.md +6 -2
  5. package/dist/cli/index.js +1216 -485
  6. package/dist/index.js +984 -337
  7. package/dist/maintenance-runner.js +564 -180
  8. package/dist/media-video-runner.js +564 -180
  9. package/dist/memcode/index.js +53 -21
  10. package/dist/memcode-runtime/CHANGELOG.md +31 -0
  11. package/dist/sdk.js +983 -336
  12. package/dist/vector-backfill-runner.js +564 -180
  13. package/docs/1.4.2-EVIDENCE-GOVERNED-MEMORY-SPEC.md +434 -0
  14. package/docs/API_REFERENCE.md +1 -1
  15. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +52 -128
  16. package/package.json +5 -2
  17. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  18. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  19. package/plugins/copilot/memorix/plugin.json +1 -1
  20. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  21. package/plugins/omp/memorix/package.json +1 -1
  22. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  23. package/plugins/pi/memorix/package.json +1 -1
  24. package/server.json +2 -2
  25. package/src/cli/commands/codegraph.ts +83 -2
  26. package/src/codegraph/auto-context.ts +20 -0
  27. package/src/codegraph/current-facts.ts +1 -0
  28. package/src/codegraph/external-provider.ts +1 -0
  29. package/src/codegraph/store.ts +216 -5
  30. package/src/codegraph/types.ts +42 -0
  31. package/src/knowledge/context-assembly.ts +25 -0
  32. package/src/knowledge/governor.ts +156 -0
  33. package/src/knowledge/outcome-store.ts +102 -0
  34. package/src/knowledge/outcome-types.ts +49 -0
  35. package/src/knowledge/workflows.ts +32 -1
  36. package/src/knowledge/workset.ts +203 -13
  37. package/src/store/sqlite-db.ts +42 -0
  38. package/docs/dev-log/progress.txt +0 -388
@@ -74127,7 +74127,7 @@ var init_models_generated = __esm({
74127
74127
  provider: "minimax",
74128
74128
  baseUrl: "https://api.minimax.io/anthropic",
74129
74129
  reasoning: true,
74130
- input: ["text", "image"],
74130
+ input: ["text", "image", "video"],
74131
74131
  cost: {
74132
74132
  input: 0.3,
74133
74133
  output: 1.2,
@@ -74180,7 +74180,7 @@ var init_models_generated = __esm({
74180
74180
  provider: "minimax-cn",
74181
74181
  baseUrl: "https://api.minimaxi.com/anthropic",
74182
74182
  reasoning: true,
74183
- input: ["text", "image"],
74183
+ input: ["text", "image", "video"],
74184
74184
  cost: {
74185
74185
  input: 0.3,
74186
74186
  output: 1.2,
@@ -93464,11 +93464,11 @@ var init_simple_options = __esm({
93464
93464
  });
93465
93465
 
93466
93466
  // packages/ai/dist/providers/transform-messages.js
93467
- function replaceImagesWithPlaceholder(content, placeholder) {
93467
+ function replaceMediaWithPlaceholder(content, dropType, placeholder) {
93468
93468
  const result = [];
93469
93469
  let previousWasPlaceholder = false;
93470
93470
  for (const block2 of content) {
93471
- if (block2.type === "image") {
93471
+ if (block2.type === dropType) {
93472
93472
  if (!previousWasPlaceholder) {
93473
93473
  result.push({ type: "text", text: placeholder });
93474
93474
  }
@@ -93476,33 +93476,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
93476
93476
  continue;
93477
93477
  }
93478
93478
  result.push(block2);
93479
- previousWasPlaceholder = block2.text === placeholder;
93479
+ previousWasPlaceholder = block2.type === "text" && block2.text === placeholder;
93480
93480
  }
93481
93481
  return result;
93482
93482
  }
93483
- function downgradeUnsupportedImages(messages, model) {
93484
- if (model.input.includes("image")) {
93483
+ function downgradeUnsupportedMedia(messages, model) {
93484
+ const supportsImage = model.input.includes("image");
93485
+ const supportsVideo = model.input.includes("video");
93486
+ if (supportsImage && supportsVideo) {
93485
93487
  return messages;
93486
93488
  }
93487
93489
  return messages.map((msg) => {
93488
93490
  if (msg.role === "user" && Array.isArray(msg.content)) {
93489
- return {
93490
- ...msg,
93491
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
93492
- };
93491
+ let content = msg.content;
93492
+ if (!supportsImage)
93493
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
93494
+ if (!supportsVideo)
93495
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
93496
+ return { ...msg, content };
93493
93497
  }
93494
93498
  if (msg.role === "toolResult") {
93495
- return {
93496
- ...msg,
93497
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
93498
- };
93499
+ let content = msg.content;
93500
+ if (!supportsImage)
93501
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
93502
+ if (!supportsVideo)
93503
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
93504
+ return { ...msg, content };
93499
93505
  }
93500
93506
  return msg;
93501
93507
  });
93502
93508
  }
93503
93509
  function transformMessages(messages, model, normalizeToolCallId2) {
93504
93510
  const toolCallIdMap = /* @__PURE__ */ new Map();
93505
- const imageAwareMessages = downgradeUnsupportedImages(messages, model);
93511
+ const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
93506
93512
  const transformed = imageAwareMessages.map((msg) => {
93507
93513
  if (msg.role === "user") {
93508
93514
  return msg;
@@ -93614,13 +93620,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
93614
93620
  insertSyntheticToolResults();
93615
93621
  return result;
93616
93622
  }
93617
- var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
93623
+ var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
93618
93624
  var init_transform_messages = __esm({
93619
93625
  "packages/ai/dist/providers/transform-messages.js"() {
93620
93626
  "use strict";
93621
93627
  init_esm_shims();
93622
93628
  NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
93623
93629
  NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
93630
+ NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
93631
+ NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
93624
93632
  }
93625
93633
  });
93626
93634
 
@@ -93651,8 +93659,8 @@ function getCacheControl(model, cacheRetention) {
93651
93659
  };
93652
93660
  }
93653
93661
  function convertContentBlocks(content) {
93654
- const hasImages = content.some((c) => c.type === "image");
93655
- if (!hasImages) {
93662
+ const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
93663
+ if (!hasMedia) {
93656
93664
  return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
93657
93665
  }
93658
93666
  const blocks = content.map((block2) => {
@@ -93662,6 +93670,16 @@ function convertContentBlocks(content) {
93662
93670
  text: sanitizeSurrogates(block2.text)
93663
93671
  };
93664
93672
  }
93673
+ if (block2.type === "video") {
93674
+ return {
93675
+ type: "video",
93676
+ source: {
93677
+ type: "base64",
93678
+ media_type: block2.mimeType,
93679
+ data: block2.data
93680
+ }
93681
+ };
93682
+ }
93665
93683
  return {
93666
93684
  type: "image",
93667
93685
  source: {
@@ -93675,7 +93693,7 @@ function convertContentBlocks(content) {
93675
93693
  if (!hasText) {
93676
93694
  blocks.unshift({
93677
93695
  type: "text",
93678
- text: "(see attached image)"
93696
+ text: "(see attached media)"
93679
93697
  });
93680
93698
  }
93681
93699
  return blocks;
@@ -94025,6 +94043,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
94025
94043
  type: "text",
94026
94044
  text: sanitizeSurrogates(item.text)
94027
94045
  };
94046
+ } else if (item.type === "video") {
94047
+ return {
94048
+ type: "video",
94049
+ source: {
94050
+ type: "base64",
94051
+ media_type: item.mimeType,
94052
+ data: item.data
94053
+ }
94054
+ };
94028
94055
  } else {
94029
94056
  return {
94030
94057
  type: "image",
@@ -94105,6 +94132,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
94105
94132
  toolResults.push({
94106
94133
  type: "tool_result",
94107
94134
  tool_use_id: msg.toolCallId,
94135
+ // MiniMax's Anthropic-compatible API accepts video in tool results;
94136
+ // the SDK's ToolResultBlockParam.content type predates video support.
94108
94137
  content: convertContentBlocks(msg.content),
94109
94138
  is_error: msg.isError
94110
94139
  });
@@ -94131,7 +94160,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
94131
94160
  if (lastMessage.role === "user") {
94132
94161
  if (Array.isArray(lastMessage.content)) {
94133
94162
  const lastBlock = lastMessage.content[lastMessage.content.length - 1];
94134
- if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
94163
+ if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
94135
94164
  lastBlock.cache_control = cacheControl;
94136
94165
  }
94137
94166
  } else if (typeof lastMessage.content === "string") {
@@ -233195,6 +233224,9 @@ function contentToText(content) {
233195
233224
  if (block2.type === "text") {
233196
233225
  return block2.text;
233197
233226
  }
233227
+ if (block2.type === "video") {
233228
+ return `[video:${block2.mimeType}:${block2.data.length}]`;
233229
+ }
233198
233230
  return `[image:${block2.mimeType}:${block2.data.length}]`;
233199
233231
  }).join("\n");
233200
233232
  }
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.2] - 2026-08-06
6
+
7
+ ### Added
8
+ - **Evidence-governed memory** -- A deterministic governor now decides whether
9
+ project knowledge should be included, compacted, deferred, or excluded based
10
+ on source backing, freshness, conflicts, quality, scope, and token budget.
11
+ - **Outcome-aware memory** -- Workflow verification results are recorded as
12
+ append-only outcome signals so failed evidence is less likely to be reused
13
+ as trusted project knowledge.
14
+ - **CodeGraph evolution views** -- Lite CodeGraph now keeps hash-only snapshot
15
+ manifests, reports exact file-level diffs, and exposes bounded one-hop impact
16
+ slices through the CLI. Continuation worksets include code evolution and
17
+ stale-memory binding counts.
18
+
19
+ ### Fixed
20
+ - **Star History automation** -- The chart workflow now updates a dedicated
21
+ branch and opens or refreshes a pull request instead of trying to push
22
+ directly to protected `main`, which caused every scheduled refresh to fail.
23
+
24
+ ## [1.4.1] - 2026-08-03
25
+
26
+ ### Added
27
+ - **MiniMax M3 video input** -- The bundled `@memorix/ai` provider layer now advertises and routes MiniMax M3 video content through MiniMax's Anthropic-compatible API. Base64 video is covered by focused request-shape tests, and image-only models still receive a clear text fallback instead of an invalid video block. Contributed by [@octo-patch](https://github.com/octo-patch) in #153.
28
+
29
+ ### Changed
30
+ - **Maintained product roadmap** -- Replaced the stale version-by-version roadmap with current product boundaries, operating constraints, and public directions. Release facts now live in this changelog and active maintainer work lives in `ACTIVE_WORK.md`. Contributed by [@FBISiri](https://github.com/FBISiri) in #140.
31
+
32
+ ### Fixed
33
+ - **Deterministic provider tests** -- `@memorix/ai` unit tests no longer discover local API keys or Pi OAuth credentials and unexpectedly call paid, changing provider endpoints. Routine tests are offline by default; deliberate live validation requires `MEMORIX_AI_LIVE_TESTS=1` plus the required credentials.
34
+ - **Stable model metadata assertion** -- Removed a test-only assumption that OpenRouter will permanently list `moonshotai/kimi-k2.6:free`; the bundled catalog snapshot no longer contains that route, while coverage remains for the supported Kimi K2.6 compatibility metadata.
35
+
5
36
  ## [1.4.0] - 2026-08-02
6
37
 
7
38
  ### Changed