memorix 1.4.3 → 1.4.4

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 (144) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +11 -4
  3. package/README.zh-CN.md +7 -1
  4. package/TEAM.md +86 -86
  5. package/assets/star-history-dark.svg +8 -8
  6. package/assets/star-history-light.svg +8 -8
  7. package/assets/star-history.json +16 -2
  8. package/dist/cli/index.js +194 -109
  9. package/dist/cli/memcode.js +0 -0
  10. package/dist/index.js +39 -12
  11. package/dist/maintenance-runner.js +9 -7
  12. package/dist/media-audio-runner.js +9 -7
  13. package/dist/media-video-runner.js +9 -7
  14. package/dist/memcode/index.js +9 -7
  15. package/dist/memcode-runtime/CHANGELOG.md +19 -0
  16. package/dist/sdk.js +38 -11
  17. package/dist/vector-backfill-runner.js +9 -7
  18. package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -3
  19. package/docs/API_REFERENCE.md +9 -5
  20. package/docs/CONFIGURATION.md +15 -5
  21. package/docs/DESIGN_DECISIONS.md +357 -357
  22. package/docs/DEVELOPMENT.md +2 -2
  23. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +3 -3
  24. package/docs/MODULES.md +1 -1
  25. package/docs/README.md +1 -1
  26. package/docs/SETUP.md +3 -3
  27. package/docs/hooks-architecture.md +2 -1
  28. package/llms-full.txt +4 -4
  29. package/llms.txt +2 -2
  30. package/package.json +1 -1
  31. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  32. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  33. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  34. package/plugins/copilot/memorix/plugin.json +1 -1
  35. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  36. package/plugins/omp/memorix/package.json +1 -1
  37. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  38. package/plugins/pi/memorix/package.json +1 -1
  39. package/server.json +2 -2
  40. package/src/audit/index.ts +156 -156
  41. package/src/cli/commands/audit-list.ts +89 -89
  42. package/src/cli/commands/formation.ts +48 -48
  43. package/src/cli/commands/git-hook-install.ts +111 -111
  44. package/src/cli/commands/handoff.ts +54 -54
  45. package/src/cli/commands/hooks-status.ts +63 -63
  46. package/src/cli/commands/ingest.ts +44 -44
  47. package/src/cli/commands/integrate-shared.ts +15 -15
  48. package/src/cli/commands/lock.ts +82 -82
  49. package/src/cli/commands/media-image.ts +27 -0
  50. package/src/cli/commands/media.ts +8 -1
  51. package/src/cli/commands/memory.ts +44 -34
  52. package/src/cli/commands/message.ts +104 -104
  53. package/src/cli/commands/operator-shared.ts +62 -18
  54. package/src/cli/commands/poll.ts +58 -58
  55. package/src/cli/commands/purge-all-memory.ts +85 -85
  56. package/src/cli/commands/purge-project-memory.ts +83 -83
  57. package/src/cli/commands/reasoning.ts +118 -118
  58. package/src/cli/commands/skills.ts +114 -114
  59. package/src/cli/commands/task.ts +167 -167
  60. package/src/cli/commands/transfer.ts +47 -47
  61. package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
  62. package/src/cli/tui/ChatView.tsx +234 -234
  63. package/src/cli/tui/CommandBar.tsx +312 -312
  64. package/src/cli/tui/ContextRail.tsx +118 -118
  65. package/src/cli/tui/HeaderBar.tsx +72 -72
  66. package/src/cli/tui/LogoBanner.tsx +51 -51
  67. package/src/cli/tui/Sidebar.tsx +179 -179
  68. package/src/cli/tui/index.ts +41 -41
  69. package/src/cli/tui/markdown-render.tsx +371 -371
  70. package/src/cli/tui/use-mouse.ts +157 -157
  71. package/src/cli/tui/useNavigation.ts +56 -56
  72. package/src/cli/version.ts +7 -7
  73. package/src/cli/workbench.ts +1 -1
  74. package/src/dashboard/project-classification.ts +64 -64
  75. package/src/git/hooks-path.ts +85 -85
  76. package/src/hooks/pattern-detector.ts +173 -173
  77. package/src/hooks/significance-filter.ts +250 -250
  78. package/src/llm/memory-manager.ts +328 -328
  79. package/src/llm/provider.ts +885 -885
  80. package/src/llm/quality.ts +248 -248
  81. package/src/media/minimax.ts +9 -1
  82. package/src/memory/attribution-guard.ts +249 -249
  83. package/src/memory/disclosure-policy.ts +135 -135
  84. package/src/memory/entity-extractor.ts +197 -197
  85. package/src/memory/formation/evaluate.ts +217 -217
  86. package/src/memory/formation/extract.ts +361 -361
  87. package/src/memory/formation/index.ts +417 -417
  88. package/src/memory/formation/resolve.ts +344 -344
  89. package/src/memory/formation/types.ts +315 -315
  90. package/src/memory/freshness.ts +122 -122
  91. package/src/memory/graph.ts +197 -197
  92. package/src/memory/refs.ts +94 -94
  93. package/src/memory/secret-filter.ts +79 -79
  94. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  95. package/src/orchestrate/adapters/claude.ts +111 -111
  96. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  97. package/src/orchestrate/adapters/codex.ts +41 -41
  98. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  99. package/src/orchestrate/adapters/gemini.ts +42 -42
  100. package/src/orchestrate/adapters/index.ts +73 -73
  101. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  102. package/src/orchestrate/adapters/opencode.ts +47 -47
  103. package/src/orchestrate/adapters/types.ts +77 -77
  104. package/src/orchestrate/capability-router.ts +284 -284
  105. package/src/orchestrate/context-compact.ts +188 -188
  106. package/src/orchestrate/cost-tracker.ts +219 -219
  107. package/src/orchestrate/error-recovery.ts +191 -191
  108. package/src/orchestrate/evidence.ts +140 -140
  109. package/src/orchestrate/ledger.ts +110 -110
  110. package/src/orchestrate/memorix-bridge.ts +343 -343
  111. package/src/orchestrate/output-budget.ts +80 -80
  112. package/src/orchestrate/permission.ts +152 -152
  113. package/src/orchestrate/pipeline-trace.ts +131 -131
  114. package/src/orchestrate/prompt-builder.ts +155 -155
  115. package/src/orchestrate/ring-buffer.ts +37 -37
  116. package/src/orchestrate/task-graph.ts +389 -389
  117. package/src/project/aliases.ts +374 -374
  118. package/src/rules/adapters/trae.ts +56 -56
  119. package/src/rules/syncer.ts +235 -235
  120. package/src/search/query-expansion.ts +52 -52
  121. package/src/server/formation-timeout.ts +27 -27
  122. package/src/server.ts +23 -1
  123. package/src/skills/mini-skills.ts +386 -386
  124. package/src/store/chat-store.ts +119 -119
  125. package/src/store/graph-store.ts +249 -249
  126. package/src/store/mini-skill-store.ts +349 -349
  127. package/src/store/persistence-json.ts +212 -212
  128. package/src/store/persistence.ts +291 -291
  129. package/src/store/project-affinity.ts +195 -195
  130. package/src/team/event-bus.ts +76 -76
  131. package/src/team/file-locks.ts +173 -173
  132. package/src/team/handoff.ts +161 -161
  133. package/src/team/messages.ts +203 -203
  134. package/src/team/poll.ts +132 -132
  135. package/src/team/tasks.ts +211 -211
  136. package/src/workspace/mcp-adapters/codex.ts +191 -191
  137. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  138. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  139. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  140. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  141. package/src/workspace/mcp-adapters/trae.ts +134 -134
  142. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  143. package/src/workspace/sanitizer.ts +60 -60
  144. package/dist/memcode-runtime/docs/images/exy.png +0 -0
File without changes
package/dist/index.js CHANGED
@@ -17859,7 +17859,7 @@ var init_image_models_generated = __esm({
17859
17859
  api: "minimax-images",
17860
17860
  provider: "minimax",
17861
17861
  baseUrl: "https://api.minimax.io/v1/image_generation",
17862
- input: ["text"],
17862
+ input: ["text", "image"],
17863
17863
  output: ["image"],
17864
17864
  cost: {
17865
17865
  "input": 0,
@@ -17874,7 +17874,7 @@ var init_image_models_generated = __esm({
17874
17874
  api: "minimax-images",
17875
17875
  provider: "minimax",
17876
17876
  baseUrl: "https://api.minimax.io/v1/image_generation",
17877
- input: ["text"],
17877
+ input: ["text", "image"],
17878
17878
  output: ["image"],
17879
17879
  cost: {
17880
17880
  "input": 0,
@@ -17891,7 +17891,7 @@ var init_image_models_generated = __esm({
17891
17891
  api: "minimax-images",
17892
17892
  provider: "minimax-cn",
17893
17893
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
17894
- input: ["text"],
17894
+ input: ["text", "image"],
17895
17895
  output: ["image"],
17896
17896
  cost: {
17897
17897
  "input": 0,
@@ -17906,7 +17906,7 @@ var init_image_models_generated = __esm({
17906
17906
  api: "minimax-images",
17907
17907
  provider: "minimax-cn",
17908
17908
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
17909
- input: ["text"],
17909
+ input: ["text", "image"],
17910
17910
  output: ["image"],
17911
17911
  cost: {
17912
17912
  "input": 0,
@@ -18005,9 +18005,10 @@ __export(minimax_exports, {
18005
18005
  });
18006
18006
  import { isIP as isIP2 } from "net";
18007
18007
  function buildPayload(model, context, options) {
18008
- if (context.input.some((item) => item.type === "image")) {
18009
- throw new Error(`Model ${model.id} does not support image input`);
18010
- }
18008
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
18009
+ type: "character",
18010
+ image_file: `data:${item.mimeType};base64,${item.data}`
18011
+ }));
18011
18012
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
18012
18013
  if (!prompt) {
18013
18014
  throw new Error("MiniMax image generation requires a text prompt");
@@ -18018,6 +18019,7 @@ function buildPayload(model, context, options) {
18018
18019
  return {
18019
18020
  model: model.id,
18020
18021
  prompt,
18022
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
18021
18023
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
18022
18024
  ...options?.width !== void 0 ? { width: options.width } : {},
18023
18025
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -143168,6 +143170,7 @@ async function generateMiniMaxImages(input, dependencies = {}) {
143168
143170
  ...input.height !== void 0 ? { height: input.height } : {},
143169
143171
  ...input.seed !== void 0 ? { seed: input.seed } : {},
143170
143172
  ...input.promptOptimizer !== void 0 ? { promptOptimizer: input.promptOptimizer } : {},
143173
+ ...input.subjectImages !== void 0 && input.subjectImages.length > 0 ? { subjectImages: input.subjectImages } : {},
143171
143174
  timeoutMs
143172
143175
  });
143173
143176
  } catch (error) {
@@ -143207,9 +143210,13 @@ var init_minimax2 = __esm({
143207
143210
  const model = getImageModel(input.provider, input.model);
143208
143211
  if (!model) throw new Error(`MiniMax image model is not registered: ${input.model}`);
143209
143212
  const configuredModel = input.baseUrl ? { ...model, baseUrl: input.baseUrl } : model;
143213
+ const content = [
143214
+ ...(input.subjectImages ?? []).map((image) => ({ type: "image", data: image.data, mimeType: image.mimeType })),
143215
+ { type: "text", text: input.prompt }
143216
+ ];
143210
143217
  const response = await generateImages(
143211
143218
  configuredModel,
143212
- { input: [{ type: "text", text: input.prompt }] },
143219
+ { input: content },
143213
143220
  {
143214
143221
  apiKey: input.apiKey,
143215
143222
  timeoutMs: input.timeoutMs,
@@ -165553,7 +165560,7 @@ The path should point to a directory containing a .git folder.`
165553
165560
  };
165554
165561
  const server = existingServer ?? new McpServer({
165555
165562
  name: "memorix",
165556
- version: true ? "1.4.3" : "1.0.1"
165563
+ version: true ? "1.4.4" : "1.0.1"
165557
165564
  });
165558
165565
  const originalRegisterTool = server.registerTool.bind(server);
165559
165566
  server.registerTool = ((name, ...args) => {
@@ -169236,6 +169243,16 @@ ${lines.join("\n")}` }] };
169236
169243
  return { content: [{ type: "text", text: lines.filter(Boolean).join("\n") }] };
169237
169244
  }
169238
169245
  );
169246
+ function matchesImagePrefix(bytes, prefix) {
169247
+ return prefix.every((byte, index) => bytes[index] === byte);
169248
+ }
169249
+ function detectReferenceImageMimeType(bytes) {
169250
+ if (bytes.length >= 8 && matchesImagePrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) return "image/png";
169251
+ if (bytes.length >= 3 && matchesImagePrefix(bytes, [255, 216, 255])) return "image/jpeg";
169252
+ if (bytes.length >= 6 && (Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF87a" || Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF89a")) return "image/gif";
169253
+ if (bytes.length >= 12 && Buffer.from(bytes.subarray(0, 4)).toString("ascii") === "RIFF" && Buffer.from(bytes.subarray(8, 12)).toString("ascii") === "WEBP") return "image/webp";
169254
+ return void 0;
169255
+ }
169239
169256
  server.registerTool(
169240
169257
  "memorix_media",
169241
169258
  {
@@ -169251,6 +169268,7 @@ ${lines.join("\n")}` }] };
169251
169268
  title: z626.string().optional().describe("Observation title when attaching generated/imported output."),
169252
169269
  narrative: z626.string().optional().describe("Short retrieval text when attaching an asset."),
169253
169270
  prompt: z626.string().optional().describe("Explicit MiniMax generation prompt."),
169271
+ image: z626.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
169254
169272
  model: z626.string().max(160).optional().describe("Provider model for the selected media action."),
169255
169273
  provider: z626.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
169256
169274
  language: z626.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription."),
@@ -169265,7 +169283,7 @@ ${lines.join("\n")}` }] };
169265
169283
  attach: z626.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly.")
169266
169284
  }
169267
169285
  },
169268
- async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
169286
+ async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
169269
169287
  const unresolved = requireResolvedProject("manage controlled media");
169270
169288
  if (unresolved) return unresolved;
169271
169289
  const safeError4 = (error) => sanitizeCredentials(
@@ -169394,6 +169412,14 @@ ${lines.join("\n")}` }] };
169394
169412
  if (model && !imageModel) throw new Error("generate-image accepts image-01 or image-01-live");
169395
169413
  const imageRatio = ratio === "1:1" || ratio === "16:9" || ratio === "4:3" || ratio === "3:2" || ratio === "2:3" || ratio === "3:4" || ratio === "9:16" || ratio === "21:9" ? ratio : void 0;
169396
169414
  if (ratio && !imageRatio) throw new Error("generate-image received an unsupported aspect ratio");
169415
+ let subjectImages;
169416
+ if (image?.trim()) {
169417
+ const { decodeBase64ImagePayload: decodeBase64ImagePayload2 } = await Promise.resolve().then(() => (init_image_payload(), image_payload_exports));
169418
+ const bytes = decodeBase64ImagePayload2(image);
169419
+ const mimeType = detectReferenceImageMimeType(bytes);
169420
+ if (!mimeType) throw new Error("Reference image must be a PNG, JPEG, GIF, or WebP image");
169421
+ subjectImages = [{ data: bytes.toString("base64"), mimeType }];
169422
+ }
169397
169423
  const { generateMiniMaxImages: generateMiniMaxImages2 } = await Promise.resolve().then(() => (init_minimax2(), minimax_exports2));
169398
169424
  const generated = await generateMiniMaxImages2({
169399
169425
  dataDir: projectDir2,
@@ -169404,7 +169430,8 @@ ${lines.join("\n")}` }] };
169404
169430
  n,
169405
169431
  aspectRatio: imageRatio,
169406
169432
  width,
169407
- height
169433
+ height,
169434
+ subjectImages
169408
169435
  });
169409
169436
  const observations2 = attach === true ? await Promise.all(generated.assets.map(({ asset }) => attachAsset(
169410
169437
  asset,
@@ -169866,7 +169893,7 @@ var init_serve_shared = __esm({
169866
169893
 
169867
169894
  // src/cli/version.ts
169868
169895
  function getCliVersion() {
169869
- return true ? "1.4.3" : pkg.version;
169896
+ return true ? "1.4.4" : pkg.version;
169870
169897
  }
169871
169898
  var init_version3 = __esm({
169872
169899
  "src/cli/version.ts"() {
@@ -16266,7 +16266,7 @@ var init_image_models_generated = __esm({
16266
16266
  api: "minimax-images",
16267
16267
  provider: "minimax",
16268
16268
  baseUrl: "https://api.minimax.io/v1/image_generation",
16269
- input: ["text"],
16269
+ input: ["text", "image"],
16270
16270
  output: ["image"],
16271
16271
  cost: {
16272
16272
  "input": 0,
@@ -16281,7 +16281,7 @@ var init_image_models_generated = __esm({
16281
16281
  api: "minimax-images",
16282
16282
  provider: "minimax",
16283
16283
  baseUrl: "https://api.minimax.io/v1/image_generation",
16284
- input: ["text"],
16284
+ input: ["text", "image"],
16285
16285
  output: ["image"],
16286
16286
  cost: {
16287
16287
  "input": 0,
@@ -16298,7 +16298,7 @@ var init_image_models_generated = __esm({
16298
16298
  api: "minimax-images",
16299
16299
  provider: "minimax-cn",
16300
16300
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16301
- input: ["text"],
16301
+ input: ["text", "image"],
16302
16302
  output: ["image"],
16303
16303
  cost: {
16304
16304
  "input": 0,
@@ -16313,7 +16313,7 @@ var init_image_models_generated = __esm({
16313
16313
  api: "minimax-images",
16314
16314
  provider: "minimax-cn",
16315
16315
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16316
- input: ["text"],
16316
+ input: ["text", "image"],
16317
16317
  output: ["image"],
16318
16318
  cost: {
16319
16319
  "input": 0,
@@ -16405,9 +16405,10 @@ __export(minimax_exports, {
16405
16405
  });
16406
16406
  import { isIP as isIP2 } from "net";
16407
16407
  function buildPayload(model, context, options) {
16408
- if (context.input.some((item) => item.type === "image")) {
16409
- throw new Error(`Model ${model.id} does not support image input`);
16410
- }
16408
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
16409
+ type: "character",
16410
+ image_file: `data:${item.mimeType};base64,${item.data}`
16411
+ }));
16411
16412
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
16412
16413
  if (!prompt) {
16413
16414
  throw new Error("MiniMax image generation requires a text prompt");
@@ -16418,6 +16419,7 @@ function buildPayload(model, context, options) {
16418
16419
  return {
16419
16420
  model: model.id,
16420
16421
  prompt,
16422
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
16421
16423
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
16422
16424
  ...options?.width !== void 0 ? { width: options.width } : {},
16423
16425
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -16193,7 +16193,7 @@ var init_image_models_generated = __esm({
16193
16193
  api: "minimax-images",
16194
16194
  provider: "minimax",
16195
16195
  baseUrl: "https://api.minimax.io/v1/image_generation",
16196
- input: ["text"],
16196
+ input: ["text", "image"],
16197
16197
  output: ["image"],
16198
16198
  cost: {
16199
16199
  "input": 0,
@@ -16208,7 +16208,7 @@ var init_image_models_generated = __esm({
16208
16208
  api: "minimax-images",
16209
16209
  provider: "minimax",
16210
16210
  baseUrl: "https://api.minimax.io/v1/image_generation",
16211
- input: ["text"],
16211
+ input: ["text", "image"],
16212
16212
  output: ["image"],
16213
16213
  cost: {
16214
16214
  "input": 0,
@@ -16225,7 +16225,7 @@ var init_image_models_generated = __esm({
16225
16225
  api: "minimax-images",
16226
16226
  provider: "minimax-cn",
16227
16227
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16228
- input: ["text"],
16228
+ input: ["text", "image"],
16229
16229
  output: ["image"],
16230
16230
  cost: {
16231
16231
  "input": 0,
@@ -16240,7 +16240,7 @@ var init_image_models_generated = __esm({
16240
16240
  api: "minimax-images",
16241
16241
  provider: "minimax-cn",
16242
16242
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16243
- input: ["text"],
16243
+ input: ["text", "image"],
16244
16244
  output: ["image"],
16245
16245
  cost: {
16246
16246
  "input": 0,
@@ -16332,9 +16332,10 @@ __export(minimax_exports, {
16332
16332
  });
16333
16333
  import { isIP as isIP2 } from "net";
16334
16334
  function buildPayload(model, context, options) {
16335
- if (context.input.some((item) => item.type === "image")) {
16336
- throw new Error(`Model ${model.id} does not support image input`);
16337
- }
16335
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
16336
+ type: "character",
16337
+ image_file: `data:${item.mimeType};base64,${item.data}`
16338
+ }));
16338
16339
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
16339
16340
  if (!prompt) {
16340
16341
  throw new Error("MiniMax image generation requires a text prompt");
@@ -16345,6 +16346,7 @@ function buildPayload(model, context, options) {
16345
16346
  return {
16346
16347
  model: model.id,
16347
16348
  prompt,
16349
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
16348
16350
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
16349
16351
  ...options?.width !== void 0 ? { width: options.width } : {},
16350
16352
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -16238,7 +16238,7 @@ var init_image_models_generated = __esm({
16238
16238
  api: "minimax-images",
16239
16239
  provider: "minimax",
16240
16240
  baseUrl: "https://api.minimax.io/v1/image_generation",
16241
- input: ["text"],
16241
+ input: ["text", "image"],
16242
16242
  output: ["image"],
16243
16243
  cost: {
16244
16244
  "input": 0,
@@ -16253,7 +16253,7 @@ var init_image_models_generated = __esm({
16253
16253
  api: "minimax-images",
16254
16254
  provider: "minimax",
16255
16255
  baseUrl: "https://api.minimax.io/v1/image_generation",
16256
- input: ["text"],
16256
+ input: ["text", "image"],
16257
16257
  output: ["image"],
16258
16258
  cost: {
16259
16259
  "input": 0,
@@ -16270,7 +16270,7 @@ var init_image_models_generated = __esm({
16270
16270
  api: "minimax-images",
16271
16271
  provider: "minimax-cn",
16272
16272
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16273
- input: ["text"],
16273
+ input: ["text", "image"],
16274
16274
  output: ["image"],
16275
16275
  cost: {
16276
16276
  "input": 0,
@@ -16285,7 +16285,7 @@ var init_image_models_generated = __esm({
16285
16285
  api: "minimax-images",
16286
16286
  provider: "minimax-cn",
16287
16287
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
16288
- input: ["text"],
16288
+ input: ["text", "image"],
16289
16289
  output: ["image"],
16290
16290
  cost: {
16291
16291
  "input": 0,
@@ -16377,9 +16377,10 @@ __export(minimax_exports, {
16377
16377
  });
16378
16378
  import { isIP as isIP2 } from "net";
16379
16379
  function buildPayload(model, context, options) {
16380
- if (context.input.some((item) => item.type === "image")) {
16381
- throw new Error(`Model ${model.id} does not support image input`);
16382
- }
16380
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
16381
+ type: "character",
16382
+ image_file: `data:${item.mimeType};base64,${item.data}`
16383
+ }));
16383
16384
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
16384
16385
  if (!prompt) {
16385
16386
  throw new Error("MiniMax image generation requires a text prompt");
@@ -16390,6 +16391,7 @@ function buildPayload(model, context, options) {
16390
16391
  return {
16391
16392
  model: model.id,
16392
16393
  prompt,
16394
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
16393
16395
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
16394
16396
  ...options?.width !== void 0 ? { width: options.width } : {},
16395
16397
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -33314,9 +33314,10 @@ __export(minimax_exports, {
33314
33314
  });
33315
33315
  import { isIP } from "net";
33316
33316
  function buildPayload(model, context, options2) {
33317
- if (context.input.some((item) => item.type === "image")) {
33318
- throw new Error(`Model ${model.id} does not support image input`);
33319
- }
33317
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
33318
+ type: "character",
33319
+ image_file: `data:${item.mimeType};base64,${item.data}`
33320
+ }));
33320
33321
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
33321
33322
  if (!prompt) {
33322
33323
  throw new Error("MiniMax image generation requires a text prompt");
@@ -33327,6 +33328,7 @@ function buildPayload(model, context, options2) {
33327
33328
  return {
33328
33329
  model: model.id,
33329
33330
  prompt,
33331
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
33330
33332
  ...options2?.aspectRatio !== void 0 ? { aspect_ratio: options2.aspectRatio } : {},
33331
33333
  ...options2?.width !== void 0 ? { width: options2.width } : {},
33332
33334
  ...options2?.height !== void 0 ? { height: options2.height } : {},
@@ -199689,7 +199691,7 @@ var IMAGE_MODELS = {
199689
199691
  api: "minimax-images",
199690
199692
  provider: "minimax",
199691
199693
  baseUrl: "https://api.minimax.io/v1/image_generation",
199692
- input: ["text"],
199694
+ input: ["text", "image"],
199693
199695
  output: ["image"],
199694
199696
  cost: {
199695
199697
  "input": 0,
@@ -199704,7 +199706,7 @@ var IMAGE_MODELS = {
199704
199706
  api: "minimax-images",
199705
199707
  provider: "minimax",
199706
199708
  baseUrl: "https://api.minimax.io/v1/image_generation",
199707
- input: ["text"],
199709
+ input: ["text", "image"],
199708
199710
  output: ["image"],
199709
199711
  cost: {
199710
199712
  "input": 0,
@@ -199721,7 +199723,7 @@ var IMAGE_MODELS = {
199721
199723
  api: "minimax-images",
199722
199724
  provider: "minimax-cn",
199723
199725
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
199724
- input: ["text"],
199726
+ input: ["text", "image"],
199725
199727
  output: ["image"],
199726
199728
  cost: {
199727
199729
  "input": 0,
@@ -199736,7 +199738,7 @@ var IMAGE_MODELS = {
199736
199738
  api: "minimax-images",
199737
199739
  provider: "minimax-cn",
199738
199740
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
199739
- input: ["text"],
199741
+ input: ["text", "image"],
199740
199742
  output: ["image"],
199741
199743
  cost: {
199742
199744
  "input": 0,
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.4] - 2026-08-14
6
+
7
+ ### Added
8
+ - **MiniMax image-to-image** -- `memorix media generate image --image
9
+ <path>` sends a reference image through MiniMax's documented
10
+ `subject_reference` API for the image-01/image-01-live models. The gated
11
+ `memorix_media` MCP tool accepts an optional base64 reference image with the
12
+ same 20 MiB visual limit and MIME validation. The existing MCP generation
13
+ billing gate is unchanged. Contributed by
14
+ [@octo-patch](https://github.com/octo-patch) in #178.
15
+
16
+ ### Fixed
17
+ - **CLI argument crash on long text** -- `memorix memory store --text` could
18
+ fail with `Error: named?.trim is not a function` when a repeated flag or a
19
+ Windows PowerShell 5.1 argument split delivered the value as an array.
20
+ CLI argument coercion now joins repeated free-text arguments and takes the
21
+ last value for scalar and enum flags, with regression tests. Reported by
22
+ [@skywalker-35](https://github.com/skywalker-35) in #194.
23
+
5
24
  ## [1.4.3] - 2026-08-10
6
25
 
7
26
  ### Added
package/dist/sdk.js CHANGED
@@ -17863,7 +17863,7 @@ var init_image_models_generated = __esm({
17863
17863
  api: "minimax-images",
17864
17864
  provider: "minimax",
17865
17865
  baseUrl: "https://api.minimax.io/v1/image_generation",
17866
- input: ["text"],
17866
+ input: ["text", "image"],
17867
17867
  output: ["image"],
17868
17868
  cost: {
17869
17869
  "input": 0,
@@ -17878,7 +17878,7 @@ var init_image_models_generated = __esm({
17878
17878
  api: "minimax-images",
17879
17879
  provider: "minimax",
17880
17880
  baseUrl: "https://api.minimax.io/v1/image_generation",
17881
- input: ["text"],
17881
+ input: ["text", "image"],
17882
17882
  output: ["image"],
17883
17883
  cost: {
17884
17884
  "input": 0,
@@ -17895,7 +17895,7 @@ var init_image_models_generated = __esm({
17895
17895
  api: "minimax-images",
17896
17896
  provider: "minimax-cn",
17897
17897
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
17898
- input: ["text"],
17898
+ input: ["text", "image"],
17899
17899
  output: ["image"],
17900
17900
  cost: {
17901
17901
  "input": 0,
@@ -17910,7 +17910,7 @@ var init_image_models_generated = __esm({
17910
17910
  api: "minimax-images",
17911
17911
  provider: "minimax-cn",
17912
17912
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
17913
- input: ["text"],
17913
+ input: ["text", "image"],
17914
17914
  output: ["image"],
17915
17915
  cost: {
17916
17916
  "input": 0,
@@ -18009,9 +18009,10 @@ __export(minimax_exports, {
18009
18009
  });
18010
18010
  import { isIP as isIP2 } from "net";
18011
18011
  function buildPayload(model, context, options) {
18012
- if (context.input.some((item) => item.type === "image")) {
18013
- throw new Error(`Model ${model.id} does not support image input`);
18014
- }
18012
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
18013
+ type: "character",
18014
+ image_file: `data:${item.mimeType};base64,${item.data}`
18015
+ }));
18015
18016
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
18016
18017
  if (!prompt) {
18017
18018
  throw new Error("MiniMax image generation requires a text prompt");
@@ -18022,6 +18023,7 @@ function buildPayload(model, context, options) {
18022
18023
  return {
18023
18024
  model: model.id,
18024
18025
  prompt,
18026
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
18025
18027
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
18026
18028
  ...options?.width !== void 0 ? { width: options.width } : {},
18027
18029
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -143172,6 +143174,7 @@ async function generateMiniMaxImages(input, dependencies = {}) {
143172
143174
  ...input.height !== void 0 ? { height: input.height } : {},
143173
143175
  ...input.seed !== void 0 ? { seed: input.seed } : {},
143174
143176
  ...input.promptOptimizer !== void 0 ? { promptOptimizer: input.promptOptimizer } : {},
143177
+ ...input.subjectImages !== void 0 && input.subjectImages.length > 0 ? { subjectImages: input.subjectImages } : {},
143175
143178
  timeoutMs
143176
143179
  });
143177
143180
  } catch (error) {
@@ -143211,9 +143214,13 @@ var init_minimax2 = __esm({
143211
143214
  const model = getImageModel(input.provider, input.model);
143212
143215
  if (!model) throw new Error(`MiniMax image model is not registered: ${input.model}`);
143213
143216
  const configuredModel = input.baseUrl ? { ...model, baseUrl: input.baseUrl } : model;
143217
+ const content = [
143218
+ ...(input.subjectImages ?? []).map((image) => ({ type: "image", data: image.data, mimeType: image.mimeType })),
143219
+ { type: "text", text: input.prompt }
143220
+ ];
143214
143221
  const response = await generateImages(
143215
143222
  configuredModel,
143216
- { input: [{ type: "text", text: input.prompt }] },
143223
+ { input: content },
143217
143224
  {
143218
143225
  apiKey: input.apiKey,
143219
143226
  timeoutMs: input.timeoutMs,
@@ -165367,7 +165374,7 @@ The path should point to a directory containing a .git folder.`
165367
165374
  };
165368
165375
  const server = existingServer ?? new McpServer({
165369
165376
  name: "memorix",
165370
- version: true ? "1.4.3" : "1.0.1"
165377
+ version: true ? "1.4.4" : "1.0.1"
165371
165378
  });
165372
165379
  const originalRegisterTool = server.registerTool.bind(server);
165373
165380
  server.registerTool = ((name, ...args) => {
@@ -169050,6 +169057,16 @@ ${lines.join("\n")}` }] };
169050
169057
  return { content: [{ type: "text", text: lines.filter(Boolean).join("\n") }] };
169051
169058
  }
169052
169059
  );
169060
+ function matchesImagePrefix(bytes, prefix) {
169061
+ return prefix.every((byte, index) => bytes[index] === byte);
169062
+ }
169063
+ function detectReferenceImageMimeType(bytes) {
169064
+ if (bytes.length >= 8 && matchesImagePrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) return "image/png";
169065
+ if (bytes.length >= 3 && matchesImagePrefix(bytes, [255, 216, 255])) return "image/jpeg";
169066
+ if (bytes.length >= 6 && (Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF87a" || Buffer.from(bytes.subarray(0, 6)).toString("ascii") === "GIF89a")) return "image/gif";
169067
+ if (bytes.length >= 12 && Buffer.from(bytes.subarray(0, 4)).toString("ascii") === "RIFF" && Buffer.from(bytes.subarray(8, 12)).toString("ascii") === "WEBP") return "image/webp";
169068
+ return void 0;
169069
+ }
169053
169070
  server.registerTool(
169054
169071
  "memorix_media",
169055
169072
  {
@@ -169065,6 +169082,7 @@ ${lines.join("\n")}` }] };
169065
169082
  title: z626.string().optional().describe("Observation title when attaching generated/imported output."),
169066
169083
  narrative: z626.string().optional().describe("Short retrieval text when attaching an asset."),
169067
169084
  prompt: z626.string().optional().describe("Explicit MiniMax generation prompt."),
169085
+ image: z626.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
169068
169086
  model: z626.string().max(160).optional().describe("Provider model for the selected media action."),
169069
169087
  provider: z626.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
169070
169088
  language: z626.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription."),
@@ -169079,7 +169097,7 @@ ${lines.join("\n")}` }] };
169079
169097
  attach: z626.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly.")
169080
169098
  }
169081
169099
  },
169082
- async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
169100
+ async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
169083
169101
  const unresolved = requireResolvedProject("manage controlled media");
169084
169102
  if (unresolved) return unresolved;
169085
169103
  const safeError4 = (error) => sanitizeCredentials(
@@ -169208,6 +169226,14 @@ ${lines.join("\n")}` }] };
169208
169226
  if (model && !imageModel) throw new Error("generate-image accepts image-01 or image-01-live");
169209
169227
  const imageRatio = ratio === "1:1" || ratio === "16:9" || ratio === "4:3" || ratio === "3:2" || ratio === "2:3" || ratio === "3:4" || ratio === "9:16" || ratio === "21:9" ? ratio : void 0;
169210
169228
  if (ratio && !imageRatio) throw new Error("generate-image received an unsupported aspect ratio");
169229
+ let subjectImages;
169230
+ if (image?.trim()) {
169231
+ const { decodeBase64ImagePayload: decodeBase64ImagePayload2 } = await Promise.resolve().then(() => (init_image_payload(), image_payload_exports));
169232
+ const bytes = decodeBase64ImagePayload2(image);
169233
+ const mimeType = detectReferenceImageMimeType(bytes);
169234
+ if (!mimeType) throw new Error("Reference image must be a PNG, JPEG, GIF, or WebP image");
169235
+ subjectImages = [{ data: bytes.toString("base64"), mimeType }];
169236
+ }
169211
169237
  const { generateMiniMaxImages: generateMiniMaxImages2 } = await Promise.resolve().then(() => (init_minimax2(), minimax_exports2));
169212
169238
  const generated = await generateMiniMaxImages2({
169213
169239
  dataDir: projectDir2,
@@ -169218,7 +169244,8 @@ ${lines.join("\n")}` }] };
169218
169244
  n,
169219
169245
  aspectRatio: imageRatio,
169220
169246
  width,
169221
- height
169247
+ height,
169248
+ subjectImages
169222
169249
  });
169223
169250
  const observations2 = attach === true ? await Promise.all(generated.assets.map(({ asset }) => attachAsset(
169224
169251
  asset,
@@ -18216,7 +18216,7 @@ var init_image_models_generated = __esm({
18216
18216
  api: "minimax-images",
18217
18217
  provider: "minimax",
18218
18218
  baseUrl: "https://api.minimax.io/v1/image_generation",
18219
- input: ["text"],
18219
+ input: ["text", "image"],
18220
18220
  output: ["image"],
18221
18221
  cost: {
18222
18222
  "input": 0,
@@ -18231,7 +18231,7 @@ var init_image_models_generated = __esm({
18231
18231
  api: "minimax-images",
18232
18232
  provider: "minimax",
18233
18233
  baseUrl: "https://api.minimax.io/v1/image_generation",
18234
- input: ["text"],
18234
+ input: ["text", "image"],
18235
18235
  output: ["image"],
18236
18236
  cost: {
18237
18237
  "input": 0,
@@ -18248,7 +18248,7 @@ var init_image_models_generated = __esm({
18248
18248
  api: "minimax-images",
18249
18249
  provider: "minimax-cn",
18250
18250
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
18251
- input: ["text"],
18251
+ input: ["text", "image"],
18252
18252
  output: ["image"],
18253
18253
  cost: {
18254
18254
  "input": 0,
@@ -18263,7 +18263,7 @@ var init_image_models_generated = __esm({
18263
18263
  api: "minimax-images",
18264
18264
  provider: "minimax-cn",
18265
18265
  baseUrl: "https://api.minimaxi.com/v1/image_generation",
18266
- input: ["text"],
18266
+ input: ["text", "image"],
18267
18267
  output: ["image"],
18268
18268
  cost: {
18269
18269
  "input": 0,
@@ -18355,9 +18355,10 @@ __export(minimax_exports, {
18355
18355
  });
18356
18356
  import { isIP as isIP2 } from "net";
18357
18357
  function buildPayload(model, context, options) {
18358
- if (context.input.some((item) => item.type === "image")) {
18359
- throw new Error(`Model ${model.id} does not support image input`);
18360
- }
18358
+ const subjectReference = context.input.filter((item) => item.type === "image").map((item) => ({
18359
+ type: "character",
18360
+ image_file: `data:${item.mimeType};base64,${item.data}`
18361
+ }));
18361
18362
  const prompt = context.input.filter((item) => item.type === "text").map((item) => sanitizeSurrogates(item.text).trim()).filter(Boolean).join("\n");
18362
18363
  if (!prompt) {
18363
18364
  throw new Error("MiniMax image generation requires a text prompt");
@@ -18368,6 +18369,7 @@ function buildPayload(model, context, options) {
18368
18369
  return {
18369
18370
  model: model.id,
18370
18371
  prompt,
18372
+ ...subjectReference.length > 0 ? { subject_reference: subjectReference } : {},
18371
18373
  ...options?.aspectRatio !== void 0 ? { aspect_ratio: options.aspectRatio } : {},
18372
18374
  ...options?.width !== void 0 ? { width: options.width } : {},
18373
18375
  ...options?.height !== void 0 ? { height: options.height } : {},
@@ -25,9 +25,9 @@ It supports:
25
25
  - local-first project-scoped memory
26
26
  - cross-agent recall across Cursor, Claude Code, Codex, CodeBuddy Code, Windsurf, Gemini CLI, GitHub Copilot, OpenCode, OpenClaw, Hermes Agent, Oh-my-Pi, Pi, Kiro, Antigravity, and Trae
27
27
 
28
- ### Current 1.2 Baseline
28
+ ### Current 1.4 Baseline
29
29
 
30
- For the 1.2 release line, the visible product shape is:
30
+ For the 1.4 release line, the visible product shape is:
31
31
 
32
32
  - `memorix setup --agent <agent> --global` is the default integration command for an existing coding agent or IDE
33
33
  - setup installs plugin packages where supported, MCP config, usage guidance, hooks, and skills according to agent capability
@@ -50,7 +50,7 @@ For the 1.2 release line, the visible product shape is:
50
50
 
51
51
  ### CLI is the direct command surface; MCP is the integration layer
52
52
 
53
- For direct use, prefer `memorix ...` commands first. In the 1.3 line, the CLI covers session, memory, reviewed long-term memory, Code State, knowledge workspaces, reasoning, retention, formation, audit, transfer, skills, orchestration coordination, sync, ingest workflows, and the bundled terminal agent.
53
+ For direct use, prefer `memorix ...` commands first. In the 1.4 line, the CLI covers session, memory, reviewed long-term memory, Code State, knowledge workspaces, reasoning, retention, formation, audit, transfer, skills, orchestration coordination, sync, controlled media, ingest workflows, and the bundled terminal agent.
54
54
 
55
55
  Do not ask memory-only users to join coordination state. A lightweight session is enough for memory, retrieval, reasoning, and continuation. Use `joinTeam` / `team_manage(join)` only for explicit task/message/lock coordination or for CLI-agent work managed by `memorix orchestrate`.
56
56