memorix 1.9.3 → 1.9.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.9.4] - 2026-09-18
8
+
9
+ ### Added
10
+ - **MiniMax first-frame video input** -- image-to-video generation now accepts
11
+ a public HTTPS first-frame image URL through the CLI and MCP surfaces,
12
+ preserves it in durable media jobs, and submits it with the provider's
13
+ `first_frame` image role.
14
+
15
+ ### Fixed
16
+ - **First-frame URL safety** -- rejects non-HTTPS URLs and embedded credentials
17
+ before a media request is submitted or persisted.
18
+
19
+ ### Changed
20
+ - **Grok Build documentation** -- the README comparison now uses the official
21
+ Grok Build logo assets.
22
+
7
23
  ## [1.9.3] - 2026-09-14
8
24
 
9
25
  ### Fixed
package/README.md CHANGED
@@ -187,7 +187,7 @@ Memorix connects through the interfaces each agent already supports: plugin pack
187
187
  <sub>stdio or HTTP MCP</sub>
188
188
  </td>
189
189
  <td align="center" width="12.5%">
190
- <a href="https://github.com/xai-org/grok-build"><img src="https://github.com/xai-org.png?size=120" alt="Grok Build" width="48" height="48"></a><br>
190
+ <a href="https://github.com/xai-org/grok-build"><picture><source media="(prefers-color-scheme: dark)" srcset="https://media.x.ai/v1/website/spacexai-symbol-white-transparent-0c31957f.png"><img src="https://media.x.ai/v1/website/spacexai-symbol-black-transparent-6435cf42.png" alt="Grok Build" width="48" height="48"></picture></a><br>
191
191
  <strong>Grok Build</strong><br>
192
192
  <sub>native hooks + AGENTS.md</sub>
193
193
  </td>
package/README.zh-CN.md CHANGED
@@ -182,7 +182,7 @@ Memorix 通过目标 Agent 已有的接口接入:插件包、MCP、项目规
182
182
  <sub>stdio or HTTP MCP</sub>
183
183
  </td>
184
184
  <td align="center" width="12.5%">
185
- <a href="https://github.com/xai-org/grok-build"><img src="https://github.com/xai-org.png?size=120" alt="Grok Build" width="48" height="48"></a><br>
185
+ <a href="https://github.com/xai-org/grok-build"><picture><source media="(prefers-color-scheme: dark)" srcset="https://media.x.ai/v1/website/spacexai-symbol-white-transparent-0c31957f.png"><img src="https://media.x.ai/v1/website/spacexai-symbol-black-transparent-6435cf42.png" alt="Grok Build" width="48" height="48"></picture></a><br>
186
186
  <strong>Grok Build</strong><br>
187
187
  <sub>原生 hooks + AGENTS.md</sub>
188
188
  </td>
package/dist/cli/index.js CHANGED
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
3232
3232
 
3233
3233
  // src/cli/version.ts
3234
3234
  function getCliVersion() {
3235
- return true ? "1.9.3" : pkg.version;
3235
+ return true ? "1.9.4" : pkg.version;
3236
3236
  }
3237
3237
  var init_version = __esm({
3238
3238
  "src/cli/version.ts"() {
@@ -177667,7 +177667,20 @@ function normalizeMiniMaxVideoRequest(input) {
177667
177667
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
177668
177668
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
177669
177669
  }
177670
- return { region, model, prompt: prompt2, resolution, duration: duration3, ratio };
177670
+ let firstFrameImageUrl;
177671
+ if (input.firstFrameImageUrl !== void 0) {
177672
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
177673
+ let parsed;
177674
+ try {
177675
+ parsed = new URL(firstFrameImageUrl);
177676
+ } catch {
177677
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
177678
+ }
177679
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
177680
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
177681
+ }
177682
+ }
177683
+ return { region, model, prompt: prompt2, resolution, duration: duration3, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
177671
177684
  }
177672
177685
  function videoRequestConfig(input) {
177673
177686
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -177744,7 +177757,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
177744
177757
  headers: videoHeaders(config2.apiKey),
177745
177758
  body: JSON.stringify({
177746
177759
  model: config2.model,
177747
- content: [{ type: "text", text: config2.prompt }],
177760
+ content: [
177761
+ { type: "text", text: config2.prompt },
177762
+ ...config2.firstFrameImageUrl ? [{
177763
+ type: "image_url",
177764
+ image_url: { url: config2.firstFrameImageUrl },
177765
+ role: "first_frame"
177766
+ }] : []
177767
+ ],
177748
177768
  resolution: config2.resolution,
177749
177769
  duration: config2.duration,
177750
177770
  ratio: config2.ratio
@@ -177992,10 +178012,19 @@ function parseStoredRequest(value) {
177992
178012
  const duration3 = value.duration;
177993
178013
  const ratio = value.ratio;
177994
178014
  const maxBytes = value.maxBytes;
177995
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt2 !== "string" || resolution !== "2K" || duration3 !== 5 && duration3 !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
178015
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt2 !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration3 !== 5 && duration3 !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
177996
178016
  throw new Error("Media video job has an invalid request payload");
177997
178017
  }
177998
- return { provider: provider2, region, model, prompt: prompt2, resolution, duration: duration3, ratio, maxBytes };
178018
+ const normalized = normalizeMiniMaxVideoRequest({
178019
+ region,
178020
+ model,
178021
+ prompt: prompt2,
178022
+ resolution,
178023
+ duration: duration3,
178024
+ ratio,
178025
+ firstFrameImageUrl: value.firstFrameImageUrl
178026
+ });
178027
+ return { provider: provider2, ...normalized, maxBytes };
177999
178028
  }
178000
178029
  function mediaJobIdFromMaintenance(job) {
178001
178030
  const mediaJobId = job.payload.mediaJobId;
@@ -178007,6 +178036,7 @@ function mediaJobIdFromMaintenance(job) {
178007
178036
  function toVideoRequest(request) {
178008
178037
  return {
178009
178038
  prompt: request.prompt,
178039
+ firstFrameImageUrl: request.firstFrameImageUrl,
178010
178040
  model: request.model,
178011
178041
  region: request.region,
178012
178042
  resolution: request.resolution,
@@ -178098,6 +178128,7 @@ function queueMiniMaxVideoGeneration(input) {
178098
178128
  region: normalized.region,
178099
178129
  model: normalized.model,
178100
178130
  prompt: normalized.prompt,
178131
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
178101
178132
  resolution: normalized.resolution,
178102
178133
  duration: normalized.duration,
178103
178134
  ratio: normalized.ratio,
@@ -207958,7 +207989,7 @@ var init_tool_profile = __esm({
207958
207989
  function getMcpServerInfo() {
207959
207990
  return {
207960
207991
  name: "memorix",
207961
- version: true ? "1.9.3" : "1.0.1"
207992
+ version: true ? "1.9.4" : "1.0.1"
207962
207993
  };
207963
207994
  }
207964
207995
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -268636,6 +268667,7 @@ ${lines.join("\n")}` }] };
268636
268667
  } : {},
268637
268668
  ...mediaGenerationEnabled ? {
268638
268669
  image: external_exports2.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
268670
+ firstFrameImageUrl: external_exports2.string().optional().describe("Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job."),
268639
268671
  region: external_exports2.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
268640
268672
  n: external_exports2.number().int().min(1).max(4).optional().describe("Image output count."),
268641
268673
  ratio: external_exports2.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
@@ -268645,7 +268677,7 @@ ${lines.join("\n")}` }] };
268645
268677
  } : {}
268646
268678
  }
268647
268679
  },
268648
- async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt: prompt2, image, model, provider: provider2, language, region, n: n3, ratio, width, height, duration: duration3, maxPages, maxChars, attach }) => {
268680
+ async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt: prompt2, image, firstFrameImageUrl, model, provider: provider2, language, region, n: n3, ratio, width, height, duration: duration3, maxPages, maxChars, attach }) => {
268649
268681
  const unresolved = requireResolvedProject("manage controlled media");
268650
268682
  if (unresolved) return unresolved;
268651
268683
  const safeError4 = (error40) => sanitizeCredentials(
@@ -268815,6 +268847,7 @@ ${lines.join("\n")}` }] };
268815
268847
  dataDir: projectDir2,
268816
268848
  projectId: project.id,
268817
268849
  prompt: prompt2,
268850
+ firstFrameImageUrl,
268818
268851
  ...model === "MiniMax-H3" ? { model } : {},
268819
268852
  ...region ? { region } : {},
268820
268853
  ...videoRatio ? { ratio: videoRatio } : {},
@@ -279290,6 +279323,7 @@ var init_media = __esm({
279290
279323
  concepts: { type: "string", description: "Comma-separated concepts when attaching" },
279291
279324
  visibility: { type: "string", description: "Observation visibility when attaching" },
279292
279325
  prompt: { type: "string", description: "Generation prompt" },
279326
+ "first-frame-image-url": { type: "string", description: "Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job" },
279293
279327
  image: { type: "string", description: "Path to a reference image for image-to-image generation" },
279294
279328
  model: { type: "string", description: "Provider model" },
279295
279329
  provider: { type: "string", description: "Audio transcription provider: openai or groq" },
@@ -279340,6 +279374,7 @@ var init_media = __esm({
279340
279374
  dataDir,
279341
279375
  projectId: project.id,
279342
279376
  prompt: prompt2,
279377
+ firstFrameImageUrl: args["first-frame-image-url"],
279343
279378
  model: parseMiniMaxVideoModel(args.model),
279344
279379
  region: parseMiniMaxRegion(args.region),
279345
279380
  duration: parseMiniMaxVideoDuration(args.duration),
package/dist/index.js CHANGED
@@ -145188,7 +145188,20 @@ function normalizeMiniMaxVideoRequest(input) {
145188
145188
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
145189
145189
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
145190
145190
  }
145191
- return { region, model, prompt, resolution, duration, ratio };
145191
+ let firstFrameImageUrl;
145192
+ if (input.firstFrameImageUrl !== void 0) {
145193
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
145194
+ let parsed;
145195
+ try {
145196
+ parsed = new URL(firstFrameImageUrl);
145197
+ } catch {
145198
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
145199
+ }
145200
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
145201
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
145202
+ }
145203
+ }
145204
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
145192
145205
  }
145193
145206
  function videoRequestConfig(input) {
145194
145207
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -145265,7 +145278,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
145265
145278
  headers: videoHeaders(config.apiKey),
145266
145279
  body: JSON.stringify({
145267
145280
  model: config.model,
145268
- content: [{ type: "text", text: config.prompt }],
145281
+ content: [
145282
+ { type: "text", text: config.prompt },
145283
+ ...config.firstFrameImageUrl ? [{
145284
+ type: "image_url",
145285
+ image_url: { url: config.firstFrameImageUrl },
145286
+ role: "first_frame"
145287
+ }] : []
145288
+ ],
145269
145289
  resolution: config.resolution,
145270
145290
  duration: config.duration,
145271
145291
  ratio: config.ratio
@@ -145513,10 +145533,19 @@ function parseStoredRequest(value) {
145513
145533
  const duration = value.duration;
145514
145534
  const ratio = value.ratio;
145515
145535
  const maxBytes = value.maxBytes;
145516
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
145536
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
145517
145537
  throw new Error("Media video job has an invalid request payload");
145518
145538
  }
145519
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
145539
+ const normalized = normalizeMiniMaxVideoRequest({
145540
+ region,
145541
+ model,
145542
+ prompt,
145543
+ resolution,
145544
+ duration,
145545
+ ratio,
145546
+ firstFrameImageUrl: value.firstFrameImageUrl
145547
+ });
145548
+ return { provider: provider2, ...normalized, maxBytes };
145520
145549
  }
145521
145550
  function mediaJobIdFromMaintenance(job) {
145522
145551
  const mediaJobId = job.payload.mediaJobId;
@@ -145528,6 +145557,7 @@ function mediaJobIdFromMaintenance(job) {
145528
145557
  function toVideoRequest(request) {
145529
145558
  return {
145530
145559
  prompt: request.prompt,
145560
+ firstFrameImageUrl: request.firstFrameImageUrl,
145531
145561
  model: request.model,
145532
145562
  region: request.region,
145533
145563
  resolution: request.resolution,
@@ -145619,6 +145649,7 @@ function queueMiniMaxVideoGeneration(input) {
145619
145649
  region: normalized.region,
145620
145650
  model: normalized.model,
145621
145651
  prompt: normalized.prompt,
145652
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
145622
145653
  resolution: normalized.resolution,
145623
145654
  duration: normalized.duration,
145624
145655
  ratio: normalized.ratio,
@@ -159771,7 +159802,7 @@ var init_request_context = __esm({
159771
159802
  function getMcpServerInfo() {
159772
159803
  return {
159773
159804
  name: "memorix",
159774
- version: true ? "1.9.3" : "1.0.1"
159805
+ version: true ? "1.9.4" : "1.0.1"
159775
159806
  };
159776
159807
  }
159777
159808
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -174485,6 +174516,7 @@ ${lines.join("\n")}` }] };
174485
174516
  } : {},
174486
174517
  ...mediaGenerationEnabled ? {
174487
174518
  image: z627.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
174519
+ firstFrameImageUrl: z627.string().optional().describe("Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job."),
174488
174520
  region: z627.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
174489
174521
  n: z627.number().int().min(1).max(4).optional().describe("Image output count."),
174490
174522
  ratio: z627.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
@@ -174494,7 +174526,7 @@ ${lines.join("\n")}` }] };
174494
174526
  } : {}
174495
174527
  }
174496
174528
  },
174497
- 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 }) => {
174529
+ async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, firstFrameImageUrl, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
174498
174530
  const unresolved = requireResolvedProject("manage controlled media");
174499
174531
  if (unresolved) return unresolved;
174500
174532
  const safeError4 = (error) => sanitizeCredentials(
@@ -174664,6 +174696,7 @@ ${lines.join("\n")}` }] };
174664
174696
  dataDir: projectDir2,
174665
174697
  projectId: project.id,
174666
174698
  prompt,
174699
+ firstFrameImageUrl,
174667
174700
  ...model === "MiniMax-H3" ? { model } : {},
174668
174701
  ...region ? { region } : {},
174669
174702
  ...videoRatio ? { ratio: videoRatio } : {},
@@ -175480,7 +175513,7 @@ var init_serve_shared = __esm({
175480
175513
 
175481
175514
  // src/cli/version.ts
175482
175515
  function getCliVersion() {
175483
- return true ? "1.9.3" : pkg.version;
175516
+ return true ? "1.9.4" : pkg.version;
175484
175517
  }
175485
175518
  var init_version3 = __esm({
175486
175519
  "src/cli/version.ts"() {
@@ -143484,7 +143484,20 @@ function normalizeMiniMaxVideoRequest(input) {
143484
143484
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
143485
143485
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
143486
143486
  }
143487
- return { region, model, prompt, resolution, duration, ratio };
143487
+ let firstFrameImageUrl;
143488
+ if (input.firstFrameImageUrl !== void 0) {
143489
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
143490
+ let parsed;
143491
+ try {
143492
+ parsed = new URL(firstFrameImageUrl);
143493
+ } catch {
143494
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
143495
+ }
143496
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
143497
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
143498
+ }
143499
+ }
143500
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
143488
143501
  }
143489
143502
  function videoRequestConfig(input) {
143490
143503
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -143561,7 +143574,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
143561
143574
  headers: videoHeaders(config.apiKey),
143562
143575
  body: JSON.stringify({
143563
143576
  model: config.model,
143564
- content: [{ type: "text", text: config.prompt }],
143577
+ content: [
143578
+ { type: "text", text: config.prompt },
143579
+ ...config.firstFrameImageUrl ? [{
143580
+ type: "image_url",
143581
+ image_url: { url: config.firstFrameImageUrl },
143582
+ role: "first_frame"
143583
+ }] : []
143584
+ ],
143565
143585
  resolution: config.resolution,
143566
143586
  duration: config.duration,
143567
143587
  ratio: config.ratio
@@ -143722,10 +143742,19 @@ function parseStoredRequest(value) {
143722
143742
  const duration = value.duration;
143723
143743
  const ratio = value.ratio;
143724
143744
  const maxBytes = value.maxBytes;
143725
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143745
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143726
143746
  throw new Error("Media video job has an invalid request payload");
143727
143747
  }
143728
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
143748
+ const normalized = normalizeMiniMaxVideoRequest({
143749
+ region,
143750
+ model,
143751
+ prompt,
143752
+ resolution,
143753
+ duration,
143754
+ ratio,
143755
+ firstFrameImageUrl: value.firstFrameImageUrl
143756
+ });
143757
+ return { provider: provider2, ...normalized, maxBytes };
143729
143758
  }
143730
143759
  function mediaJobIdFromMaintenance(job) {
143731
143760
  const mediaJobId = job.payload.mediaJobId;
@@ -143737,6 +143766,7 @@ function mediaJobIdFromMaintenance(job) {
143737
143766
  function toVideoRequest(request) {
143738
143767
  return {
143739
143768
  prompt: request.prompt,
143769
+ firstFrameImageUrl: request.firstFrameImageUrl,
143740
143770
  model: request.model,
143741
143771
  region: request.region,
143742
143772
  resolution: request.resolution,
@@ -143828,6 +143858,7 @@ function queueMiniMaxVideoGeneration(input) {
143828
143858
  region: normalized.region,
143829
143859
  model: normalized.model,
143830
143860
  prompt: normalized.prompt,
143861
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
143831
143862
  resolution: normalized.resolution,
143832
143863
  duration: normalized.duration,
143833
143864
  ratio: normalized.ratio,
@@ -143409,7 +143409,20 @@ function normalizeMiniMaxVideoRequest(input) {
143409
143409
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
143410
143410
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
143411
143411
  }
143412
- return { region, model, prompt, resolution, duration, ratio };
143412
+ let firstFrameImageUrl;
143413
+ if (input.firstFrameImageUrl !== void 0) {
143414
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
143415
+ let parsed;
143416
+ try {
143417
+ parsed = new URL(firstFrameImageUrl);
143418
+ } catch {
143419
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
143420
+ }
143421
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
143422
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
143423
+ }
143424
+ }
143425
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
143413
143426
  }
143414
143427
  function videoRequestConfig(input) {
143415
143428
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -143486,7 +143499,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
143486
143499
  headers: videoHeaders(config.apiKey),
143487
143500
  body: JSON.stringify({
143488
143501
  model: config.model,
143489
- content: [{ type: "text", text: config.prompt }],
143502
+ content: [
143503
+ { type: "text", text: config.prompt },
143504
+ ...config.firstFrameImageUrl ? [{
143505
+ type: "image_url",
143506
+ image_url: { url: config.firstFrameImageUrl },
143507
+ role: "first_frame"
143508
+ }] : []
143509
+ ],
143490
143510
  resolution: config.resolution,
143491
143511
  duration: config.duration,
143492
143512
  ratio: config.ratio
@@ -143647,10 +143667,19 @@ function parseStoredRequest(value) {
143647
143667
  const duration = value.duration;
143648
143668
  const ratio = value.ratio;
143649
143669
  const maxBytes = value.maxBytes;
143650
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143670
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143651
143671
  throw new Error("Media video job has an invalid request payload");
143652
143672
  }
143653
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
143673
+ const normalized = normalizeMiniMaxVideoRequest({
143674
+ region,
143675
+ model,
143676
+ prompt,
143677
+ resolution,
143678
+ duration,
143679
+ ratio,
143680
+ firstFrameImageUrl: value.firstFrameImageUrl
143681
+ });
143682
+ return { provider: provider2, ...normalized, maxBytes };
143654
143683
  }
143655
143684
  function mediaJobIdFromMaintenance(job) {
143656
143685
  const mediaJobId = job.payload.mediaJobId;
@@ -143662,6 +143691,7 @@ function mediaJobIdFromMaintenance(job) {
143662
143691
  function toVideoRequest(request) {
143663
143692
  return {
143664
143693
  prompt: request.prompt,
143694
+ firstFrameImageUrl: request.firstFrameImageUrl,
143665
143695
  model: request.model,
143666
143696
  region: request.region,
143667
143697
  resolution: request.resolution,
@@ -143753,6 +143783,7 @@ function queueMiniMaxVideoGeneration(input) {
143753
143783
  region: normalized.region,
143754
143784
  model: normalized.model,
143755
143785
  prompt: normalized.prompt,
143786
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
143756
143787
  resolution: normalized.resolution,
143757
143788
  duration: normalized.duration,
143758
143789
  ratio: normalized.ratio,
@@ -143454,7 +143454,20 @@ function normalizeMiniMaxVideoRequest(input) {
143454
143454
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
143455
143455
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
143456
143456
  }
143457
- return { region, model, prompt, resolution, duration, ratio };
143457
+ let firstFrameImageUrl;
143458
+ if (input.firstFrameImageUrl !== void 0) {
143459
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
143460
+ let parsed;
143461
+ try {
143462
+ parsed = new URL(firstFrameImageUrl);
143463
+ } catch {
143464
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
143465
+ }
143466
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
143467
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
143468
+ }
143469
+ }
143470
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
143458
143471
  }
143459
143472
  function videoRequestConfig(input) {
143460
143473
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -143531,7 +143544,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
143531
143544
  headers: videoHeaders(config.apiKey),
143532
143545
  body: JSON.stringify({
143533
143546
  model: config.model,
143534
- content: [{ type: "text", text: config.prompt }],
143547
+ content: [
143548
+ { type: "text", text: config.prompt },
143549
+ ...config.firstFrameImageUrl ? [{
143550
+ type: "image_url",
143551
+ image_url: { url: config.firstFrameImageUrl },
143552
+ role: "first_frame"
143553
+ }] : []
143554
+ ],
143535
143555
  resolution: config.resolution,
143536
143556
  duration: config.duration,
143537
143557
  ratio: config.ratio
@@ -143692,10 +143712,19 @@ function parseStoredRequest(value) {
143692
143712
  const duration = value.duration;
143693
143713
  const ratio = value.ratio;
143694
143714
  const maxBytes = value.maxBytes;
143695
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143715
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
143696
143716
  throw new Error("Media video job has an invalid request payload");
143697
143717
  }
143698
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
143718
+ const normalized = normalizeMiniMaxVideoRequest({
143719
+ region,
143720
+ model,
143721
+ prompt,
143722
+ resolution,
143723
+ duration,
143724
+ ratio,
143725
+ firstFrameImageUrl: value.firstFrameImageUrl
143726
+ });
143727
+ return { provider: provider2, ...normalized, maxBytes };
143699
143728
  }
143700
143729
  function mediaJobIdFromMaintenance(job) {
143701
143730
  const mediaJobId = job.payload.mediaJobId;
@@ -143707,6 +143736,7 @@ function mediaJobIdFromMaintenance(job) {
143707
143736
  function toVideoRequest(request) {
143708
143737
  return {
143709
143738
  prompt: request.prompt,
143739
+ firstFrameImageUrl: request.firstFrameImageUrl,
143710
143740
  model: request.model,
143711
143741
  region: request.region,
143712
143742
  resolution: request.resolution,
@@ -143798,6 +143828,7 @@ function queueMiniMaxVideoGeneration(input) {
143798
143828
  region: normalized.region,
143799
143829
  model: normalized.model,
143800
143830
  prompt: normalized.prompt,
143831
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
143801
143832
  resolution: normalized.resolution,
143802
143833
  duration: normalized.duration,
143803
143834
  ratio: normalized.ratio,
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.9.4] - 2026-09-18
8
+
9
+ ### Added
10
+ - **MiniMax first-frame video input** -- image-to-video generation now accepts
11
+ a public HTTPS first-frame image URL through the CLI and MCP surfaces,
12
+ preserves it in durable media jobs, and submits it with the provider's
13
+ `first_frame` image role.
14
+
15
+ ### Fixed
16
+ - **First-frame URL safety** -- rejects non-HTTPS URLs and embedded credentials
17
+ before a media request is submitted or persisted.
18
+
19
+ ### Changed
20
+ - **Grok Build documentation** -- the README comparison now uses the official
21
+ Grok Build logo assets.
22
+
7
23
  ## [1.9.3] - 2026-09-14
8
24
 
9
25
  ### Fixed
package/dist/sdk.js CHANGED
@@ -145234,7 +145234,20 @@ function normalizeMiniMaxVideoRequest(input) {
145234
145234
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
145235
145235
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
145236
145236
  }
145237
- return { region, model, prompt, resolution, duration, ratio };
145237
+ let firstFrameImageUrl;
145238
+ if (input.firstFrameImageUrl !== void 0) {
145239
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
145240
+ let parsed;
145241
+ try {
145242
+ parsed = new URL(firstFrameImageUrl);
145243
+ } catch {
145244
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
145245
+ }
145246
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
145247
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
145248
+ }
145249
+ }
145250
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
145238
145251
  }
145239
145252
  function videoRequestConfig(input) {
145240
145253
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -145311,7 +145324,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
145311
145324
  headers: videoHeaders(config.apiKey),
145312
145325
  body: JSON.stringify({
145313
145326
  model: config.model,
145314
- content: [{ type: "text", text: config.prompt }],
145327
+ content: [
145328
+ { type: "text", text: config.prompt },
145329
+ ...config.firstFrameImageUrl ? [{
145330
+ type: "image_url",
145331
+ image_url: { url: config.firstFrameImageUrl },
145332
+ role: "first_frame"
145333
+ }] : []
145334
+ ],
145315
145335
  resolution: config.resolution,
145316
145336
  duration: config.duration,
145317
145337
  ratio: config.ratio
@@ -145559,10 +145579,19 @@ function parseStoredRequest(value) {
145559
145579
  const duration = value.duration;
145560
145580
  const ratio = value.ratio;
145561
145581
  const maxBytes = value.maxBytes;
145562
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
145582
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
145563
145583
  throw new Error("Media video job has an invalid request payload");
145564
145584
  }
145565
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
145585
+ const normalized = normalizeMiniMaxVideoRequest({
145586
+ region,
145587
+ model,
145588
+ prompt,
145589
+ resolution,
145590
+ duration,
145591
+ ratio,
145592
+ firstFrameImageUrl: value.firstFrameImageUrl
145593
+ });
145594
+ return { provider: provider2, ...normalized, maxBytes };
145566
145595
  }
145567
145596
  function mediaJobIdFromMaintenance(job) {
145568
145597
  const mediaJobId = job.payload.mediaJobId;
@@ -145574,6 +145603,7 @@ function mediaJobIdFromMaintenance(job) {
145574
145603
  function toVideoRequest(request) {
145575
145604
  return {
145576
145605
  prompt: request.prompt,
145606
+ firstFrameImageUrl: request.firstFrameImageUrl,
145577
145607
  model: request.model,
145578
145608
  region: request.region,
145579
145609
  resolution: request.resolution,
@@ -145665,6 +145695,7 @@ function queueMiniMaxVideoGeneration(input) {
145665
145695
  region: normalized.region,
145666
145696
  model: normalized.model,
145667
145697
  prompt: normalized.prompt,
145698
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
145668
145699
  resolution: normalized.resolution,
145669
145700
  duration: normalized.duration,
145670
145701
  ratio: normalized.ratio,
@@ -170019,7 +170050,7 @@ var MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
170019
170050
  function getMcpServerInfo() {
170020
170051
  return {
170021
170052
  name: "memorix",
170022
- version: true ? "1.9.3" : "1.0.1"
170053
+ version: true ? "1.9.4" : "1.0.1"
170023
170054
  };
170024
170055
  }
170025
170056
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -174325,6 +174356,7 @@ ${lines.join("\n")}` }] };
174325
174356
  } : {},
174326
174357
  ...mediaGenerationEnabled ? {
174327
174358
  image: z627.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
174359
+ firstFrameImageUrl: z627.string().optional().describe("Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job."),
174328
174360
  region: z627.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
174329
174361
  n: z627.number().int().min(1).max(4).optional().describe("Image output count."),
174330
174362
  ratio: z627.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
@@ -174334,7 +174366,7 @@ ${lines.join("\n")}` }] };
174334
174366
  } : {}
174335
174367
  }
174336
174368
  },
174337
- 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 }) => {
174369
+ async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, firstFrameImageUrl, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
174338
174370
  const unresolved = requireResolvedProject("manage controlled media");
174339
174371
  if (unresolved) return unresolved;
174340
174372
  const safeError4 = (error) => sanitizeCredentials(
@@ -174504,6 +174536,7 @@ ${lines.join("\n")}` }] };
174504
174536
  dataDir: projectDir2,
174505
174537
  projectId: project.id,
174506
174538
  prompt,
174539
+ firstFrameImageUrl,
174507
174540
  ...model === "MiniMax-H3" ? { model } : {},
174508
174541
  ...region ? { region } : {},
174509
174542
  ...videoRatio ? { ratio: videoRatio } : {},
@@ -145782,7 +145782,20 @@ function normalizeMiniMaxVideoRequest(input) {
145782
145782
  if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
145783
145783
  throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
145784
145784
  }
145785
- return { region, model, prompt, resolution, duration, ratio };
145785
+ let firstFrameImageUrl;
145786
+ if (input.firstFrameImageUrl !== void 0) {
145787
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
145788
+ let parsed;
145789
+ try {
145790
+ parsed = new URL(firstFrameImageUrl);
145791
+ } catch {
145792
+ throw new Error("MiniMax first-frame image must be a public HTTPS URL");
145793
+ }
145794
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
145795
+ throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
145796
+ }
145797
+ }
145798
+ return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
145786
145799
  }
145787
145800
  function videoRequestConfig(input) {
145788
145801
  const normalized = normalizeMiniMaxVideoRequest(input);
@@ -145859,7 +145872,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
145859
145872
  headers: videoHeaders(config.apiKey),
145860
145873
  body: JSON.stringify({
145861
145874
  model: config.model,
145862
- content: [{ type: "text", text: config.prompt }],
145875
+ content: [
145876
+ { type: "text", text: config.prompt },
145877
+ ...config.firstFrameImageUrl ? [{
145878
+ type: "image_url",
145879
+ image_url: { url: config.firstFrameImageUrl },
145880
+ role: "first_frame"
145881
+ }] : []
145882
+ ],
145863
145883
  resolution: config.resolution,
145864
145884
  duration: config.duration,
145865
145885
  ratio: config.ratio
@@ -146020,10 +146040,19 @@ function parseStoredRequest(value) {
146020
146040
  const duration = value.duration;
146021
146041
  const ratio = value.ratio;
146022
146042
  const maxBytes = value.maxBytes;
146023
- if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
146043
+ if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
146024
146044
  throw new Error("Media video job has an invalid request payload");
146025
146045
  }
146026
- return { provider: provider2, region, model, prompt, resolution, duration, ratio, maxBytes };
146046
+ const normalized = normalizeMiniMaxVideoRequest({
146047
+ region,
146048
+ model,
146049
+ prompt,
146050
+ resolution,
146051
+ duration,
146052
+ ratio,
146053
+ firstFrameImageUrl: value.firstFrameImageUrl
146054
+ });
146055
+ return { provider: provider2, ...normalized, maxBytes };
146027
146056
  }
146028
146057
  function mediaJobIdFromMaintenance(job) {
146029
146058
  const mediaJobId = job.payload.mediaJobId;
@@ -146035,6 +146064,7 @@ function mediaJobIdFromMaintenance(job) {
146035
146064
  function toVideoRequest(request) {
146036
146065
  return {
146037
146066
  prompt: request.prompt,
146067
+ firstFrameImageUrl: request.firstFrameImageUrl,
146038
146068
  model: request.model,
146039
146069
  region: request.region,
146040
146070
  resolution: request.resolution,
@@ -146126,6 +146156,7 @@ function queueMiniMaxVideoGeneration(input) {
146126
146156
  region: normalized.region,
146127
146157
  model: normalized.model,
146128
146158
  prompt: normalized.prompt,
146159
+ ...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
146129
146160
  resolution: normalized.resolution,
146130
146161
  duration: normalized.duration,
146131
146162
  ratio: normalized.ratio,
@@ -13,7 +13,7 @@ Memorix is a TypeScript project built around:
13
13
 
14
14
  ## Current Development Baseline
15
15
 
16
- The current release line is **1.9.3** and package metadata is kept synchronized
16
+ The current release line is **1.9.4** and package metadata is kept synchronized
17
17
  with the root package and MCP Registry manifest.
18
18
 
19
19
  Contributors should assume the following areas are part of the current release line:
package/docs/README.md CHANGED
@@ -125,7 +125,7 @@ Historical/deep-reference documents may describe older designs. If they conflict
125
125
 
126
126
  ## Current Product Line
127
127
 
128
- The current product line is **1.9.3**. Multi-device store sync is opt-in and
128
+ The current product line is **1.9.4**. Multi-device store sync is opt-in and
129
129
  keeps local SQLite canonical; existing users do not upload anything until they
130
130
  configure a relay provider explicitly.
131
131
  The authoritative acceptance contract for the current implementation is
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorix",
3
3
  "mcpName": "io.github.AVIDS2/memorix",
4
- "version": "1.9.3",
4
+ "version": "1.9.4",
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,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3"
3
+ "version": "1.9.4"
4
4
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.9.3",
4
+ "version": "1.9.4",
5
5
  "description": "Shared workspace memory for Claude Code and other AI coding agents.",
6
6
  "author": {
7
7
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Local-first project memory for CodeBuddy Code and other coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Shared local workspace memory for GitHub Copilot CLI and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "mcpServers": {
5
5
  "memorix": {
6
6
  "command": "memorix",
@@ -1,5 +1,5 @@
1
1
  name: memorix
2
- version: "1.9.3"
2
+ version: "1.9.4"
3
3
  description: Shared workspace memory bridge for Hermes Agent.
4
4
  author: AVIDS2
5
5
  license: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-omp-package",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Memorix shared workspace memory package for Oh-my-Pi.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Shared workspace memory for OpenClaw and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-pi-package",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Memorix shared workspace memory package for Pi coding agent.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/server.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "https://github.com/AVIDS2/memorix",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.9.3",
10
+ "version": "1.9.4",
11
11
  "websiteUrl": "https://mem.rglens.com",
12
12
  "icons": [
13
13
  {
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "memorix",
25
- "version": "1.9.3",
25
+ "version": "1.9.4",
26
26
  "runtimeHint": "npx",
27
27
  "packageArguments": [
28
28
  {
@@ -146,6 +146,7 @@ export default defineCommand({
146
146
  concepts: { type: 'string', description: 'Comma-separated concepts when attaching' },
147
147
  visibility: { type: 'string', description: 'Observation visibility when attaching' },
148
148
  prompt: { type: 'string', description: 'Generation prompt' },
149
+ 'first-frame-image-url': { type: 'string', description: 'Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job' },
149
150
  image: { type: 'string', description: 'Path to a reference image for image-to-image generation' },
150
151
  model: { type: 'string', description: 'Provider model' },
151
152
  provider: { type: 'string', description: 'Audio transcription provider: openai or groq' },
@@ -201,6 +202,7 @@ export default defineCommand({
201
202
  dataDir,
202
203
  projectId: project.id,
203
204
  prompt,
205
+ firstFrameImageUrl: args['first-frame-image-url'] as string | undefined,
204
206
  model: parseMiniMaxVideoModel(args.model),
205
207
  region: parseMiniMaxRegion(args.region),
206
208
  duration: parseMiniMaxVideoDuration(args.duration),
@@ -47,6 +47,7 @@ export interface GeneratedMiniMaxImages {
47
47
 
48
48
  export interface MiniMaxVideoGenerationRequest {
49
49
  prompt: string;
50
+ firstFrameImageUrl?: string;
50
51
  model?: MiniMaxVideoModel;
51
52
  region?: MiniMaxRegion;
52
53
  apiKey?: string;
@@ -162,6 +163,7 @@ export function normalizeMiniMaxVideoRequest(input: MiniMaxVideoGenerationReques
162
163
  region: MiniMaxRegion;
163
164
  model: MiniMaxVideoModel;
164
165
  prompt: string;
166
+ firstFrameImageUrl?: string;
165
167
  resolution: MiniMaxVideoResolution;
166
168
  duration: 5 | 10;
167
169
  ratio: MiniMaxVideoRatio;
@@ -178,7 +180,21 @@ export function normalizeMiniMaxVideoRequest(input: MiniMaxVideoGenerationReques
178
180
  if (ratio !== 'adaptive' && ratio !== '16:9' && ratio !== '9:16' && ratio !== '1:1') {
179
181
  throw new Error('MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1');
180
182
  }
181
- return { region, model, prompt, resolution, duration, ratio };
183
+ let firstFrameImageUrl: string | undefined;
184
+ if (input.firstFrameImageUrl !== undefined) {
185
+ firstFrameImageUrl = input.firstFrameImageUrl.trim();
186
+ let parsed: URL;
187
+ try {
188
+ parsed = new URL(firstFrameImageUrl);
189
+ } catch {
190
+ throw new Error('MiniMax first-frame image must be a public HTTPS URL');
191
+ }
192
+ if (parsed.protocol !== 'https:' || parsed.username || parsed.password
193
+ || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
194
+ throw new Error('MiniMax first-frame image must be an HTTPS URL without credentials');
195
+ }
196
+ }
197
+ return { region, model, prompt, resolution, duration, ratio, ...(firstFrameImageUrl ? { firstFrameImageUrl } : {}) };
182
198
  }
183
199
 
184
200
  function videoRequestConfig(input: MiniMaxVideoGenerationRequest): {
@@ -187,6 +203,7 @@ function videoRequestConfig(input: MiniMaxVideoGenerationRequest): {
187
203
  baseUrl: string;
188
204
  model: MiniMaxVideoModel;
189
205
  prompt: string;
206
+ firstFrameImageUrl?: string;
190
207
  resolution: MiniMaxVideoResolution;
191
208
  duration: 5 | 10;
192
209
  ratio: MiniMaxVideoRatio;
@@ -284,7 +301,14 @@ export async function createMiniMaxVideoTask(
284
301
  headers: videoHeaders(config.apiKey),
285
302
  body: JSON.stringify({
286
303
  model: config.model,
287
- content: [{ type: 'text', text: config.prompt }],
304
+ content: [
305
+ { type: 'text', text: config.prompt },
306
+ ...(config.firstFrameImageUrl ? [{
307
+ type: 'image_url',
308
+ image_url: { url: config.firstFrameImageUrl },
309
+ role: 'first_frame',
310
+ }] : []),
311
+ ],
288
312
  resolution: config.resolution,
289
313
  duration: config.duration,
290
314
  ratio: config.ratio,
@@ -32,6 +32,7 @@ interface StoredMiniMaxVideoRequest {
32
32
  region: 'global' | 'cn';
33
33
  model: 'MiniMax-H3';
34
34
  prompt: string;
35
+ firstFrameImageUrl?: string;
35
36
  resolution: '2K';
36
37
  duration: 5 | 10;
37
38
  ratio: 'adaptive' | '16:9' | '9:16' | '1:1';
@@ -93,13 +94,18 @@ function parseStoredRequest(value: Record<string, unknown>): StoredMiniMaxVideoR
93
94
  || (region !== 'global' && region !== 'cn')
94
95
  || model !== 'MiniMax-H3'
95
96
  || typeof prompt !== 'string'
97
+ || (value.firstFrameImageUrl !== undefined && typeof value.firstFrameImageUrl !== 'string')
96
98
  || resolution !== '2K'
97
99
  || (duration !== 5 && duration !== 10)
98
100
  || (ratio !== 'adaptive' && ratio !== '16:9' && ratio !== '9:16' && ratio !== '1:1')
99
101
  || typeof maxBytes !== 'number' || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
100
102
  throw new Error('Media video job has an invalid request payload');
101
103
  }
102
- return { provider, region, model, prompt, resolution, duration, ratio, maxBytes };
104
+ const normalized = normalizeMiniMaxVideoRequest({
105
+ region, model, prompt, resolution, duration, ratio,
106
+ firstFrameImageUrl: value.firstFrameImageUrl as string | undefined,
107
+ });
108
+ return { provider, ...normalized, maxBytes };
103
109
  }
104
110
 
105
111
  function mediaJobIdFromMaintenance(job: MaintenanceJob): string {
@@ -113,6 +119,7 @@ function mediaJobIdFromMaintenance(job: MaintenanceJob): string {
113
119
  function toVideoRequest(request: StoredMiniMaxVideoRequest): MiniMaxVideoGenerationRequest {
114
120
  return {
115
121
  prompt: request.prompt,
122
+ firstFrameImageUrl: request.firstFrameImageUrl,
116
123
  model: request.model,
117
124
  region: request.region,
118
125
  resolution: request.resolution,
@@ -233,6 +240,7 @@ export function queueMiniMaxVideoGeneration(input: QueueMiniMaxVideoInput): Queu
233
240
  region: normalized.region,
234
241
  model: normalized.model,
235
242
  prompt: normalized.prompt,
243
+ ...(normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {}),
236
244
  resolution: normalized.resolution,
237
245
  duration: normalized.duration,
238
246
  ratio: normalized.ratio,
package/src/server.ts CHANGED
@@ -5208,6 +5208,7 @@ export async function createMemorixServer(
5208
5208
  } : {}),
5209
5209
  ...(mediaGenerationEnabled ? {
5210
5210
  image: z.string().optional().describe('Base64-encoded reference image for image-to-image generation.'),
5211
+ firstFrameImageUrl: z.string().optional().describe('Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job.'),
5211
5212
  region: z.enum(['global', 'cn']).optional().describe('MiniMax deployment region.'),
5212
5213
  n: z.number().int().min(1).max(4).optional().describe('Image output count.'),
5213
5214
  ratio: z.enum(['adaptive', '1:1', '16:9', '4:3', '3:2', '2:3', '3:4', '9:16', '21:9']).optional().describe('Image or video aspect ratio.'),
@@ -5217,7 +5218,7 @@ export async function createMemorixServer(
5217
5218
  } : {}),
5218
5219
  },
5219
5220
  },
5220
- async ({ action, path: assetPath, assetId, jobId, kind, limit, title, narrative, prompt, image, model, provider, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
5221
+ async ({ action, path: assetPath, assetId, jobId, kind, limit, title, narrative, prompt, image, firstFrameImageUrl, model, provider, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
5221
5222
  const unresolved = requireResolvedProject('manage controlled media');
5222
5223
  if (unresolved) return unresolved;
5223
5224
  const safeError = (error: unknown) => sanitizeCredentials(
@@ -5402,6 +5403,7 @@ export async function createMemorixServer(
5402
5403
  dataDir: projectDir,
5403
5404
  projectId: project.id,
5404
5405
  prompt,
5406
+ firstFrameImageUrl,
5405
5407
  ...(model === 'MiniMax-H3' ? { model } : {}),
5406
5408
  ...(region ? { region } : {}),
5407
5409
  ...(videoRatio ? { ratio: videoRatio } : {}),