memorix 1.4.3 → 1.4.5

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 (158) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +20 -6
  3. package/README.zh-CN.md +16 -3
  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 +539 -233
  9. package/dist/cli/memcode.js +0 -0
  10. package/dist/index.js +72 -15
  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 +34 -0
  16. package/dist/sdk.js +71 -14
  17. package/dist/types.d.ts +1 -1
  18. package/dist/vector-backfill-runner.js +9 -7
  19. package/docs/AGENT_OPERATOR_PLAYBOOK.md +6 -5
  20. package/docs/API_REFERENCE.md +9 -5
  21. package/docs/CONFIGURATION.md +15 -5
  22. package/docs/DESIGN_DECISIONS.md +357 -357
  23. package/docs/DEVELOPMENT.md +2 -2
  24. package/docs/INTEGRATIONS.md +9 -2
  25. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +4 -3
  26. package/docs/MEMCODE.md +1 -1
  27. package/docs/MODULES.md +1 -1
  28. package/docs/README.md +1 -1
  29. package/docs/SETUP.md +12 -4
  30. package/docs/hooks-architecture.md +2 -1
  31. package/llms-full.txt +7 -6
  32. package/llms.txt +2 -2
  33. package/package.json +1 -1
  34. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  35. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  36. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  37. package/plugins/copilot/memorix/plugin.json +1 -1
  38. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  39. package/plugins/omp/memorix/package.json +1 -1
  40. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  41. package/plugins/pi/memorix/package.json +1 -1
  42. package/server.json +2 -2
  43. package/src/audit/index.ts +156 -156
  44. package/src/cli/commands/agent-integrations.ts +7 -1
  45. package/src/cli/commands/audit-list.ts +89 -89
  46. package/src/cli/commands/formation.ts +48 -48
  47. package/src/cli/commands/git-hook-install.ts +111 -111
  48. package/src/cli/commands/handoff.ts +54 -54
  49. package/src/cli/commands/hooks-install.ts +2 -0
  50. package/src/cli/commands/hooks-preview.ts +5 -0
  51. package/src/cli/commands/hooks-status.ts +63 -63
  52. package/src/cli/commands/ingest.ts +44 -44
  53. package/src/cli/commands/integrate-shared.ts +15 -15
  54. package/src/cli/commands/integrate.ts +2 -0
  55. package/src/cli/commands/lock.ts +82 -82
  56. package/src/cli/commands/media-image.ts +27 -0
  57. package/src/cli/commands/media.ts +8 -1
  58. package/src/cli/commands/memory.ts +44 -34
  59. package/src/cli/commands/message.ts +104 -104
  60. package/src/cli/commands/operator-shared.ts +62 -18
  61. package/src/cli/commands/poll.ts +58 -58
  62. package/src/cli/commands/purge-all-memory.ts +85 -85
  63. package/src/cli/commands/purge-project-memory.ts +83 -83
  64. package/src/cli/commands/reasoning.ts +118 -118
  65. package/src/cli/commands/setup.ts +57 -2
  66. package/src/cli/commands/skills.ts +114 -114
  67. package/src/cli/commands/task.ts +167 -167
  68. package/src/cli/commands/transfer.ts +47 -47
  69. package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
  70. package/src/cli/commands/uninstall.ts +20 -0
  71. package/src/cli/tui/ChatView.tsx +234 -234
  72. package/src/cli/tui/CommandBar.tsx +312 -312
  73. package/src/cli/tui/ContextRail.tsx +118 -118
  74. package/src/cli/tui/HeaderBar.tsx +72 -72
  75. package/src/cli/tui/LogoBanner.tsx +51 -51
  76. package/src/cli/tui/Sidebar.tsx +179 -179
  77. package/src/cli/tui/index.ts +41 -41
  78. package/src/cli/tui/markdown-render.tsx +371 -371
  79. package/src/cli/tui/use-mouse.ts +157 -157
  80. package/src/cli/tui/useNavigation.ts +56 -56
  81. package/src/cli/version.ts +7 -7
  82. package/src/cli/workbench.ts +1 -1
  83. package/src/dashboard/project-classification.ts +64 -64
  84. package/src/git/hooks-path.ts +85 -85
  85. package/src/hooks/installers/index.ts +43 -2
  86. package/src/hooks/pattern-detector.ts +173 -173
  87. package/src/hooks/significance-filter.ts +250 -250
  88. package/src/hooks/types.ts +2 -0
  89. package/src/integrations/registry.ts +9 -0
  90. package/src/llm/memory-manager.ts +328 -328
  91. package/src/llm/provider.ts +885 -885
  92. package/src/llm/quality.ts +248 -248
  93. package/src/media/minimax.ts +9 -1
  94. package/src/memory/attribution-guard.ts +249 -249
  95. package/src/memory/disclosure-policy.ts +135 -135
  96. package/src/memory/entity-extractor.ts +197 -197
  97. package/src/memory/formation/evaluate.ts +217 -217
  98. package/src/memory/formation/extract.ts +361 -361
  99. package/src/memory/formation/index.ts +417 -417
  100. package/src/memory/formation/resolve.ts +344 -344
  101. package/src/memory/formation/types.ts +315 -315
  102. package/src/memory/freshness.ts +122 -122
  103. package/src/memory/graph.ts +197 -197
  104. package/src/memory/refs.ts +94 -94
  105. package/src/memory/secret-filter.ts +79 -79
  106. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  107. package/src/orchestrate/adapters/claude.ts +111 -111
  108. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  109. package/src/orchestrate/adapters/codex.ts +41 -41
  110. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  111. package/src/orchestrate/adapters/gemini.ts +42 -42
  112. package/src/orchestrate/adapters/index.ts +73 -73
  113. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  114. package/src/orchestrate/adapters/opencode.ts +47 -47
  115. package/src/orchestrate/adapters/types.ts +77 -77
  116. package/src/orchestrate/capability-router.ts +284 -284
  117. package/src/orchestrate/context-compact.ts +188 -188
  118. package/src/orchestrate/cost-tracker.ts +219 -219
  119. package/src/orchestrate/error-recovery.ts +191 -191
  120. package/src/orchestrate/evidence.ts +140 -140
  121. package/src/orchestrate/ledger.ts +110 -110
  122. package/src/orchestrate/memorix-bridge.ts +343 -343
  123. package/src/orchestrate/output-budget.ts +80 -80
  124. package/src/orchestrate/permission.ts +152 -152
  125. package/src/orchestrate/pipeline-trace.ts +131 -131
  126. package/src/orchestrate/prompt-builder.ts +155 -155
  127. package/src/orchestrate/ring-buffer.ts +37 -37
  128. package/src/orchestrate/task-graph.ts +389 -389
  129. package/src/project/aliases.ts +374 -374
  130. package/src/rules/adapters/trae.ts +56 -56
  131. package/src/rules/syncer.ts +235 -235
  132. package/src/search/query-expansion.ts +52 -52
  133. package/src/server/formation-timeout.ts +27 -27
  134. package/src/server.ts +23 -1
  135. package/src/skills/mini-skills.ts +386 -386
  136. package/src/store/chat-store.ts +119 -119
  137. package/src/store/graph-store.ts +249 -249
  138. package/src/store/mini-skill-store.ts +349 -349
  139. package/src/store/persistence-json.ts +212 -212
  140. package/src/store/persistence.ts +291 -291
  141. package/src/store/project-affinity.ts +195 -195
  142. package/src/team/event-bus.ts +76 -76
  143. package/src/team/file-locks.ts +173 -173
  144. package/src/team/handoff.ts +161 -161
  145. package/src/team/messages.ts +203 -203
  146. package/src/team/poll.ts +132 -132
  147. package/src/team/tasks.ts +211 -211
  148. package/src/types.ts +1 -1
  149. package/src/workspace/mcp-adapters/codex.ts +191 -191
  150. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  151. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  152. package/src/workspace/mcp-adapters/dsh.ts +147 -0
  153. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  154. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  155. package/src/workspace/mcp-adapters/trae.ts +134 -134
  156. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  157. package/src/workspace/sanitizer.ts +60 -60
  158. 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,
@@ -164214,7 +164221,7 @@ async function installOfficialSkillsForAgent(agent, projectRoot, global2 = false
164214
164221
  const dirs = AGENT_SKILL_DIRS[agent];
164215
164222
  const relativeDir = global2 ? dirs?.global : dirs?.project;
164216
164223
  if (!relativeDir) return [];
164217
- const root = global2 ? os3.homedir() : projectRoot;
164224
+ const root = global2 ? agent === "dsh" ? process.env.DSH_HOME?.trim() || path32.join(os3.homedir(), ".dsh") : os3.homedir() : projectRoot;
164218
164225
  const skillPaths = [];
164219
164226
  for (const skillEntry of OFFICIAL_MEMORIX_SKILLS) {
164220
164227
  const skillPath = path32.join(root, relativeDir, skillEntry.name, "SKILL.md");
@@ -164446,6 +164453,8 @@ function getProjectConfigPath(agent, projectRoot) {
164446
164453
  return path32.join(projectRoot, "AGENTS.md");
164447
164454
  case "trae":
164448
164455
  return path32.join(projectRoot, ".trae", "rules", "project_rules.md");
164456
+ case "dsh":
164457
+ return path32.join(projectRoot, "AGENTS.md");
164449
164458
  case "opencode":
164450
164459
  return path32.join(projectRoot, ".opencode", "plugins", "memorix.js");
164451
164460
  case "pi":
@@ -164491,6 +164500,8 @@ function getGlobalConfigPath(agent) {
164491
164500
  return path32.join(home, ".omp", "agent", "packages", "memorix", "extensions", "memorix.js");
164492
164501
  case "trae":
164493
164502
  return path32.join(home, ".trae", "rules", "project_rules.md");
164503
+ case "dsh":
164504
+ return path32.join(process.env.DSH_HOME?.trim() || path32.join(home, ".dsh"), "AGENTS.md");
164494
164505
  default:
164495
164506
  return path32.join(home, ".memorix", "hooks.json");
164496
164507
  }
@@ -164515,6 +164526,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
164515
164526
  return path32.join(root, ".gemini", "GEMINI.md");
164516
164527
  case "trae":
164517
164528
  return path32.join(root, ".trae", "rules", "project_rules.md");
164529
+ case "dsh":
164530
+ return path32.join(process.env.DSH_HOME?.trim() || path32.join(root, ".dsh"), "AGENTS.md");
164518
164531
  default:
164519
164532
  return path32.join(root, ".agent", "rules", "memorix.md");
164520
164533
  }
@@ -164539,6 +164552,8 @@ function getAgentRulesPath(agent, root, global2 = false) {
164539
164552
  return path32.join(root, "GEMINI.md");
164540
164553
  case "trae":
164541
164554
  return path32.join(root, ".trae", "rules", "project_rules.md");
164555
+ case "dsh":
164556
+ return path32.join(root, "AGENTS.md");
164542
164557
  default:
164543
164558
  return path32.join(root, ".agent", "rules", "memorix.md");
164544
164559
  }
@@ -164621,6 +164636,12 @@ async function detectInstalledAgents() {
164621
164636
  agents.push("trae");
164622
164637
  } catch {
164623
164638
  }
164639
+ const dshDir = process.env.DSH_HOME?.trim() || path32.join(home, ".dsh");
164640
+ try {
164641
+ await fs21.access(dshDir);
164642
+ agents.push("dsh");
164643
+ } catch {
164644
+ }
164624
164645
  return agents;
164625
164646
  }
164626
164647
  async function installHooks(agent, projectRoot, global2 = false) {
@@ -164703,6 +164724,19 @@ async function installHooks(agent, projectRoot, global2 = false) {
164703
164724
  generated: { note: "Trae has no hooks system, only rules (.trae/rules/project_rules.md) installed" }
164704
164725
  };
164705
164726
  }
164727
+ case "dsh": {
164728
+ const rulesPath = await installAgentRules(agent, projectRoot, global2);
164729
+ const skillPaths2 = await installOfficialSkillsForAgent(agent, projectRoot, global2);
164730
+ return {
164731
+ agent,
164732
+ configPath: rulesPath,
164733
+ events: [],
164734
+ generated: {
164735
+ note: "DeepSeek Harness has no hook system \u2014 installed AGENTS.md guidance and skills; the MCP row is installed by `memorix setup --agent dsh`.",
164736
+ ...skillPaths2.length > 0 ? { skillPaths: skillPaths2, skillPath: skillPaths2[0] } : {}
164737
+ }
164738
+ };
164739
+ }
164706
164740
  case "opencode": {
164707
164741
  const pluginContent = generateOpenCodePlugin();
164708
164742
  const pluginPath = global2 ? getGlobalConfigPath(agent) : getProjectConfigPath(agent, projectRoot);
@@ -164837,7 +164871,7 @@ async function installAgentRules(agent, projectRoot, global2 = false) {
164837
164871
  const rulesPath = getAgentRulesPath(agent, rulesRoot, global2);
164838
164872
  try {
164839
164873
  await fs21.mkdir(path32.dirname(rulesPath), { recursive: true });
164840
- if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli") {
164874
+ if (agent === "claude" || agent === "codex" || agent === "opencode" || agent === "antigravity" || agent === "gemini-cli" || agent === "dsh") {
164841
164875
  try {
164842
164876
  const existing = await fs21.readFile(rulesPath, "utf-8");
164843
164877
  await fs21.writeFile(rulesPath, mergeMemorixRulesContent(existing, rulesContent), "utf-8");
@@ -165126,7 +165160,10 @@ var init_installers = __esm({
165126
165160
  windsurf: { project: path32.join(".windsurf", "skills"), global: path32.join(".windsurf", "skills") },
165127
165161
  kiro: { project: path32.join(".kiro", "skills"), global: path32.join(".kiro", "skills") },
165128
165162
  opencode: { project: path32.join(".opencode", "skills"), global: path32.join(".config", "opencode", "skills") },
165129
- trae: { project: path32.join(".trae", "skills"), global: path32.join(".trae", "skills") }
165163
+ trae: { project: path32.join(".trae", "skills"), global: path32.join(".trae", "skills") },
165164
+ // DSH's user skill root is <harness home>/skills; the global root below is
165165
+ // resolved to $DSH_HOME (or ~/.dsh) for dsh by installOfficialSkillsForAgent.
165166
+ dsh: { project: path32.join(".dsh", "skills"), global: "skills" }
165130
165167
  };
165131
165168
  PACKAGE_OWNED_HOOK_AGENTS = /* @__PURE__ */ new Set(["openclaw", "hermes", "omp"]);
165132
165169
  }
@@ -165553,7 +165590,7 @@ The path should point to a directory containing a .git folder.`
165553
165590
  };
165554
165591
  const server = existingServer ?? new McpServer({
165555
165592
  name: "memorix",
165556
- version: true ? "1.4.3" : "1.0.1"
165593
+ version: true ? "1.4.5" : "1.0.1"
165557
165594
  });
165558
165595
  const originalRegisterTool = server.registerTool.bind(server);
165559
165596
  server.registerTool = ((name, ...args) => {
@@ -169236,6 +169273,16 @@ ${lines.join("\n")}` }] };
169236
169273
  return { content: [{ type: "text", text: lines.filter(Boolean).join("\n") }] };
169237
169274
  }
169238
169275
  );
169276
+ function matchesImagePrefix(bytes, prefix) {
169277
+ return prefix.every((byte, index) => bytes[index] === byte);
169278
+ }
169279
+ function detectReferenceImageMimeType(bytes) {
169280
+ if (bytes.length >= 8 && matchesImagePrefix(bytes, [137, 80, 78, 71, 13, 10, 26, 10])) return "image/png";
169281
+ if (bytes.length >= 3 && matchesImagePrefix(bytes, [255, 216, 255])) return "image/jpeg";
169282
+ 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";
169283
+ 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";
169284
+ return void 0;
169285
+ }
169239
169286
  server.registerTool(
169240
169287
  "memorix_media",
169241
169288
  {
@@ -169251,6 +169298,7 @@ ${lines.join("\n")}` }] };
169251
169298
  title: z626.string().optional().describe("Observation title when attaching generated/imported output."),
169252
169299
  narrative: z626.string().optional().describe("Short retrieval text when attaching an asset."),
169253
169300
  prompt: z626.string().optional().describe("Explicit MiniMax generation prompt."),
169301
+ image: z626.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
169254
169302
  model: z626.string().max(160).optional().describe("Provider model for the selected media action."),
169255
169303
  provider: z626.enum(["openai", "groq"]).optional().describe("Explicit audio transcription provider."),
169256
169304
  language: z626.string().max(32).optional().describe("Optional ISO-639-1 hint for audio transcription."),
@@ -169265,7 +169313,7 @@ ${lines.join("\n")}` }] };
169265
169313
  attach: z626.boolean().optional().describe("Attach generated/imported output to normal project memory explicitly.")
169266
169314
  }
169267
169315
  },
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 }) => {
169316
+ 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
169317
  const unresolved = requireResolvedProject("manage controlled media");
169270
169318
  if (unresolved) return unresolved;
169271
169319
  const safeError4 = (error) => sanitizeCredentials(
@@ -169394,6 +169442,14 @@ ${lines.join("\n")}` }] };
169394
169442
  if (model && !imageModel) throw new Error("generate-image accepts image-01 or image-01-live");
169395
169443
  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
169444
  if (ratio && !imageRatio) throw new Error("generate-image received an unsupported aspect ratio");
169445
+ let subjectImages;
169446
+ if (image?.trim()) {
169447
+ const { decodeBase64ImagePayload: decodeBase64ImagePayload2 } = await Promise.resolve().then(() => (init_image_payload(), image_payload_exports));
169448
+ const bytes = decodeBase64ImagePayload2(image);
169449
+ const mimeType = detectReferenceImageMimeType(bytes);
169450
+ if (!mimeType) throw new Error("Reference image must be a PNG, JPEG, GIF, or WebP image");
169451
+ subjectImages = [{ data: bytes.toString("base64"), mimeType }];
169452
+ }
169397
169453
  const { generateMiniMaxImages: generateMiniMaxImages2 } = await Promise.resolve().then(() => (init_minimax2(), minimax_exports2));
169398
169454
  const generated = await generateMiniMaxImages2({
169399
169455
  dataDir: projectDir2,
@@ -169404,7 +169460,8 @@ ${lines.join("\n")}` }] };
169404
169460
  n,
169405
169461
  aspectRatio: imageRatio,
169406
169462
  width,
169407
- height
169463
+ height,
169464
+ subjectImages
169408
169465
  });
169409
169466
  const observations2 = attach === true ? await Promise.all(generated.assets.map(({ asset }) => attachAsset(
169410
169467
  asset,
@@ -169866,7 +169923,7 @@ var init_serve_shared = __esm({
169866
169923
 
169867
169924
  // src/cli/version.ts
169868
169925
  function getCliVersion() {
169869
- return true ? "1.4.3" : pkg.version;
169926
+ return true ? "1.4.5" : pkg.version;
169870
169927
  }
169871
169928
  var init_version3 = __esm({
169872
169929
  "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,40 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.4.5] - 2026-08-14
6
+
7
+ ### Added
8
+ - **DeepSeek Harness integration** -- `memorix setup --agent dsh` installs
9
+ Memorix into DeepSeek's official harness: a `@deepseek-ai/dsh-mcp-client`
10
+ row in `$DSH_HOME/cordis.patch.yml` (tools appear as `mcp__memorix__*`),
11
+ AGENTS.md guidance at the harness and project levels, and official skills
12
+ under `$DSH_HOME/skills` or `.dsh/skills`. Existing user patch rows are
13
+ preserved and installs are idempotent. DSH has no hook surface, so none is
14
+ written. `doctor`, `repair`, `uninstall`, and `setup --list` cover the new
15
+ target, and MCP checks for user-level-only adapters now run under an
16
+ explicit global scope (fixing the same latent skip for Trae). Native
17
+ validation composed the generated patch with the real
18
+ `@deepseek-ai/dsh@0.1.0-rc.6` launcher.
19
+
20
+ ## [1.4.4] - 2026-08-14
21
+
22
+ ### Added
23
+ - **MiniMax image-to-image** -- `memorix media generate image --image
24
+ <path>` sends a reference image through MiniMax's documented
25
+ `subject_reference` API for the image-01/image-01-live models. The gated
26
+ `memorix_media` MCP tool accepts an optional base64 reference image with the
27
+ same 20 MiB visual limit and MIME validation. The existing MCP generation
28
+ billing gate is unchanged. Contributed by
29
+ [@octo-patch](https://github.com/octo-patch) in #178.
30
+
31
+ ### Fixed
32
+ - **CLI argument crash on long text** -- `memorix memory store --text` could
33
+ fail with `Error: named?.trim is not a function` when a repeated flag or a
34
+ Windows PowerShell 5.1 argument split delivered the value as an array.
35
+ CLI argument coercion now joins repeated free-text arguments and takes the
36
+ last value for scalar and enum flags, with regression tests. Reported by
37
+ [@skywalker-35](https://github.com/skywalker-35) in #194.
38
+
5
39
  ## [1.4.3] - 2026-08-10
6
40
 
7
41
  ### Added