memorix 1.3.4 → 1.4.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/dist/sdk.js CHANGED
@@ -32934,7 +32934,7 @@ var init_models_generated = __esm({
32934
32934
  provider: "minimax",
32935
32935
  baseUrl: "https://api.minimax.io/anthropic",
32936
32936
  reasoning: true,
32937
- input: ["text", "image"],
32937
+ input: ["text", "image", "video"],
32938
32938
  cost: {
32939
32939
  input: 0.3,
32940
32940
  output: 1.2,
@@ -32987,7 +32987,7 @@ var init_models_generated = __esm({
32987
32987
  provider: "minimax-cn",
32988
32988
  baseUrl: "https://api.minimaxi.com/anthropic",
32989
32989
  reasoning: true,
32990
- input: ["text", "image"],
32990
+ input: ["text", "image", "video"],
32991
32991
  cost: {
32992
32992
  input: 0.3,
32993
32993
  output: 1.2,
@@ -52262,11 +52262,11 @@ var init_simple_options = __esm({
52262
52262
  });
52263
52263
 
52264
52264
  // packages/ai/dist/providers/transform-messages.js
52265
- function replaceImagesWithPlaceholder(content, placeholder) {
52265
+ function replaceMediaWithPlaceholder(content, dropType, placeholder) {
52266
52266
  const result = [];
52267
52267
  let previousWasPlaceholder = false;
52268
52268
  for (const block of content) {
52269
- if (block.type === "image") {
52269
+ if (block.type === dropType) {
52270
52270
  if (!previousWasPlaceholder) {
52271
52271
  result.push({ type: "text", text: placeholder });
52272
52272
  }
@@ -52274,33 +52274,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
52274
52274
  continue;
52275
52275
  }
52276
52276
  result.push(block);
52277
- previousWasPlaceholder = block.text === placeholder;
52277
+ previousWasPlaceholder = block.type === "text" && block.text === placeholder;
52278
52278
  }
52279
52279
  return result;
52280
52280
  }
52281
- function downgradeUnsupportedImages(messages, model) {
52282
- if (model.input.includes("image")) {
52281
+ function downgradeUnsupportedMedia(messages, model) {
52282
+ const supportsImage = model.input.includes("image");
52283
+ const supportsVideo = model.input.includes("video");
52284
+ if (supportsImage && supportsVideo) {
52283
52285
  return messages;
52284
52286
  }
52285
52287
  return messages.map((msg) => {
52286
52288
  if (msg.role === "user" && Array.isArray(msg.content)) {
52287
- return {
52288
- ...msg,
52289
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
52290
- };
52289
+ let content = msg.content;
52290
+ if (!supportsImage)
52291
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
52292
+ if (!supportsVideo)
52293
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
52294
+ return { ...msg, content };
52291
52295
  }
52292
52296
  if (msg.role === "toolResult") {
52293
- return {
52294
- ...msg,
52295
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
52296
- };
52297
+ let content = msg.content;
52298
+ if (!supportsImage)
52299
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
52300
+ if (!supportsVideo)
52301
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
52302
+ return { ...msg, content };
52297
52303
  }
52298
52304
  return msg;
52299
52305
  });
52300
52306
  }
52301
52307
  function transformMessages(messages, model, normalizeToolCallId2) {
52302
52308
  const toolCallIdMap = /* @__PURE__ */ new Map();
52303
- const imageAwareMessages = downgradeUnsupportedImages(messages, model);
52309
+ const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
52304
52310
  const transformed = imageAwareMessages.map((msg) => {
52305
52311
  if (msg.role === "user") {
52306
52312
  return msg;
@@ -52412,13 +52418,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
52412
52418
  insertSyntheticToolResults();
52413
52419
  return result;
52414
52420
  }
52415
- var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
52421
+ var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
52416
52422
  var init_transform_messages = __esm({
52417
52423
  "packages/ai/dist/providers/transform-messages.js"() {
52418
52424
  "use strict";
52419
52425
  init_esm_shims();
52420
52426
  NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
52421
52427
  NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
52428
+ NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
52429
+ NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
52422
52430
  }
52423
52431
  });
52424
52432
 
@@ -52449,8 +52457,8 @@ function getCacheControl(model, cacheRetention) {
52449
52457
  };
52450
52458
  }
52451
52459
  function convertContentBlocks(content) {
52452
- const hasImages = content.some((c) => c.type === "image");
52453
- if (!hasImages) {
52460
+ const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
52461
+ if (!hasMedia) {
52454
52462
  return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
52455
52463
  }
52456
52464
  const blocks = content.map((block) => {
@@ -52460,6 +52468,16 @@ function convertContentBlocks(content) {
52460
52468
  text: sanitizeSurrogates(block.text)
52461
52469
  };
52462
52470
  }
52471
+ if (block.type === "video") {
52472
+ return {
52473
+ type: "video",
52474
+ source: {
52475
+ type: "base64",
52476
+ media_type: block.mimeType,
52477
+ data: block.data
52478
+ }
52479
+ };
52480
+ }
52463
52481
  return {
52464
52482
  type: "image",
52465
52483
  source: {
@@ -52473,7 +52491,7 @@ function convertContentBlocks(content) {
52473
52491
  if (!hasText) {
52474
52492
  blocks.unshift({
52475
52493
  type: "text",
52476
- text: "(see attached image)"
52494
+ text: "(see attached media)"
52477
52495
  });
52478
52496
  }
52479
52497
  return blocks;
@@ -52823,6 +52841,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
52823
52841
  type: "text",
52824
52842
  text: sanitizeSurrogates(item.text)
52825
52843
  };
52844
+ } else if (item.type === "video") {
52845
+ return {
52846
+ type: "video",
52847
+ source: {
52848
+ type: "base64",
52849
+ media_type: item.mimeType,
52850
+ data: item.data
52851
+ }
52852
+ };
52826
52853
  } else {
52827
52854
  return {
52828
52855
  type: "image",
@@ -52903,6 +52930,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
52903
52930
  toolResults.push({
52904
52931
  type: "tool_result",
52905
52932
  tool_use_id: msg.toolCallId,
52933
+ // MiniMax's Anthropic-compatible API accepts video in tool results;
52934
+ // the SDK's ToolResultBlockParam.content type predates video support.
52906
52935
  content: convertContentBlocks(msg.content),
52907
52936
  is_error: msg.isError
52908
52937
  });
@@ -52929,7 +52958,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
52929
52958
  if (lastMessage.role === "user") {
52930
52959
  if (Array.isArray(lastMessage.content)) {
52931
52960
  const lastBlock = lastMessage.content[lastMessage.content.length - 1];
52932
- if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
52961
+ if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
52933
52962
  lastBlock.cache_control = cacheControl;
52934
52963
  }
52935
52964
  } else if (typeof lastMessage.content === "string") {
@@ -152679,6 +152708,7 @@ function compareDateStrings(a, b) {
152679
152708
  }
152680
152709
  function detectStaleProgressNotes(input) {
152681
152710
  const candidates = [
152711
+ "ACTIVE_WORK.md",
152682
152712
  "progress.txt",
152683
152713
  "docs/dev-log/progress.txt",
152684
152714
  "docs/memcode/dev-log/progress.txt"
@@ -164129,7 +164159,7 @@ The path should point to a directory containing a .git folder.`
164129
164159
  };
164130
164160
  const server = existingServer ?? new McpServer({
164131
164161
  name: "memorix",
164132
- version: true ? "1.3.4" : "1.0.1"
164162
+ version: true ? "1.4.1" : "1.0.1"
164133
164163
  });
164134
164164
  const originalRegisterTool = server.registerTool.bind(server);
164135
164165
  server.registerTool = ((name, ...args) => {
@@ -33079,7 +33079,7 @@ var init_models_generated = __esm({
33079
33079
  provider: "minimax",
33080
33080
  baseUrl: "https://api.minimax.io/anthropic",
33081
33081
  reasoning: true,
33082
- input: ["text", "image"],
33082
+ input: ["text", "image", "video"],
33083
33083
  cost: {
33084
33084
  input: 0.3,
33085
33085
  output: 1.2,
@@ -33132,7 +33132,7 @@ var init_models_generated = __esm({
33132
33132
  provider: "minimax-cn",
33133
33133
  baseUrl: "https://api.minimaxi.com/anthropic",
33134
33134
  reasoning: true,
33135
- input: ["text", "image"],
33135
+ input: ["text", "image", "video"],
33136
33136
  cost: {
33137
33137
  input: 0.3,
33138
33138
  output: 1.2,
@@ -52407,11 +52407,11 @@ var init_simple_options = __esm({
52407
52407
  });
52408
52408
 
52409
52409
  // packages/ai/dist/providers/transform-messages.js
52410
- function replaceImagesWithPlaceholder(content, placeholder) {
52410
+ function replaceMediaWithPlaceholder(content, dropType, placeholder) {
52411
52411
  const result = [];
52412
52412
  let previousWasPlaceholder = false;
52413
52413
  for (const block of content) {
52414
- if (block.type === "image") {
52414
+ if (block.type === dropType) {
52415
52415
  if (!previousWasPlaceholder) {
52416
52416
  result.push({ type: "text", text: placeholder });
52417
52417
  }
@@ -52419,33 +52419,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
52419
52419
  continue;
52420
52420
  }
52421
52421
  result.push(block);
52422
- previousWasPlaceholder = block.text === placeholder;
52422
+ previousWasPlaceholder = block.type === "text" && block.text === placeholder;
52423
52423
  }
52424
52424
  return result;
52425
52425
  }
52426
- function downgradeUnsupportedImages(messages, model) {
52427
- if (model.input.includes("image")) {
52426
+ function downgradeUnsupportedMedia(messages, model) {
52427
+ const supportsImage = model.input.includes("image");
52428
+ const supportsVideo = model.input.includes("video");
52429
+ if (supportsImage && supportsVideo) {
52428
52430
  return messages;
52429
52431
  }
52430
52432
  return messages.map((msg) => {
52431
52433
  if (msg.role === "user" && Array.isArray(msg.content)) {
52432
- return {
52433
- ...msg,
52434
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
52435
- };
52434
+ let content = msg.content;
52435
+ if (!supportsImage)
52436
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
52437
+ if (!supportsVideo)
52438
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
52439
+ return { ...msg, content };
52436
52440
  }
52437
52441
  if (msg.role === "toolResult") {
52438
- return {
52439
- ...msg,
52440
- content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
52441
- };
52442
+ let content = msg.content;
52443
+ if (!supportsImage)
52444
+ content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
52445
+ if (!supportsVideo)
52446
+ content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
52447
+ return { ...msg, content };
52442
52448
  }
52443
52449
  return msg;
52444
52450
  });
52445
52451
  }
52446
52452
  function transformMessages(messages, model, normalizeToolCallId2) {
52447
52453
  const toolCallIdMap = /* @__PURE__ */ new Map();
52448
- const imageAwareMessages = downgradeUnsupportedImages(messages, model);
52454
+ const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
52449
52455
  const transformed = imageAwareMessages.map((msg) => {
52450
52456
  if (msg.role === "user") {
52451
52457
  return msg;
@@ -52557,13 +52563,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
52557
52563
  insertSyntheticToolResults();
52558
52564
  return result;
52559
52565
  }
52560
- var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
52566
+ var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
52561
52567
  var init_transform_messages = __esm({
52562
52568
  "packages/ai/dist/providers/transform-messages.js"() {
52563
52569
  "use strict";
52564
52570
  init_esm_shims();
52565
52571
  NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
52566
52572
  NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
52573
+ NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
52574
+ NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
52567
52575
  }
52568
52576
  });
52569
52577
 
@@ -52594,8 +52602,8 @@ function getCacheControl(model, cacheRetention) {
52594
52602
  };
52595
52603
  }
52596
52604
  function convertContentBlocks(content) {
52597
- const hasImages = content.some((c) => c.type === "image");
52598
- if (!hasImages) {
52605
+ const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
52606
+ if (!hasMedia) {
52599
52607
  return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
52600
52608
  }
52601
52609
  const blocks = content.map((block) => {
@@ -52605,6 +52613,16 @@ function convertContentBlocks(content) {
52605
52613
  text: sanitizeSurrogates(block.text)
52606
52614
  };
52607
52615
  }
52616
+ if (block.type === "video") {
52617
+ return {
52618
+ type: "video",
52619
+ source: {
52620
+ type: "base64",
52621
+ media_type: block.mimeType,
52622
+ data: block.data
52623
+ }
52624
+ };
52625
+ }
52608
52626
  return {
52609
52627
  type: "image",
52610
52628
  source: {
@@ -52618,7 +52636,7 @@ function convertContentBlocks(content) {
52618
52636
  if (!hasText) {
52619
52637
  blocks.unshift({
52620
52638
  type: "text",
52621
- text: "(see attached image)"
52639
+ text: "(see attached media)"
52622
52640
  });
52623
52641
  }
52624
52642
  return blocks;
@@ -52968,6 +52986,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
52968
52986
  type: "text",
52969
52987
  text: sanitizeSurrogates(item.text)
52970
52988
  };
52989
+ } else if (item.type === "video") {
52990
+ return {
52991
+ type: "video",
52992
+ source: {
52993
+ type: "base64",
52994
+ media_type: item.mimeType,
52995
+ data: item.data
52996
+ }
52997
+ };
52971
52998
  } else {
52972
52999
  return {
52973
53000
  type: "image",
@@ -53048,6 +53075,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
53048
53075
  toolResults.push({
53049
53076
  type: "tool_result",
53050
53077
  tool_use_id: msg.toolCallId,
53078
+ // MiniMax's Anthropic-compatible API accepts video in tool results;
53079
+ // the SDK's ToolResultBlockParam.content type predates video support.
53051
53080
  content: convertContentBlocks(msg.content),
53052
53081
  is_error: msg.isError
53053
53082
  });
@@ -53074,7 +53103,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
53074
53103
  if (lastMessage.role === "user") {
53075
53104
  if (Array.isArray(lastMessage.content)) {
53076
53105
  const lastBlock = lastMessage.content[lastMessage.content.length - 1];
53077
- if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
53106
+ if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
53078
53107
  lastBlock.cache_control = cacheControl;
53079
53108
  }
53080
53109
  } else if (typeof lastMessage.content === "string") {
@@ -318,20 +318,20 @@ then document the 2026-07-28 migration boundary.
318
318
  - no personal Codex/Claude/OpenCode configuration mutation;
319
319
  - documentation and changelog reviewed.
320
320
 
321
- ### Phase G: 1.3.4 hardening
321
+ ### Phase G: 1.3.4 hardening (completed 2026-08-02)
322
322
 
323
- 1.3.4 is not a feature release. It exercises fresh install, Windows CLI
324
- windows-hide behavior, CLI/stdio/HTTP MCP routes, cancellation/restart of media
325
- jobs, quota cleanup, failure messages, and agent-facing UX. Only defects found
326
- through that work are fixed.
323
+ 1.3.4 exercised fresh install, Windows CLI windows-hide behavior,
324
+ CLI/stdio/HTTP MCP routes, cancellation/restart of media jobs, quota cleanup,
325
+ failure messages, and agent-facing UX. The resulting fixes are published in
326
+ the 1.3.4 release notes and passed Windows and Ubuntu CI.
327
327
 
328
- ### Phase H: 1.4 stable release
328
+ ### Phase H: 1.4 stable release (completed 2026-08-02)
329
329
 
330
- 1.4 is cut only when 1.3.3 and 1.3.4 gates are green, all supported paths have
331
- packaged CLI evidence, the compatibility matrix is updated, and there is no
332
- known high-severity data-loss, credential-retention, Windows-popup, or MCP
333
- binding regression. “No bug” means no known release blocker after these tests,
334
- not an impossible claim of mathematical perfection.
330
+ 1.4.0 was cut after the 1.3.3 and 1.3.4 gates were green, supported paths had
331
+ packaged CLI evidence, and no high-severity data-loss, credential-retention,
332
+ Windows-popup, or MCP binding regression was known. “Stable” means no known
333
+ release blocker after these tests, not an impossible claim of mathematical
334
+ perfection.
335
335
 
336
336
  ## Acceptance criteria
337
337
 
@@ -351,8 +351,8 @@ not an impossible claim of mathematical perfection.
351
351
  8. No generated asset enters project memory without an explicit attach action.
352
352
  9. The same media action works through CLI and MCP using an explicit resolved
353
353
  project binding, independent of a legacy HTTP session identifier.
354
- 10. 1.3.4 regression tests cover Windows, fresh package install, CLI, stdio,
355
- HTTP MCP, quota cleanup, and error UX before 1.4 is published.
354
+ 10. 1.3.4 regression tests covered Windows, fresh package install, CLI, stdio,
355
+ HTTP MCP, quota cleanup, and error UX before 1.4.0 was published.
356
356
 
357
357
  ## Research and implementation basis
358
358
 
@@ -114,7 +114,7 @@ MCP:
114
114
  - `memorix_codegraph_status` returns provider/index counts for the current project.
115
115
  - `memorix_context_pack` builds a task-specific packet with reliable current memories, lower-trust unbound memories, current code facts, freshness warnings, suggested reads, and suggested verification.
116
116
 
117
- `memorix context` defaults to `--refresh auto`, so first use can seed Code State without a separate manual `memorix codegraph refresh`. Its brief puts live package/changelog/Git facts before memory hints and flags old `progress.txt` / dev-log notes as historical when they predate the latest changelog, so agents should treat current facts as the source of truth when files disagree. Task lenses keep the packet shaped to the work: bugfix briefs prefer failing tests and repros, release briefs prefer metadata/changelog/package checks, and onboarding briefs prefer docs and entry points while hiding unrelated suspect details. Continuation delivery is separate from the task lens: continuation language in `memorix_project_context` enables a bounded prior-work projection, and `memorix resume "..."` makes that choice explicit. It includes only the latest useful session summary, up to three readable durable memories, and at most one recent source-labelled compact checkpoint. Checkpoints are host lifecycle evidence, not durable memory or transcript backups; ordinary new tasks do not receive historical-session context. A completed MCP brief is the default retrieval boundary: search, detail, or Context Pack should expand it only for a named missing fact or an explicit request for deeper history. Use `--refresh never` for read-only inspection and `--refresh always` when you want to force a fresh scan.
117
+ `memorix context` defaults to `--refresh auto`, so first use can seed Code State without a separate manual `memorix codegraph refresh`. Its brief puts live package/changelog/Git facts before memory hints and flags an old `ACTIVE_WORK.md`, legacy `progress.txt`, or legacy dev-log note as historical when it predates the latest changelog, so agents should treat current facts as the source of truth when files disagree. Task lenses keep the packet shaped to the work: bugfix briefs prefer failing tests and repros, release briefs prefer metadata/changelog/package checks, and onboarding briefs prefer docs and entry points while hiding unrelated suspect details. Continuation delivery is separate from the task lens: continuation language in `memorix_project_context` enables a bounded prior-work projection, and `memorix resume "..."` makes that choice explicit. It includes only the latest useful session summary, up to three readable durable memories, and at most one recent source-labelled compact checkpoint. Checkpoints are host lifecycle evidence, not durable memory or transcript backups; ordinary new tasks do not receive historical-session context. A completed MCP brief is the default retrieval boundary: search, detail, or Context Pack should expand it only for a named missing fact or an explicit request for deeper history. Use `--refresh never` for read-only inspection and `--refresh always` when you want to force a fresh scan.
118
118
 
119
119
  Project-specific generated, vendored, or cache paths can be excluded from Code State with `[codegraph].exclude_patterns` in `memorix.toml` or `~/.memorix/config.toml` (`codegraph.excludePatterns` in legacy YAML). User patterns extend the built-in excludes and are applied to indexing, Project Context suggested reads, and Context Pack suggested reads.
120
120
 
@@ -1,149 +1,73 @@
1
- # Memorix 已知问题 & 未来路线图
1
+ # Memorix 已知边界与路线图
2
2
 
3
- > 最后更新: 2026-03-09 (v1.0.0)
3
+ > 最后审阅:2026-08-03(对照 v1.4.0)
4
4
 
5
- ---
5
+ 这份文档说明仍然成立的产品边界、风险和方向;它不是发布流水账。
6
6
 
7
- ## 已知问题 & 限制
7
+ - 已发布版本和每次修复的事实,以 [CHANGELOG](../CHANGELOG.md) 为准。
8
+ - 当前正在进行的维护工作,以 [ACTIVE_WORK](../ACTIVE_WORK.md) 为准。
9
+ - 可讨论、可订阅的后续事项,以 GitHub Open Issues 为准。
8
10
 
9
- ### 🔴 严重
11
+ ---
10
12
 
11
- | # | 问题 | 影响 | 状态 |
12
- |---|------|------|------|
13
- | 1 | ~~**无文件锁**~~ — 多 Agent 同时写入 | 数据完整性 | ✅ v0.7.11 (`withFileLock` + `atomicWriteFile`) |
14
- | 2 | **Orama where 过滤不可靠** — 空 term + number filter 时结果可能不正确 | `compactDetail` 已绕过 (使用内存查找) | 已变通 |
13
+ ## 当前产品边界
15
14
 
16
- ### 🟡 中等
15
+ Memorix 是本地优先、可插拔的 Agent Memory 系统。它给不同 Agent 或同一 Agent 的新会话提供同一个项目记忆层,并把 CLI 作为最完整、最稳定的控制面;MCP 是面向 Agent 的受控入口,而不是唯一入口。
17
16
 
18
- | # | 问题 | 影响 | 状态 |
19
- |---|------|------|------|
20
- | 3 | **非 Git 项目的 projectId 不稳定** — 基于目录名,不同机器或路径会不同 | 数据隔离 | 未修复 |
21
- | 4 | ~~**retention 只有报告没有执行**~~ | 数据膨胀 | ✅ v0.7.11 (`archiveExpired` + `action="archive"`) |
22
- | 5 | ~~**实体抽取不支持中文标识符**~~ | 中文项目覆盖不足 | ✅ v0.7.11 (中文括号/反引号 + 因果语言) |
23
- | 6 | ~~**auto-relations 每次读取全图**~~ | 性能 | ✅ v0.7.11 (entityIndex O(1) 查找) |
24
- | 7 | **高重要性 observations 永远免疫** — gotcha/decision/trade-off 永不过期 | 数据膨胀 | 设计如此,需评估 |
17
+ 当前版本已经包括:
25
18
 
26
- ### 🟢 轻微
19
+ - 项目记忆、会话续接、任务透镜和按需展开的上下文;
20
+ - 代码状态、知识库 / Wiki、知识图谱投影和工作流记录;
21
+ - 受控的本地媒体资产库,可显式导入图片、音频、视频和 PDF,并保留来源、哈希、配额和删除审计;
22
+ - 多 Agent 集成、hook、doctor / repair,以及可选择的后台维护;
23
+ - SQLite 规范存储、可见性边界、保留策略和清理审计。
27
24
 
28
- | # | 问题 | 影响 | 状态 |
29
- |---|------|------|------|
30
- | 8 | ~~**Kiro/Trae Agent hooks 未实现**~~ | 功能缺失 | ✅ v0.9.12+ (Kiro/Trae/OpenCode/Gemini CLI 全部支持) |
31
- | 9 | **fastembed 首次使用需下载模型** — ~30MB,可能在网络不好时超时 | 用户体验 | 需用户显式安装 |
32
- | 10 | **npx 缓存可能损坏** — 见 `MODULE_NOT_FOUND chownr` 问题 | 安装体验 | 需文档说明 |
25
+ 这些能力并不等于“任何数据都会被自动收集”或“所有媒体都已经被模型理解”。Memorix 的默认边界是显式、可追溯、可清理,避免把无关聊天、任意本地文件或有成本的模型调用悄悄写入长期记忆。
33
26
 
34
27
  ---
35
28
 
36
- ## 未来路线图
37
-
38
- ### Phase 1: 稳定化 ✅
39
- - [x] Copilot Adapter 实现
40
- - [x] Antigravity Adapter 实现
41
- - [x] MCP Server 集成验证
42
- - [x] 753 测试通过 (v1.0.0)
43
- - [x] 开发文档编写
44
- - [x] README 优化 (中英双语, Antigravity 配置指南)
45
- - [x] npm 发布配置优化
46
-
47
- ### Phase 2: 推广 & 用户获取
48
- - [ ] 社区推广 (Reddit, HN, X, Discord)
49
- - [ ] 技术博客文章
50
- - [ ] 演示视频
51
- - [ ] 与其他 MCP Server 项目的对比文档
52
-
53
- ### Phase 3: Web Dashboard ✅
54
- - [x] 知识图谱可视化 (D3.js force graph)
55
- - [x] Observation 搜索/浏览 Web UI
56
- - [x] 记忆保留状态仪表板
57
- - [x] 跨项目记忆概览 (project switcher)
58
-
59
- ### Phase 4: 功能增强 ✅
60
- - [x] 自动归档过期记忆 (`memorix_retention action="archive"`)
61
- - [x] 文件锁机制 (多进程安全)
62
- - [x] 搜索精确度优化 (fuzzy + field boosting)
63
- - [x] 中文实体抽取
64
- - [x] 图谱-记忆双向同步
65
- - [x] `memorix_transfer` — 导出/导入记忆 (JSON + Markdown)
66
- - [x] 记忆去重和冲突检测 (`memorix_deduplicate` + `memorix_consolidate`)
67
- - [x] LLM 增强模式 (压缩/重排序/写入时去重)
68
-
69
- ### Phase 5: Agent 集成 ✅
70
- - [x] Kiro 完整支持
71
- - [x] Trae 支持
72
- - [x] OpenCode 支持
73
- - [x] Gemini CLI 支持
74
- - [x] Copilot hooks 支持
75
- - [x] 10 个 Agent 全覆盖
76
-
77
- ### Phase 6: v1.0.0 特性 ✅
78
- - [x] 团队协作 (Agent注册/文件锁/任务板/消息)
79
- - [x] 工具合并 (41 → 22 默认)
80
- - [x] 启动自动清理 (归档 + LLM/Jaccard 去重)
81
- - [x] Mini-Skills (永久技能, 自动注入)
82
- - [x] 会话管理 (跨会话上下文注入)
83
-
84
- ### Phase 7: 未来路线图
85
- - [ ] 多项目记忆关联搜索
86
- - [ ] LLM-based 实体抽取 (替代正则)
87
- - [ ] JetBrains AI 支持
88
- - [ ] VS Code + Continue.dev 支持
89
- - [ ] 自定义 embedding 模型支持
90
- - [ ] 记忆联邦协议 (跨团队共享)
29
+ ## 仍需注意的边界
30
+
31
+ | 主题 | 现状 | 使用建议 |
32
+ |---|---|---|
33
+ | 项目绑定 | 没有可靠工作区根目录时,MCP 会等待显式根目录、MCP Roots 或会话启动,而不会猜测上一个项目。 | 这是防止跨项目读写的安全边界;首次接入时按客户端的项目根目录配置即可。 |
34
+ | 向量与外部模型 | 可选嵌入提供商、网络和首次模型准备会影响写入或检索延迟。 | 不要把外部 API 的瞬时可用性当作本地数据是否已写入的唯一判断;先用 `memorix status` / `doctor` 看状态。 |
35
+ | 媒体记忆 | 已有受控附件和元数据/向量基础,但 PDF 文本提取、音频转写、视频语义提取仍不是默认的全自动链路。 | 只导入确实需要长期复用的资产;不要把截图或工具输出当作默认记忆来源。 |
36
+ | 图谱与 Wiki | 它们是从规范记忆和代码状态生成的可追溯投影,不是可任意编辑的 GraphRAG 数据库。 | 先写清楚有来源的知识和决策,让投影自然形成关联;不要把图谱当作另一份手工真相。 |
37
+ | Agent 集成 | 上游客户端会改变 hook、MCP、配置文件和权限模型。 | 使用 `memorix doctor agents` 诊断,优先让 `setup` / `repair` 做非破坏性修复。 |
38
+ | 大规模数据 | 保留、归档、去重和检索预算已存在,但上万至百万级数据仍需要按项目负载做容量验证。 | 为高增长项目配置明确的保留与清理策略,并关注 Dashboard / CLI 的审计信息。 |
91
39
 
92
40
  ---
93
41
 
94
- ## 依赖关系
95
-
96
- ### 运行时依赖
97
- | 包 | 版本 | 用途 |
98
- |---|------|------|
99
- | `@modelcontextprotocol/sdk` | ^latest | MCP 协议 SDK |
100
- | `@orama/orama` | ^latest | 全文/向量搜索 |
101
- | `gpt-tokenizer` | ^latest | Token 计数 |
102
- | `citty` | ^latest | CLI 框架 |
103
- | `@clack/prompts` | ^latest | CLI 交互提示 |
104
- | `zod` | ^3 | 参数验证 |
105
-
106
- ### 可选依赖
107
- | 包 | 版本 | 用途 |
108
- |---|------|------|
109
- | `fastembed` | ^latest | 本地 ONNX embedding (384d),需用户显式安装 |
110
-
111
- ### 开发依赖
112
- | 包 | 版本 | 用途 |
113
- |---|------|------|
114
- | `vitest` | ^latest | 测试框架 |
115
- | `tsup` | ^latest | 打包构建 |
116
- | `typescript` | ^5 | 类型系统 |
42
+ ## 公开路线
117
43
 
118
- ---
44
+ ### 1. 稳定性与可操作性
45
+
46
+ - 继续以 Windows、macOS/Linux、CLI、MCP、后台服务和全新安装作为发布门槛;
47
+ - 保持 MCP 工具面小而按需展开,CLI 保持完整的管理和恢复能力;
48
+ - 让配置迁移、诊断、修复和清理保持非破坏性、可解释、可回退。
49
+
50
+ ### 2. 记忆质量与知识工作区
119
51
 
120
- ## 技术债务
52
+ - 提高“新会话接手”时的相关性:先给简短进度卡,再按任务取详情;
53
+ - 统一保留状态、归档、检索预算和 Dashboard 的解释,避免同一条记忆在不同入口显示不同状态;
54
+ - 继续发展代码状态、知识库、Wiki、图谱和工作流之间的可追溯关联,而不是重复堆叠文本摘要。
121
55
 
122
- | 优先级 | 项目 | 说明 |
123
- |--------|------|------|
124
- | ~~P0~~ | ~~文件锁~~ | ~~✅ v0.7.11~~ |
125
- | ~~P1~~ | ~~自动归档~~ | ~~✅ v0.7.11~~ |
126
- | P1 | projectId 稳定性 | 非 Git 项目需要更好的识别策略 |
127
- | ~~P2~~ | ~~中文实体抽取~~ | ~~✅ v0.7.11~~ |
128
- | ~~P2~~ | ~~auto-relations 性能~~ | ~~✅ v0.7.11~~ |
129
- | P3 | Orama 持久化 | 考虑 Orama 的原生持久化而非每次重建 |
130
- | ~~P3~~ | ~~测试覆盖~~ | ~~✅ 753 tests, 56 files, 含 HTTP 集成测试~~ |
56
+ ### 3. 受控的多模态派生能力
57
+
58
+ - 在现有资产生命周期之上评估 PDF 文本提取、音频转写、视频语义派生;
59
+ - 每一类派生都必须有来源、成本边界、配额、删除联动和重建路径;
60
+ - 不把“接受任意 URL / 任意文件”误宣传为完整多模态 RAG。
61
+
62
+ ### 4. Agent 生态与研究
63
+
64
+ - 跟进受用户需求推动的集成,例如 [Qwen 自动 hooks](https://github.com/AVIDS2/memorix/issues/3) 与 [持久化 Agent 身份](https://github.com/AVIDS2/memorix/issues/49);
65
+ - 独立推进记忆能力的实证研究,例如[模型能力如何改变项目记忆收益与伤害边界](https://github.com/AVIDS2/memorix/issues/152),不把研究假设当作产品已经证明的效果。
131
66
 
132
67
  ---
133
68
 
134
- ## 历史重要事件
135
-
136
- | 日期 | 事件 |
137
- |------|------|
138
- | 2026-02-13 | Copilot Adapter 实现完成,274 测试全部通过 |
139
- | 2026-02-13 | Antigravity MCP 配置修复,Memorix MCP Server 首次成功运行 |
140
- | 2026-02-13 | 发现并修复 npx 缓存损坏问题 (MODULE_NOT_FOUND chownr) |
141
- | 2026-02-15 | 完成全部核心模块的深度代码审查 |
142
- | 2026-02-15 | 开发文档完成 (ARCHITECTURE, MODULES, DEVELOPMENT, DESIGN_DECISIONS, API_REFERENCE) |
143
- | 2026-02-24 | v0.7.8-0.7.10: Antigravity 兼容 + MCP roots + 中英双语文档 |
144
- | 2026-02-24 | v0.7.11: P0-P2 全部完成 (文件锁 + 搜索优化 + 自动归档 + 中文实体 + 性能优化 + 图谱同步) |
145
- | 2026-02-25 | v0.9.0-0.9.12: Hooks 系统全量修复 + 10 Agent 支持 |
146
- | 2026-02-28 | v0.9.25: Windsurf 兼容性修复 |
147
- | 2026-03-05 | v0.10.5: Antigravity/Claude Code hooks 修复 |
148
- | 2026-03-07 | v0.11.0: Mini-Skills + LLM 增强模式 |
149
- | 2026-03-09 | **v1.0.0**: 首个稳定版 — 22 工具 + 团队协作 + 自动清理 + 753 测试 |
69
+ ## 贡献与验证原则
70
+
71
+ 贡献会先检查三件事:是否符合当前存储/可见性/生命周期边界,是否能由 CLI 与 MCP 一致地使用,是否有可重复的测试或人工验证证据。功能方向有价值但架构已演进的 PR 会保留作者署名,并通过公开后续 Issue 延续,而不是悄悄重写或吞掉成果。
72
+
73
+ 历史版本、已解决问题和详细发布日期请查看 [CHANGELOG](../CHANGELOG.md)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorix",
3
3
  "mcpName": "io.github.AVIDS2/memorix",
4
- "version": "1.3.4",
4
+ "version": "1.4.1",
5
5
  "description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -44,6 +44,7 @@
44
44
  "README.zh-CN.md",
45
45
  "assets",
46
46
  "docs",
47
+ "!docs/dev-log",
47
48
  "!docs/memcode",
48
49
  "!docs/superpowers",
49
50
  "plugins",
@@ -69,9 +70,11 @@
69
70
  "generate:star-history": "node scripts/generate-star-history.mjs",
70
71
  "sync:mcp-registry": "node scripts/sync-mcp-registry-manifest.mjs",
71
72
  "check:mcp-registry": "node scripts/check-mcp-registry-manifest.mjs",
73
+ "sync:plugin-release": "node scripts/sync-plugin-release-manifests.mjs",
74
+ "check:plugin-release": "node scripts/sync-plugin-release-manifests.mjs --check",
72
75
  "audit:pi-upstream": "node scripts/pi-upstream-audit.mjs",
73
76
  "lint": "tsc --noEmit",
74
- "prepublishOnly": "npm run sync:mcp-registry && npm run check:mcp-registry && npm run build && npm test"
77
+ "prepublishOnly": "npm run sync:mcp-registry && npm run sync:plugin-release && npm run check:mcp-registry && npm run check:plugin-release && npm run build && npm test"
75
78
  },
76
79
  "keywords": [
77
80
  "mcp",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.3.4",
4
+ "version": "1.4.1",
5
5
  "description": "Shared workspace memory for Claude Code and other AI coding agents.",
6
6
  "author": {
7
7
  "name": "AVIDS2",