memorix 1.3.4 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/CLAUDE.md +9 -9
- package/README.md +7 -2
- package/README.zh-CN.md +6 -2
- package/dist/cli/index.js +53 -23
- package/dist/index.js +53 -23
- package/dist/maintenance-runner.js +50 -21
- package/dist/media-video-runner.js +50 -21
- package/dist/memcode/index.js +53 -21
- package/dist/memcode-runtime/CHANGELOG.md +21 -0
- package/dist/sdk.js +52 -22
- package/dist/vector-backfill-runner.js +50 -21
- package/docs/1.3.3-MULTIMODAL-MEDIA-AND-MCP-COMPAT.md +13 -13
- package/docs/API_REFERENCE.md +1 -1
- package/docs/KNOWN_ISSUES_AND_ROADMAP.md +52 -128
- package/package.json +5 -2
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/codegraph/current-facts.ts +1 -0
- package/docs/dev-log/progress.txt +0 -388
|
@@ -31308,7 +31308,7 @@ var init_models_generated = __esm({
|
|
|
31308
31308
|
provider: "minimax",
|
|
31309
31309
|
baseUrl: "https://api.minimax.io/anthropic",
|
|
31310
31310
|
reasoning: true,
|
|
31311
|
-
input: ["text", "image"],
|
|
31311
|
+
input: ["text", "image", "video"],
|
|
31312
31312
|
cost: {
|
|
31313
31313
|
input: 0.3,
|
|
31314
31314
|
output: 1.2,
|
|
@@ -31361,7 +31361,7 @@ var init_models_generated = __esm({
|
|
|
31361
31361
|
provider: "minimax-cn",
|
|
31362
31362
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
|
31363
31363
|
reasoning: true,
|
|
31364
|
-
input: ["text", "image"],
|
|
31364
|
+
input: ["text", "image", "video"],
|
|
31365
31365
|
cost: {
|
|
31366
31366
|
input: 0.3,
|
|
31367
31367
|
output: 1.2,
|
|
@@ -50636,11 +50636,11 @@ var init_simple_options = __esm({
|
|
|
50636
50636
|
});
|
|
50637
50637
|
|
|
50638
50638
|
// packages/ai/dist/providers/transform-messages.js
|
|
50639
|
-
function
|
|
50639
|
+
function replaceMediaWithPlaceholder(content, dropType, placeholder) {
|
|
50640
50640
|
const result = [];
|
|
50641
50641
|
let previousWasPlaceholder = false;
|
|
50642
50642
|
for (const block of content) {
|
|
50643
|
-
if (block.type ===
|
|
50643
|
+
if (block.type === dropType) {
|
|
50644
50644
|
if (!previousWasPlaceholder) {
|
|
50645
50645
|
result.push({ type: "text", text: placeholder });
|
|
50646
50646
|
}
|
|
@@ -50648,33 +50648,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
|
|
|
50648
50648
|
continue;
|
|
50649
50649
|
}
|
|
50650
50650
|
result.push(block);
|
|
50651
|
-
previousWasPlaceholder = block.text === placeholder;
|
|
50651
|
+
previousWasPlaceholder = block.type === "text" && block.text === placeholder;
|
|
50652
50652
|
}
|
|
50653
50653
|
return result;
|
|
50654
50654
|
}
|
|
50655
|
-
function
|
|
50656
|
-
|
|
50655
|
+
function downgradeUnsupportedMedia(messages, model) {
|
|
50656
|
+
const supportsImage = model.input.includes("image");
|
|
50657
|
+
const supportsVideo = model.input.includes("video");
|
|
50658
|
+
if (supportsImage && supportsVideo) {
|
|
50657
50659
|
return messages;
|
|
50658
50660
|
}
|
|
50659
50661
|
return messages.map((msg) => {
|
|
50660
50662
|
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
50661
|
-
|
|
50662
|
-
|
|
50663
|
-
content
|
|
50664
|
-
|
|
50663
|
+
let content = msg.content;
|
|
50664
|
+
if (!supportsImage)
|
|
50665
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
|
|
50666
|
+
if (!supportsVideo)
|
|
50667
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
|
|
50668
|
+
return { ...msg, content };
|
|
50665
50669
|
}
|
|
50666
50670
|
if (msg.role === "toolResult") {
|
|
50667
|
-
|
|
50668
|
-
|
|
50669
|
-
content
|
|
50670
|
-
|
|
50671
|
+
let content = msg.content;
|
|
50672
|
+
if (!supportsImage)
|
|
50673
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
|
|
50674
|
+
if (!supportsVideo)
|
|
50675
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
|
|
50676
|
+
return { ...msg, content };
|
|
50671
50677
|
}
|
|
50672
50678
|
return msg;
|
|
50673
50679
|
});
|
|
50674
50680
|
}
|
|
50675
50681
|
function transformMessages(messages, model, normalizeToolCallId2) {
|
|
50676
50682
|
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
50677
|
-
const imageAwareMessages =
|
|
50683
|
+
const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
|
|
50678
50684
|
const transformed = imageAwareMessages.map((msg) => {
|
|
50679
50685
|
if (msg.role === "user") {
|
|
50680
50686
|
return msg;
|
|
@@ -50786,13 +50792,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
|
|
|
50786
50792
|
insertSyntheticToolResults();
|
|
50787
50793
|
return result;
|
|
50788
50794
|
}
|
|
50789
|
-
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
|
|
50795
|
+
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
|
|
50790
50796
|
var init_transform_messages = __esm({
|
|
50791
50797
|
"packages/ai/dist/providers/transform-messages.js"() {
|
|
50792
50798
|
"use strict";
|
|
50793
50799
|
init_esm_shims();
|
|
50794
50800
|
NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
50795
50801
|
NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
50802
|
+
NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
50803
|
+
NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
|
|
50796
50804
|
}
|
|
50797
50805
|
});
|
|
50798
50806
|
|
|
@@ -50823,8 +50831,8 @@ function getCacheControl(model, cacheRetention) {
|
|
|
50823
50831
|
};
|
|
50824
50832
|
}
|
|
50825
50833
|
function convertContentBlocks(content) {
|
|
50826
|
-
const
|
|
50827
|
-
if (!
|
|
50834
|
+
const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
|
|
50835
|
+
if (!hasMedia) {
|
|
50828
50836
|
return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
|
|
50829
50837
|
}
|
|
50830
50838
|
const blocks = content.map((block) => {
|
|
@@ -50834,6 +50842,16 @@ function convertContentBlocks(content) {
|
|
|
50834
50842
|
text: sanitizeSurrogates(block.text)
|
|
50835
50843
|
};
|
|
50836
50844
|
}
|
|
50845
|
+
if (block.type === "video") {
|
|
50846
|
+
return {
|
|
50847
|
+
type: "video",
|
|
50848
|
+
source: {
|
|
50849
|
+
type: "base64",
|
|
50850
|
+
media_type: block.mimeType,
|
|
50851
|
+
data: block.data
|
|
50852
|
+
}
|
|
50853
|
+
};
|
|
50854
|
+
}
|
|
50837
50855
|
return {
|
|
50838
50856
|
type: "image",
|
|
50839
50857
|
source: {
|
|
@@ -50847,7 +50865,7 @@ function convertContentBlocks(content) {
|
|
|
50847
50865
|
if (!hasText) {
|
|
50848
50866
|
blocks.unshift({
|
|
50849
50867
|
type: "text",
|
|
50850
|
-
text: "(see attached
|
|
50868
|
+
text: "(see attached media)"
|
|
50851
50869
|
});
|
|
50852
50870
|
}
|
|
50853
50871
|
return blocks;
|
|
@@ -51197,6 +51215,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51197
51215
|
type: "text",
|
|
51198
51216
|
text: sanitizeSurrogates(item.text)
|
|
51199
51217
|
};
|
|
51218
|
+
} else if (item.type === "video") {
|
|
51219
|
+
return {
|
|
51220
|
+
type: "video",
|
|
51221
|
+
source: {
|
|
51222
|
+
type: "base64",
|
|
51223
|
+
media_type: item.mimeType,
|
|
51224
|
+
data: item.data
|
|
51225
|
+
}
|
|
51226
|
+
};
|
|
51200
51227
|
} else {
|
|
51201
51228
|
return {
|
|
51202
51229
|
type: "image",
|
|
@@ -51277,6 +51304,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51277
51304
|
toolResults.push({
|
|
51278
51305
|
type: "tool_result",
|
|
51279
51306
|
tool_use_id: msg.toolCallId,
|
|
51307
|
+
// MiniMax's Anthropic-compatible API accepts video in tool results;
|
|
51308
|
+
// the SDK's ToolResultBlockParam.content type predates video support.
|
|
51280
51309
|
content: convertContentBlocks(msg.content),
|
|
51281
51310
|
is_error: msg.isError
|
|
51282
51311
|
});
|
|
@@ -51303,7 +51332,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51303
51332
|
if (lastMessage.role === "user") {
|
|
51304
51333
|
if (Array.isArray(lastMessage.content)) {
|
|
51305
51334
|
const lastBlock = lastMessage.content[lastMessage.content.length - 1];
|
|
51306
|
-
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
|
|
51335
|
+
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
|
|
51307
51336
|
lastBlock.cache_control = cacheControl;
|
|
51308
51337
|
}
|
|
51309
51338
|
} else if (typeof lastMessage.content === "string") {
|
|
@@ -31281,7 +31281,7 @@ var init_models_generated = __esm({
|
|
|
31281
31281
|
provider: "minimax",
|
|
31282
31282
|
baseUrl: "https://api.minimax.io/anthropic",
|
|
31283
31283
|
reasoning: true,
|
|
31284
|
-
input: ["text", "image"],
|
|
31284
|
+
input: ["text", "image", "video"],
|
|
31285
31285
|
cost: {
|
|
31286
31286
|
input: 0.3,
|
|
31287
31287
|
output: 1.2,
|
|
@@ -31334,7 +31334,7 @@ var init_models_generated = __esm({
|
|
|
31334
31334
|
provider: "minimax-cn",
|
|
31335
31335
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
|
31336
31336
|
reasoning: true,
|
|
31337
|
-
input: ["text", "image"],
|
|
31337
|
+
input: ["text", "image", "video"],
|
|
31338
31338
|
cost: {
|
|
31339
31339
|
input: 0.3,
|
|
31340
31340
|
output: 1.2,
|
|
@@ -50609,11 +50609,11 @@ var init_simple_options = __esm({
|
|
|
50609
50609
|
});
|
|
50610
50610
|
|
|
50611
50611
|
// packages/ai/dist/providers/transform-messages.js
|
|
50612
|
-
function
|
|
50612
|
+
function replaceMediaWithPlaceholder(content, dropType, placeholder) {
|
|
50613
50613
|
const result = [];
|
|
50614
50614
|
let previousWasPlaceholder = false;
|
|
50615
50615
|
for (const block of content) {
|
|
50616
|
-
if (block.type ===
|
|
50616
|
+
if (block.type === dropType) {
|
|
50617
50617
|
if (!previousWasPlaceholder) {
|
|
50618
50618
|
result.push({ type: "text", text: placeholder });
|
|
50619
50619
|
}
|
|
@@ -50621,33 +50621,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
|
|
|
50621
50621
|
continue;
|
|
50622
50622
|
}
|
|
50623
50623
|
result.push(block);
|
|
50624
|
-
previousWasPlaceholder = block.text === placeholder;
|
|
50624
|
+
previousWasPlaceholder = block.type === "text" && block.text === placeholder;
|
|
50625
50625
|
}
|
|
50626
50626
|
return result;
|
|
50627
50627
|
}
|
|
50628
|
-
function
|
|
50629
|
-
|
|
50628
|
+
function downgradeUnsupportedMedia(messages, model) {
|
|
50629
|
+
const supportsImage = model.input.includes("image");
|
|
50630
|
+
const supportsVideo = model.input.includes("video");
|
|
50631
|
+
if (supportsImage && supportsVideo) {
|
|
50630
50632
|
return messages;
|
|
50631
50633
|
}
|
|
50632
50634
|
return messages.map((msg) => {
|
|
50633
50635
|
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
50634
|
-
|
|
50635
|
-
|
|
50636
|
-
content
|
|
50637
|
-
|
|
50636
|
+
let content = msg.content;
|
|
50637
|
+
if (!supportsImage)
|
|
50638
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
|
|
50639
|
+
if (!supportsVideo)
|
|
50640
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
|
|
50641
|
+
return { ...msg, content };
|
|
50638
50642
|
}
|
|
50639
50643
|
if (msg.role === "toolResult") {
|
|
50640
|
-
|
|
50641
|
-
|
|
50642
|
-
content
|
|
50643
|
-
|
|
50644
|
+
let content = msg.content;
|
|
50645
|
+
if (!supportsImage)
|
|
50646
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
|
|
50647
|
+
if (!supportsVideo)
|
|
50648
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
|
|
50649
|
+
return { ...msg, content };
|
|
50644
50650
|
}
|
|
50645
50651
|
return msg;
|
|
50646
50652
|
});
|
|
50647
50653
|
}
|
|
50648
50654
|
function transformMessages(messages, model, normalizeToolCallId2) {
|
|
50649
50655
|
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
50650
|
-
const imageAwareMessages =
|
|
50656
|
+
const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
|
|
50651
50657
|
const transformed = imageAwareMessages.map((msg) => {
|
|
50652
50658
|
if (msg.role === "user") {
|
|
50653
50659
|
return msg;
|
|
@@ -50759,13 +50765,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
|
|
|
50759
50765
|
insertSyntheticToolResults();
|
|
50760
50766
|
return result;
|
|
50761
50767
|
}
|
|
50762
|
-
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
|
|
50768
|
+
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
|
|
50763
50769
|
var init_transform_messages = __esm({
|
|
50764
50770
|
"packages/ai/dist/providers/transform-messages.js"() {
|
|
50765
50771
|
"use strict";
|
|
50766
50772
|
init_esm_shims();
|
|
50767
50773
|
NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
50768
50774
|
NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
50775
|
+
NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
50776
|
+
NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
|
|
50769
50777
|
}
|
|
50770
50778
|
});
|
|
50771
50779
|
|
|
@@ -50796,8 +50804,8 @@ function getCacheControl(model, cacheRetention) {
|
|
|
50796
50804
|
};
|
|
50797
50805
|
}
|
|
50798
50806
|
function convertContentBlocks(content) {
|
|
50799
|
-
const
|
|
50800
|
-
if (!
|
|
50807
|
+
const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
|
|
50808
|
+
if (!hasMedia) {
|
|
50801
50809
|
return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
|
|
50802
50810
|
}
|
|
50803
50811
|
const blocks = content.map((block) => {
|
|
@@ -50807,6 +50815,16 @@ function convertContentBlocks(content) {
|
|
|
50807
50815
|
text: sanitizeSurrogates(block.text)
|
|
50808
50816
|
};
|
|
50809
50817
|
}
|
|
50818
|
+
if (block.type === "video") {
|
|
50819
|
+
return {
|
|
50820
|
+
type: "video",
|
|
50821
|
+
source: {
|
|
50822
|
+
type: "base64",
|
|
50823
|
+
media_type: block.mimeType,
|
|
50824
|
+
data: block.data
|
|
50825
|
+
}
|
|
50826
|
+
};
|
|
50827
|
+
}
|
|
50810
50828
|
return {
|
|
50811
50829
|
type: "image",
|
|
50812
50830
|
source: {
|
|
@@ -50820,7 +50838,7 @@ function convertContentBlocks(content) {
|
|
|
50820
50838
|
if (!hasText) {
|
|
50821
50839
|
blocks.unshift({
|
|
50822
50840
|
type: "text",
|
|
50823
|
-
text: "(see attached
|
|
50841
|
+
text: "(see attached media)"
|
|
50824
50842
|
});
|
|
50825
50843
|
}
|
|
50826
50844
|
return blocks;
|
|
@@ -51170,6 +51188,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51170
51188
|
type: "text",
|
|
51171
51189
|
text: sanitizeSurrogates(item.text)
|
|
51172
51190
|
};
|
|
51191
|
+
} else if (item.type === "video") {
|
|
51192
|
+
return {
|
|
51193
|
+
type: "video",
|
|
51194
|
+
source: {
|
|
51195
|
+
type: "base64",
|
|
51196
|
+
media_type: item.mimeType,
|
|
51197
|
+
data: item.data
|
|
51198
|
+
}
|
|
51199
|
+
};
|
|
51173
51200
|
} else {
|
|
51174
51201
|
return {
|
|
51175
51202
|
type: "image",
|
|
@@ -51250,6 +51277,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51250
51277
|
toolResults.push({
|
|
51251
51278
|
type: "tool_result",
|
|
51252
51279
|
tool_use_id: msg.toolCallId,
|
|
51280
|
+
// MiniMax's Anthropic-compatible API accepts video in tool results;
|
|
51281
|
+
// the SDK's ToolResultBlockParam.content type predates video support.
|
|
51253
51282
|
content: convertContentBlocks(msg.content),
|
|
51254
51283
|
is_error: msg.isError
|
|
51255
51284
|
});
|
|
@@ -51276,7 +51305,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
51276
51305
|
if (lastMessage.role === "user") {
|
|
51277
51306
|
if (Array.isArray(lastMessage.content)) {
|
|
51278
51307
|
const lastBlock = lastMessage.content[lastMessage.content.length - 1];
|
|
51279
|
-
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
|
|
51308
|
+
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
|
|
51280
51309
|
lastBlock.cache_control = cacheControl;
|
|
51281
51310
|
}
|
|
51282
51311
|
} else if (typeof lastMessage.content === "string") {
|
package/dist/memcode/index.js
CHANGED
|
@@ -74127,7 +74127,7 @@ var init_models_generated = __esm({
|
|
|
74127
74127
|
provider: "minimax",
|
|
74128
74128
|
baseUrl: "https://api.minimax.io/anthropic",
|
|
74129
74129
|
reasoning: true,
|
|
74130
|
-
input: ["text", "image"],
|
|
74130
|
+
input: ["text", "image", "video"],
|
|
74131
74131
|
cost: {
|
|
74132
74132
|
input: 0.3,
|
|
74133
74133
|
output: 1.2,
|
|
@@ -74180,7 +74180,7 @@ var init_models_generated = __esm({
|
|
|
74180
74180
|
provider: "minimax-cn",
|
|
74181
74181
|
baseUrl: "https://api.minimaxi.com/anthropic",
|
|
74182
74182
|
reasoning: true,
|
|
74183
|
-
input: ["text", "image"],
|
|
74183
|
+
input: ["text", "image", "video"],
|
|
74184
74184
|
cost: {
|
|
74185
74185
|
input: 0.3,
|
|
74186
74186
|
output: 1.2,
|
|
@@ -93464,11 +93464,11 @@ var init_simple_options = __esm({
|
|
|
93464
93464
|
});
|
|
93465
93465
|
|
|
93466
93466
|
// packages/ai/dist/providers/transform-messages.js
|
|
93467
|
-
function
|
|
93467
|
+
function replaceMediaWithPlaceholder(content, dropType, placeholder) {
|
|
93468
93468
|
const result = [];
|
|
93469
93469
|
let previousWasPlaceholder = false;
|
|
93470
93470
|
for (const block2 of content) {
|
|
93471
|
-
if (block2.type ===
|
|
93471
|
+
if (block2.type === dropType) {
|
|
93472
93472
|
if (!previousWasPlaceholder) {
|
|
93473
93473
|
result.push({ type: "text", text: placeholder });
|
|
93474
93474
|
}
|
|
@@ -93476,33 +93476,39 @@ function replaceImagesWithPlaceholder(content, placeholder) {
|
|
|
93476
93476
|
continue;
|
|
93477
93477
|
}
|
|
93478
93478
|
result.push(block2);
|
|
93479
|
-
previousWasPlaceholder = block2.text === placeholder;
|
|
93479
|
+
previousWasPlaceholder = block2.type === "text" && block2.text === placeholder;
|
|
93480
93480
|
}
|
|
93481
93481
|
return result;
|
|
93482
93482
|
}
|
|
93483
|
-
function
|
|
93484
|
-
|
|
93483
|
+
function downgradeUnsupportedMedia(messages, model) {
|
|
93484
|
+
const supportsImage = model.input.includes("image");
|
|
93485
|
+
const supportsVideo = model.input.includes("video");
|
|
93486
|
+
if (supportsImage && supportsVideo) {
|
|
93485
93487
|
return messages;
|
|
93486
93488
|
}
|
|
93487
93489
|
return messages.map((msg) => {
|
|
93488
93490
|
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
93489
|
-
|
|
93490
|
-
|
|
93491
|
-
content
|
|
93492
|
-
|
|
93491
|
+
let content = msg.content;
|
|
93492
|
+
if (!supportsImage)
|
|
93493
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_USER_IMAGE_PLACEHOLDER);
|
|
93494
|
+
if (!supportsVideo)
|
|
93495
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_USER_VIDEO_PLACEHOLDER);
|
|
93496
|
+
return { ...msg, content };
|
|
93493
93497
|
}
|
|
93494
93498
|
if (msg.role === "toolResult") {
|
|
93495
|
-
|
|
93496
|
-
|
|
93497
|
-
content
|
|
93498
|
-
|
|
93499
|
+
let content = msg.content;
|
|
93500
|
+
if (!supportsImage)
|
|
93501
|
+
content = replaceMediaWithPlaceholder(content, "image", NON_VISION_TOOL_IMAGE_PLACEHOLDER);
|
|
93502
|
+
if (!supportsVideo)
|
|
93503
|
+
content = replaceMediaWithPlaceholder(content, "video", NON_VISION_TOOL_VIDEO_PLACEHOLDER);
|
|
93504
|
+
return { ...msg, content };
|
|
93499
93505
|
}
|
|
93500
93506
|
return msg;
|
|
93501
93507
|
});
|
|
93502
93508
|
}
|
|
93503
93509
|
function transformMessages(messages, model, normalizeToolCallId2) {
|
|
93504
93510
|
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
93505
|
-
const imageAwareMessages =
|
|
93511
|
+
const imageAwareMessages = downgradeUnsupportedMedia(messages, model);
|
|
93506
93512
|
const transformed = imageAwareMessages.map((msg) => {
|
|
93507
93513
|
if (msg.role === "user") {
|
|
93508
93514
|
return msg;
|
|
@@ -93614,13 +93620,15 @@ function transformMessages(messages, model, normalizeToolCallId2) {
|
|
|
93614
93620
|
insertSyntheticToolResults();
|
|
93615
93621
|
return result;
|
|
93616
93622
|
}
|
|
93617
|
-
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
|
|
93623
|
+
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER, NON_VISION_USER_VIDEO_PLACEHOLDER, NON_VISION_TOOL_VIDEO_PLACEHOLDER;
|
|
93618
93624
|
var init_transform_messages = __esm({
|
|
93619
93625
|
"packages/ai/dist/providers/transform-messages.js"() {
|
|
93620
93626
|
"use strict";
|
|
93621
93627
|
init_esm_shims();
|
|
93622
93628
|
NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
93623
93629
|
NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
93630
|
+
NON_VISION_USER_VIDEO_PLACEHOLDER = "(video omitted: model does not support video)";
|
|
93631
|
+
NON_VISION_TOOL_VIDEO_PLACEHOLDER = "(tool video omitted: model does not support video)";
|
|
93624
93632
|
}
|
|
93625
93633
|
});
|
|
93626
93634
|
|
|
@@ -93651,8 +93659,8 @@ function getCacheControl(model, cacheRetention) {
|
|
|
93651
93659
|
};
|
|
93652
93660
|
}
|
|
93653
93661
|
function convertContentBlocks(content) {
|
|
93654
|
-
const
|
|
93655
|
-
if (!
|
|
93662
|
+
const hasMedia = content.some((c) => c.type === "image" || c.type === "video");
|
|
93663
|
+
if (!hasMedia) {
|
|
93656
93664
|
return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
|
|
93657
93665
|
}
|
|
93658
93666
|
const blocks = content.map((block2) => {
|
|
@@ -93662,6 +93670,16 @@ function convertContentBlocks(content) {
|
|
|
93662
93670
|
text: sanitizeSurrogates(block2.text)
|
|
93663
93671
|
};
|
|
93664
93672
|
}
|
|
93673
|
+
if (block2.type === "video") {
|
|
93674
|
+
return {
|
|
93675
|
+
type: "video",
|
|
93676
|
+
source: {
|
|
93677
|
+
type: "base64",
|
|
93678
|
+
media_type: block2.mimeType,
|
|
93679
|
+
data: block2.data
|
|
93680
|
+
}
|
|
93681
|
+
};
|
|
93682
|
+
}
|
|
93665
93683
|
return {
|
|
93666
93684
|
type: "image",
|
|
93667
93685
|
source: {
|
|
@@ -93675,7 +93693,7 @@ function convertContentBlocks(content) {
|
|
|
93675
93693
|
if (!hasText) {
|
|
93676
93694
|
blocks.unshift({
|
|
93677
93695
|
type: "text",
|
|
93678
|
-
text: "(see attached
|
|
93696
|
+
text: "(see attached media)"
|
|
93679
93697
|
});
|
|
93680
93698
|
}
|
|
93681
93699
|
return blocks;
|
|
@@ -94025,6 +94043,15 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
94025
94043
|
type: "text",
|
|
94026
94044
|
text: sanitizeSurrogates(item.text)
|
|
94027
94045
|
};
|
|
94046
|
+
} else if (item.type === "video") {
|
|
94047
|
+
return {
|
|
94048
|
+
type: "video",
|
|
94049
|
+
source: {
|
|
94050
|
+
type: "base64",
|
|
94051
|
+
media_type: item.mimeType,
|
|
94052
|
+
data: item.data
|
|
94053
|
+
}
|
|
94054
|
+
};
|
|
94028
94055
|
} else {
|
|
94029
94056
|
return {
|
|
94030
94057
|
type: "image",
|
|
@@ -94105,6 +94132,8 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
94105
94132
|
toolResults.push({
|
|
94106
94133
|
type: "tool_result",
|
|
94107
94134
|
tool_use_id: msg.toolCallId,
|
|
94135
|
+
// MiniMax's Anthropic-compatible API accepts video in tool results;
|
|
94136
|
+
// the SDK's ToolResultBlockParam.content type predates video support.
|
|
94108
94137
|
content: convertContentBlocks(msg.content),
|
|
94109
94138
|
is_error: msg.isError
|
|
94110
94139
|
});
|
|
@@ -94131,7 +94160,7 @@ function convertMessages(messages, model, isOAuthToken2, cacheControl, allowEmpt
|
|
|
94131
94160
|
if (lastMessage.role === "user") {
|
|
94132
94161
|
if (Array.isArray(lastMessage.content)) {
|
|
94133
94162
|
const lastBlock = lastMessage.content[lastMessage.content.length - 1];
|
|
94134
|
-
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "tool_result")) {
|
|
94163
|
+
if (lastBlock && (lastBlock.type === "text" || lastBlock.type === "image" || lastBlock.type === "video" || lastBlock.type === "tool_result")) {
|
|
94135
94164
|
lastBlock.cache_control = cacheControl;
|
|
94136
94165
|
}
|
|
94137
94166
|
} else if (typeof lastMessage.content === "string") {
|
|
@@ -233195,6 +233224,9 @@ function contentToText(content) {
|
|
|
233195
233224
|
if (block2.type === "text") {
|
|
233196
233225
|
return block2.text;
|
|
233197
233226
|
}
|
|
233227
|
+
if (block2.type === "video") {
|
|
233228
|
+
return `[video:${block2.mimeType}:${block2.data.length}]`;
|
|
233229
|
+
}
|
|
233198
233230
|
return `[image:${block2.mimeType}:${block2.data.length}]`;
|
|
233199
233231
|
}).join("\n");
|
|
233200
233232
|
}
|
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.4.1] - 2026-08-03
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **MiniMax M3 video input** -- The bundled `@memorix/ai` provider layer now advertises and routes MiniMax M3 video content through MiniMax's Anthropic-compatible API. Base64 video is covered by focused request-shape tests, and image-only models still receive a clear text fallback instead of an invalid video block. Contributed by [@octo-patch](https://github.com/octo-patch) in #153.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Maintained product roadmap** -- Replaced the stale version-by-version roadmap with current product boundaries, operating constraints, and public directions. Release facts now live in this changelog and active maintainer work lives in `ACTIVE_WORK.md`. Contributed by [@FBISiri](https://github.com/FBISiri) in #140.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- **Deterministic provider tests** -- `@memorix/ai` unit tests no longer discover local API keys or Pi OAuth credentials and unexpectedly call paid, changing provider endpoints. Routine tests are offline by default; deliberate live validation requires `MEMORIX_AI_LIVE_TESTS=1` plus the required credentials.
|
|
15
|
+
- **Stable model metadata assertion** -- Removed a test-only assumption that OpenRouter will permanently list `moonshotai/kimi-k2.6:free`; the bundled catalog snapshot no longer contains that route, while coverage remains for the supported Kimi K2.6 compatibility metadata.
|
|
16
|
+
|
|
17
|
+
## [1.4.0] - 2026-08-02
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- **Stable multimodal release** -- Promoted the controlled media lifecycle, explicit MiniMax image/video generation, and honest multimodal embedding foundation introduced in 1.3.3 to the stable line after the 1.3.4 Windows, MCP binding, cancellation, cleanup, configuration-migration, and fresh-package hardening work.
|
|
21
|
+
|
|
22
|
+
### Verified
|
|
23
|
+
- **Release evidence** -- Full local regression, fresh npm-package MCP smoke, GitHub Actions on Windows and Ubuntu, Docker control-plane startup, native SQLite compatibility, npm provenance publication, and official MCP Registry publication all passed before this release.
|
|
24
|
+
- **Release boundary** -- “Stable” means no known release blocker after those gates. It does not claim that any software is mathematically free of future defects.
|
|
25
|
+
|
|
5
26
|
## [1.3.4] - 2026-08-02
|
|
6
27
|
|
|
7
28
|
### Fixed
|